diff --git a/.gitignore b/.gitignore index ef35f6b5..42f09440 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# apple +.DS_Store + # cmake CMakeFiles/ .cmake/ diff --git a/CMakeLists.txt b/CMakeLists.txt index c010c3d2..46da9008 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ option (NRI_ENABLE_NVTX_SUPPORT "Annotations for NVIDIA Nsight Systems" OFF) # Options: backends option (NRI_ENABLE_NONE_SUPPORT "Enable NONE backend" ON) +option (NRI_ENABLE_VK_SUPPORT "Enable VULKAN backend" ON) +option (NRI_ENABLE_METAL_SUPPORT "Enable METAL backend" ON) option (NRI_ENABLE_D3D11_SUPPORT "Enable D3D11 backend" ON) option (NRI_ENABLE_D3D12_SUPPORT "Enable D3D12 backend" ON) option (NRI_ENABLE_VK_SUPPORT "Enable VULKAN backend" ON) @@ -233,6 +235,25 @@ if (WIN32 AND NRI_ENABLE_D3D12_SUPPORT) endif () endif () +# METAL +if (NRI_ENABLE_METAL_SUPPORT AND APPLE) + message ("NRI adding backend: METAL") + set (COMPILE_DEFINITIONS ${COMPILE_DEFINITIONS} NRI_USE_MTL=1) + file (GLOB MTL_SOURCE "Source/Metal/*.cpp" "Source/Metal/*.mm" "Source/Metal/*.h" "Source/Metal/*.hpp" ) + source_group ("" FILES ${MTL_SOURCE}) + add_library (NRI_MTL STATIC ${MTL_SOURCE}) + target_link_libraries(NRI_MTL + "-framework Metal" + "-framework MetalKit" + "-framework AppKit" + "-framework Foundation" + "-framework IOKit" + "-framework QuartzCore" + ) + target_include_directories (NRI_MTL PRIVATE "Include" "Source/Shared" "External") + target_compile_definitions (NRI_MTL PRIVATE ${COMPILE_DEFINITIONS}) +endif() + # VK if (NRI_ENABLE_VK_SUPPORT) message ("NRI adding backend: VK") @@ -301,8 +322,14 @@ file (GLOB NRI_EXTENSIONS "Include/Extensions/*.h" "Include/Extensions/*.hpp") source_group ("Include/Extensions" FILES ${NRI_EXTENSIONS}) file (GLOB NRI_SOURCE "Source/Creation/*.cpp" "Source/Creation/*.h") +if (NRI_ENABLE_METAL_SUPPORT) + file (GLOB MTL_SOURCE "Source/Creation/*.mm") + list (APPEND NRI_SOURCE ${MTL_SOURCE}) +endif() source_group ("Sources" FILES ${NRI_SOURCE}) + + file (GLOB NRI_RESOURCES "Resources/*") source_group ("Resources" FILES ${NRI_RESOURCES}) @@ -342,6 +369,9 @@ endif () if (NRI_ENABLE_VK_SUPPORT) target_link_libraries (${PROJECT_NAME} PRIVATE NRI_VK) endif () +if (NRI_ENABLE_METAL_SUPPORT) + target_link_libraries (${PROJECT_NAME} PRIVATE NRI_MTL) +endif () set_property (TARGET ${PROJECT_NAME} PROPERTY FOLDER ${PROJECT_FOLDER}) diff --git a/Include/Extensions/NRIWrapperMTL.h b/Include/Extensions/NRIWrapperMTL.h new file mode 100644 index 00000000..a80d0cac --- /dev/null +++ b/Include/Extensions/NRIWrapperMTL.h @@ -0,0 +1,62 @@ +// © 2021 NVIDIA Corporation + +#pragma once + +#include "NRIMacro.h" +#include "NRIDeviceCreation.h" + + +NriNamespaceBegin + + +typedef void* MTLHeap; +typedef void* MTLDeviceHandle; // id +typedef void* MTLBufferHandle; // id +typedef void* MTLTextureHandle; + +typedef uint32_t MTLEnum; + +NriStruct(DeviceCreationMTLDesc) +{ + bool enableNRIValidation; + MTLDeviceHandle MtlDevice; +}; + +NriStruct(CommandBufferMTLDesc) +{ + +}; + +NriStruct(BufferMTLDesc) +{ + MTLBufferHandle buffer; + void* mappedMemory; + //MTLResourceOptions options; +}; + +NriStruct(TextureMTLDesc) +{ + MTLTextureHandle mtlTexture; + MTLEnum textureType; + MTLEnum pixelFormat; + Nri(Dim_t) width; + Nri(Dim_t) height; + Nri(Dim_t) depth; + Nri(Mip_t) mipNum; + Nri(Dim_t) layerNum; + Nri(Sample_t) sampleNum; + //MTLTextureDescriptor* descriptor; +}; + +NriStruct(MemoryMTLDesc) +{ + uint64_t size; + // MTLStorageMode storage; + + //MTLResourceOptions options; +}; + +NRI_API Nri(Result) NRI_CALL nriCreateDeviceFromMtlDevice(const NriRef(DeviceCreationMTLDesc) deviceDesc, NriRef(Device*) device); + +NriNamespaceEnd + diff --git a/Include/NRIDescs.h b/Include/NRIDescs.h index 7f2f53d5..7f9d39c5 100644 --- a/Include/NRIDescs.h +++ b/Include/NRIDescs.h @@ -1,4 +1,4 @@ -// © 2021 NVIDIA Corporation +// © 2021 NVIDIA Corporation #pragma once @@ -76,7 +76,8 @@ NriEnum(GraphicsAPI, uint8_t, NONE, // Supports everything, does nothing, returns dummy non-NULL objects and ~0-filled descs, available if "NRI_ENABLE_NONE_SUPPORT = ON" in CMake D3D11, // Direct3D 11 (feature set 11.1), available if "NRI_ENABLE_D3D11_SUPPORT = ON" in CMake D3D12, // Direct3D 12 (feature set 11.1+), available if "NRI_ENABLE_D3D12_SUPPORT = ON" in CMake - VK // Vulkan 1.3 or 1.2+ (can be used on MacOS via MoltenVK), available if "NRI_ENABLE_VK_SUPPORT = ON" in CMake + VK, // Vulkan 1.3 or 1.2+ (can be used on MacOS via MoltenVK), available if "NRI_ENABLE_VK_SUPPORT = ON" in CMake + MTL ); NriEnum(Result, uint8_t, @@ -685,9 +686,14 @@ NriStruct(VertexAttributeVK) { uint32_t location; }; +NriStruct(VertexAttributeMTL) { + uint32_t location; +}; + NriStruct(VertexAttributeDesc) { Nri(VertexAttributeD3D) d3d; Nri(VertexAttributeVK) vk; + Nri(VertexAttributeMTL) mtl; uint32_t offset; Nri(Format) format; uint16_t streamIndex; @@ -1284,12 +1290,17 @@ NriStruct(PipelineStatisticsDesc) { #pragma region [ Device desc ] //============================================================================================================================================================================================ +// defined in apple framework +#undef INTEL +#undef AMD + NriEnum(Vendor, uint8_t, UNKNOWN, NVIDIA, AMD, - INTEL -); + INTEL, + APPLE +); NriStruct(AdapterDesc) { char name[256]; diff --git a/Include/NRIMacro.h b/Include/NRIMacro.h index 42c343aa..7ae83833 100644 --- a/Include/NRIMacro.h +++ b/Include/NRIMacro.h @@ -202,6 +202,7 @@ constexpr name operator | (name val0, name val1) { return (name)((type)val0 | (type)val1); } \ constexpr name& operator &= (name& val0, name val1) { val0 = (name)(val0 & val1); return val0; } \ constexpr name& operator |= (name& val0, name val1) { val0 = (name)(val0 | val1); return val0; } \ + constexpr name operator ~(name val0) { return (name)(~(type)val0); } \ enum class name : type { \ _NRI_ENUM_EXPAND(__VA_ARGS__), \ } diff --git a/Source/Creation/Creation.cpp b/Source/Creation/Creation.cpp index 1d81fbb7..0a439891 100644 --- a/Source/Creation/Creation.cpp +++ b/Source/Creation/Creation.cpp @@ -18,6 +18,11 @@ Result CreateDeviceD3D12(const DeviceCreationDesc& deviceCreationDesc, DeviceBas Result CreateDeviceD3D12(const DeviceCreationD3D12Desc& deviceCreationDesc, DeviceBase*& device); #endif +#if NRI_USE_MTL +Result CreateDeviceMTL(const DeviceCreationDesc& deviceCreationDesc, DeviceBase*& device); +Result CreateDeviceMTL(const DeviceCreationMTLDesc& deviceCreationDesc, DeviceBase*& device); +#endif + #if NRI_USE_VK Result CreateDeviceVK(const DeviceCreationDesc& deviceCreationDesc, DeviceBase*& device); Result CreateDeviceVK(const DeviceCreationVKDesc& deviceDesc, DeviceBase*& device); @@ -216,6 +221,11 @@ NRI_API Result NRI_CALL nriCreateDevice(const DeviceCreationDesc& deviceCreation if (modifiedDeviceCreationDesc.graphicsAPI == GraphicsAPI::D3D12) result = CreateDeviceD3D12(modifiedDeviceCreationDesc, deviceImpl); #endif + +#if NRI_USE_MTL + if (modifiedDeviceCreationDesc.graphicsAPI == GraphicsAPI::MTL) + result = CreateDeviceMTL(modifiedDeviceCreationDesc, deviceImpl); +#endif #if NRI_USE_VK if (modifiedDeviceCreationDesc.graphicsAPI == GraphicsAPI::VK) @@ -284,6 +294,24 @@ NRI_API Result NRI_CALL nriCreateDeviceFromD3D12Device(const DeviceCreationD3D12 return FinalizeDeviceCreation(deviceCreationDesc, *deviceImpl, device); } +NRI_API Result NRI_CALL nriCreateDeviceFromMtlDevice(const DeviceCreationMTLDesc& deviceCreationMtlDesc, Device*& device) { + DeviceCreationDesc deviceCreationDesc = {}; + deviceCreationDesc.graphicsAPI = GraphicsAPI::MTL; + deviceCreationDesc.enableNRIValidation = deviceCreationMtlDesc.enableNRIValidation; + + Result result = Result::UNSUPPORTED; + DeviceBase* deviceImpl = nullptr; + +#if NRI_USE_MTL + //result = CreateDeviceD3D12(tempDeviceCreationD3D12Desc, deviceImpl); +#endif + + if (result != Result::SUCCESS) + return result; + + return FinalizeDeviceCreation(deviceCreationDesc, *deviceImpl, device); +} + NRI_API Result NRI_CALL nriCreateDeviceFromVkDevice(const DeviceCreationVKDesc& deviceCreationVKDesc, Device*& device) { DeviceCreationDesc deviceCreationDesc = {}; deviceCreationDesc.callbackInterface = deviceCreationVKDesc.callbackInterface; @@ -325,6 +353,17 @@ NRI_API Format NRI_CALL nriConvertDXGIFormatToNRI(uint32_t dxgiFormat) { return DXGIFormatToNRIFormat(dxgiFormat); } +NRI_API uint32_t NRI_CALL nriConvertNRIFormatToMTL(Format format) { + MaybeUnused(format); + +#if NRI_USE_VK + return NRIFormatToMTLFormat(format); +#else + return 0; +#endif +} + + NRI_API uint32_t NRI_CALL nriConvertNRIFormatToVK(Format format) { MaybeUnused(format); @@ -443,6 +482,8 @@ NRI_API void NRI_CALL nriReportLiveObjects() { pDebug->ReportLiveObjects(DXGI_DEBUG_ALL, (DXGI_DEBUG_RLO_FLAGS)((uint32_t)DXGI_DEBUG_RLO_DETAIL | (uint32_t)DXGI_DEBUG_RLO_IGNORE_INTERNAL)); } +#elif __APPLE__ + #else # include # define GET_VK_FUNCTION(instance, name) \ diff --git a/Source/Creation/Creation.mm b/Source/Creation/Creation.mm new file mode 100644 index 00000000..14f651c9 --- /dev/null +++ b/Source/Creation/Creation.mm @@ -0,0 +1,83 @@ +#import + +#include "SharedExternal.h" + +using namespace nri; + +// referenced from Molten VK +static uint32_t GetEntryProperty(io_registry_entry_t entry, CFStringRef propertyName) { + + uint32_t value = 0; + + CFTypeRef cfProp = IORegistryEntrySearchCFProperty(entry, + kIOServicePlane, + propertyName, + kCFAllocatorDefault, + kIORegistryIterateRecursively | + kIORegistryIterateParents); + if (cfProp) { + const uint32_t* pValue = reinterpret_cast(CFDataGetBytePtr((CFDataRef)cfProp)); + if (pValue) { value = *pValue; } + CFRelease(cfProp); + } + + return value; +} + + +static int SortAdaptersByDedicatedVideoMemorySize(const void* pa, const void* pb) { + AdapterDesc* a = (AdapterDesc*)pa; + AdapterDesc* b = (AdapterDesc*)pb; + + if (a->videoMemorySize > b->videoMemorySize) + return -1; + + if (a->videoMemorySize < b->videoMemorySize) + return 1; + + return 0; +} + +NRI_API Result NRI_CALL nriEnumerateAdapters(AdapterDesc* adapterDescs, uint32_t& adapterDescNum) { + + NSArray>* devices = MTLCopyAllDevices(); + if(!adapterDescs) { + adapterDescNum = (uint32_t)devices.count; + return Result::SUCCESS; + } + + AdapterDesc* adapterDescsSorted = (AdapterDesc*)alloca(sizeof(AdapterDesc) * devices.count); + for(size_t i = 0; i < devices.count; i++) { + NSString* name = [devices[i] name]; + [name getCString:adapterDescsSorted[i].name maxLength: sizeof(adapterDescs[i].name) - 1 encoding: NSASCIIStringEncoding]; + const uint64_t regID = [devices[i] registryID]; + adapterDescsSorted[i].luid = regID; + if (regID) + { + io_registry_entry_t entry = IOServiceGetMatchingService(MACH_PORT_NULL, IORegistryEntryIDMatching(regID)); + if (entry) + { + // That returned the IOGraphicsAccelerator nub. Its parent, then, is the actual PCI device. + io_registry_entry_t deviceEntry; + if (IORegistryEntryGetParentEntry(entry, kIOServicePlane, &deviceEntry) == kIOReturnSuccess) + { + adapterDescsSorted[i].vendor = GetVendorFromID(GetEntryProperty(deviceEntry, CFSTR("vendor-id"))) ; + adapterDescsSorted[i].deviceId = GetEntryProperty(deviceEntry, CFSTR("device-id")); + } + } + } else { + adapterDescsSorted[i].vendor = nri::Vendor::APPLE; + } + adapterDescsSorted[i].videoMemorySize = [devices[i] recommendedMaxWorkingSetSize]; + NSProcessInfo *pinfo = [NSProcessInfo processInfo]; + adapterDescsSorted[i].systemMemorySize = [pinfo physicalMemory]; + } + + // Sort by video memory size + qsort(adapterDescsSorted, devices.count, sizeof(adapterDescsSorted[0]), SortAdaptersByDedicatedVideoMemorySize); + for(size_t i = 0; i < MIN(devices.count, adapterDescNum); i++) { + adapterDescs[i] = adapterDescsSorted[i]; + } + adapterDescNum = (uint32_t)MIN(devices.count, adapterDescNum); + return Result::SUCCESS; +} diff --git a/Source/Metal/BufferMTL.h b/Source/Metal/BufferMTL.h new file mode 100644 index 00000000..42adba26 --- /dev/null +++ b/Source/Metal/BufferMTL.h @@ -0,0 +1,59 @@ +// © 2021 NVIDIA Corporation +#pragma once + +#import + +namespace nri { + +struct DeviceMTL; +struct MemoryMTL; + +struct BufferMTL { + + inline BufferMTL(DeviceMTL& device) + : m_Device(device) { + } + + ~BufferMTL(); + + inline id GetHandle() const { + return m_Handle; + } + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + inline const BufferDesc& GetDesc() const { + return m_Desc; + } + + void* Map(uint64_t offset, uint64_t size); + void Unmap(); + + void FinishMemoryBinding(MemoryMTL& memory, uint64_t memoryOffset); + Result Create(const BufferDesc& bufferDesc); + Result Create(const AllocateBufferDesc& bufferDesc); + + //================================================================================================================ + // NRI + //================================================================================================================ + + void SetDebugName(const char* name); + +private: + void UpdateLabel(); + + NSString* m_Label = nullptr; + DeviceMTL& m_Device; + id m_Handle; + uint8_t* m_MappedMemory = nullptr; + uint64_t m_MappedMemoryOffset = 0; + uint64_t m_MappedMemoryRangeSize = 0; + uint64_t m_MappedMemoryRangeOffset = 0; + BufferDesc m_Desc = {}; + bool m_OwnsNativeObjects = true; +}; + + +}; diff --git a/Source/Metal/BufferMTL.mm b/Source/Metal/BufferMTL.mm new file mode 100644 index 00000000..67c286a3 --- /dev/null +++ b/Source/Metal/BufferMTL.mm @@ -0,0 +1,48 @@ +#include "SharedMTL.h" + +#include "BufferMTL.h" +#include "MemoryMTL.h" + +using namespace nri; + +void* BufferMTL::Map(uint64_t offset, uint64_t size) { + return (uint8_t*)[m_Handle contents] + offset; +} + +BufferMTL::~BufferMTL() { + [m_Label release]; +} + +void BufferMTL::Unmap() { + +} + +void BufferMTL::FinishMemoryBinding(MemoryMTL& memory, uint64_t memoryOffset) { + m_Handle = [memory.GetHandle() + newBufferWithLength: m_Desc.size + options: MTLResourceCPUCacheModeDefaultCache + offset: memoryOffset]; + UpdateLabel(); +} + +Result BufferMTL::Create(const AllocateBufferDesc& bufferDesc) { + m_Desc = bufferDesc.desc; + m_Handle = [m_Device.GetHandle() newBufferWithLength: m_Desc.size options: MTLResourceCPUCacheModeDefaultCache]; + UpdateLabel(); +} + +void BufferMTL::UpdateLabel() { + if(m_Handle && m_Label) { + [m_Handle setLabel: m_Label]; + } +} + +Result BufferMTL::Create(const BufferDesc& bufferDesc) { + m_Desc = bufferDesc; +} + +void BufferMTL::SetDebugName(const char* name) { + m_Label = [NSString stringWithUTF8String:name]; + [m_Label retain]; + UpdateLabel(); +} diff --git a/Source/Metal/CommandAllocatorMTL.h b/Source/Metal/CommandAllocatorMTL.h new file mode 100644 index 00000000..402580a7 --- /dev/null +++ b/Source/Metal/CommandAllocatorMTL.h @@ -0,0 +1,39 @@ +// © 2021 NVIDIA Corporation + +#pragma once + +namespace nri { + +struct DeviceMTL; +struct CommandQueueMTL; + +struct CommandAllocatorMTL { + inline CommandAllocatorMTL(DeviceMTL& device) + : m_Device(device) { + } + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + ~CommandAllocatorMTL(); + + + + Result Create(const CommandQueue& commandQueue); + + //================================================================================================================ + // NRI + //================================================================================================================ + + void SetDebugName(const char* name); + Result CreateCommandBuffer(CommandBuffer*& commandBuffer); + void Reset(); + +private: + DeviceMTL& m_Device; + const struct CommandQueueMTL* m_CommandQueue; +}; + +} + diff --git a/Source/Metal/CommandAllocatorMTL.hpp b/Source/Metal/CommandAllocatorMTL.hpp new file mode 100644 index 00000000..0239d982 --- /dev/null +++ b/Source/Metal/CommandAllocatorMTL.hpp @@ -0,0 +1,19 @@ +// © 2021 NVIDIA Corporation + +#pragma region[ Core ] + +static void NRI_CALL SetCommandAllocatorDebugName(CommandAllocator& commandAllocator, const char* name) { + //((CommandAllocatorVK&)commandAllocator).SetDebugName(name); +} + +static Result NRI_CALL CreateCommandBuffer(CommandAllocator& commandAllocator, CommandBuffer*& commandBuffer) { + return ((CommandAllocatorMTL&)commandAllocator).CreateCommandBuffer(commandBuffer); +} + +static void NRI_CALL ResetCommandAllocator(CommandAllocator& commandAllocator) { + //((CommandAllocatorVK&)commandAllocator).Reset(); +} + +#pragma endregion + + diff --git a/Source/Metal/CommandAllocatorMTL.mm b/Source/Metal/CommandAllocatorMTL.mm new file mode 100644 index 00000000..325074fb --- /dev/null +++ b/Source/Metal/CommandAllocatorMTL.mm @@ -0,0 +1,39 @@ +#include "SharedMTL.h" + +#include "CommandAllocatorMTL.h" +#include "CommandBufferMTL.h" +#include "CommandQueueMTL.h" + +using namespace nri; + +CommandAllocatorMTL::~CommandAllocatorMTL() { + +} + +Result CommandAllocatorMTL::Create(const CommandQueue& commandQueue) { + const CommandQueueMTL& commandQueueImpl = (CommandQueueMTL&)commandQueue; + m_CommandQueue = &commandQueueImpl; + return Result::SUCCESS; +} + + +void CommandAllocatorMTL::SetDebugName(const char* name) { + +} + +void CommandAllocatorMTL::Reset() { + +} +//================================================================================================================ +// NRI +//================================================================================================================ + +Result CommandAllocatorMTL::CreateCommandBuffer(CommandBuffer*& commandBuffer) { + + CommandBufferMTL* commandBufferImpl = Allocate(m_Device.GetStdAllocator(), m_Device); + commandBufferImpl->Create(m_CommandQueue); + commandBuffer = (CommandBuffer*)commandBufferImpl; + return Result::SUCCESS; +} + +#include "CommandAllocatorMTL.hpp" diff --git a/Source/Metal/CommandBufferMTL.h b/Source/Metal/CommandBufferMTL.h new file mode 100644 index 00000000..44d6420b --- /dev/null +++ b/Source/Metal/CommandBufferMTL.h @@ -0,0 +1,130 @@ +// © 2021 NVIDIA Corporation + +#pragma once + +#import + +#include "SharedMTL.h" + +namespace nri { + +struct DeviceMTL; +struct PipelineMTL; +struct BufferMTL; +struct PipelineLayoutMTL; +struct TextureMTL; +struct DescriptorMTL; + +struct CommandBufferMTL { + + CommandBufferMTL(DeviceMTL& device); + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + inline id GetHandle() const { + return m_Handle; + } + + void SetDebugName(const char* name); + Result Begin(const DescriptorPool* descriptorPool); + Result End(); + void SetPipeline(const Pipeline& pipeline); + void SetPipelineLayout(const PipelineLayout& pipelineLayout); + void SetDescriptorSet(uint32_t setIndexInPipelineLayout, const DescriptorSet& descriptorSet, const uint32_t* dynamicConstantBufferOffsets); + void SetConstants(uint32_t pushConstantIndex, const void* data, uint32_t size); + void SetDescriptorPool(const DescriptorPool& descriptorPool); + void Barrier(const BarrierGroupDesc& barrierGroupDesc); + void BeginRendering(const AttachmentsDesc& attachmentsDesc); + void EndRendering(); + void SetViewports(const Viewport* viewports, uint32_t viewportNum); + void SetScissors(const Rect* rects, uint32_t rectNum); + void SetDepthBounds(float boundsMin, float boundsMax); + void SetStencilReference(uint8_t frontRef, uint8_t backRef); + // void SetSamplePositions(const SamplePosition* positions, Sample_t positionNum, Sample_t sampleNum); + void SetBlendConstants(const Color32f& color); + void SetShadingRate(const ShadingRateDesc& shadingRateDesc); + void ClearAttachments(const ClearDesc* clearDescs, uint32_t clearDescNum, const Rect* rects, uint32_t rectNum); + void SetIndexBuffer(const Buffer& buffer, uint64_t offset, IndexType indexType); + void SetVertexBuffers(uint32_t baseSlot, uint32_t bufferNum, const Buffer* const* buffers, const uint64_t* offsets); + void Draw(const DrawDesc& drawDesc); + void DrawIndexed(const DrawIndexedDesc& drawIndexedDesc); + void DrawIndirect(const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride, const Buffer* countBuffer, uint64_t countBufferOffset); + void DrawIndexedIndirect(const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride, const Buffer* countBuffer, uint64_t countBufferOffset); + void Dispatch(const DispatchDesc& dispatchDesc); + void DispatchIndirect(const Buffer& buffer, uint64_t offset); + void BeginQuery(const QueryPool& queryPool, uint32_t offset); + void EndQuery(const QueryPool& queryPool, uint32_t offset); + void BeginAnnotation(const char* name); + void EndAnnotation(); + void ClearStorageBuffer(const ClearStorageBufferDesc& clearDesc); + void ClearStorageTexture(const ClearStorageTextureDesc& clearDesc); + void CopyBuffer(Buffer& dstBuffer, uint64_t dstOffset, const Buffer& srcBuffer, uint64_t srcOffset, uint64_t size); + void CopyTexture(Texture& dstTexture, const TextureRegionDesc* dstRegionDesc, const Texture& srcTexture, const TextureRegionDesc* srcRegionDesc); + void UploadBufferToTexture(Texture& dstTexture, const TextureRegionDesc& dstRegionDesc, const Buffer& srcBuffer, const TextureDataLayoutDesc& srcDataLayoutDesc); + void ReadbackTextureToBuffer(Buffer& dstBuffer, const TextureDataLayoutDesc& dstDataLayoutDesc, const Texture& srcTexture, const TextureRegionDesc& srcRegionDesc); + void CopyQueries(const QueryPool& queryPool, uint32_t offset, uint32_t num, Buffer& dstBuffer, uint64_t dstOffset); + void ResetQueries(const QueryPool& queryPool, uint32_t offset, uint32_t num); + void BuildTopLevelAccelerationStructure(uint32_t instanceNum, const Buffer& buffer, uint64_t bufferOffset, AccelerationStructureBuildBits flags, AccelerationStructure& dst, Buffer& scratch, uint64_t scratchOffset); + void BuildBottomLevelAccelerationStructure(uint32_t geometryObjectNum, const GeometryObject* geometryObjects, AccelerationStructureBuildBits flags, AccelerationStructure& dst, Buffer& scratch, uint64_t scratchOffset); + void UpdateTopLevelAccelerationStructure(uint32_t instanceNum, const Buffer& buffer, uint64_t bufferOffset, AccelerationStructureBuildBits flags, AccelerationStructure& dst, AccelerationStructure& src, Buffer& scratch, uint64_t scratchOffset); + void UpdateBottomLevelAccelerationStructure(uint32_t geometryObjectNum, const GeometryObject* geometryObjects, AccelerationStructureBuildBits flags, AccelerationStructure& dst, AccelerationStructure& src, Buffer& scratch, uint64_t scratchOffset); + void CopyAccelerationStructure(AccelerationStructure& dst, AccelerationStructure& src, CopyMode copyMode); + void WriteAccelerationStructureSize(const AccelerationStructure* const* accelerationStructures, uint32_t accelerationStructureNum, QueryPool& queryPool, uint32_t queryPoolOffset); + void DispatchRays(const DispatchRaysDesc& dispatchRaysDesc); + void DispatchRaysIndirect(const Buffer& buffer, uint64_t offset); + void DrawMeshTasks(const DrawMeshTasksDesc& drawMeshTasksDesc); + void DrawMeshTasksIndirect(const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride); + + ~CommandBufferMTL(); + + void Create(const struct CommandQueueMTL* queue); + + struct CmdIndexBuffer { + size_t m_Offset; + MTLIndexType m_Type; + struct BufferMTL* m_Buffer; + }; + struct CmdVertexBuffer { + size_t m_Offset; + struct BufferMTL* m_Buffer; + }; + +private: + + void updateCommandBufferState(); + void EndCurrentEncoders(); + void InsertBarriers(); + + DeviceMTL& m_Device; + struct PipelineMTL* m_CurrentPipeline = nullptr; + PipelineLayoutMTL* m_CurrentPipelineLayout = nullptr; + id m_Handle; + id m_RendererEncoder = nil; + id m_ComputeEncoder = nil; + id m_BlitEncoder = nil; + const struct CommandQueueMTL* m_CommandQueue = nullptr; + + BarrierBits m_barrierFlags = BarrierBits::NONE; + + + uint16_t m_numViewports = 0; + uint16_t m_numScissors = 0; + CommandBufferDirtyBits m_DirtyBits = CommandBufferDirtyBits::NONE; + + MTLRenderPassDescriptor* m_renderPassDescriptor = nil; + struct CmdIndexBuffer m_indexBuffer; + uint32_t m_dirtyVertexBufferBits = 0; + struct CmdVertexBuffer m_vertexBuffers[32]; + struct ShadingRateDesc m_shadingRateDesc; + MTLViewport m_Viewports[16]; + MTLScissorRect m_Scissors[16]; + Color32f m_BlendColor; + uint8_t m_StencilFront; + uint8_t m_StencilBack; + + NSMutableArray* m_Annotations; + +}; +}; + diff --git a/Source/Metal/CommandBufferMTL.hpp b/Source/Metal/CommandBufferMTL.hpp new file mode 100644 index 00000000..17f4af40 --- /dev/null +++ b/Source/Metal/CommandBufferMTL.hpp @@ -0,0 +1,179 @@ + +//#pragma region[ Core ] +// +//static void NRI_CALL SetCommandBufferDebugName(CommandBuffer& commandBuffer, const char* name) { +// ((CommandBufferMTL&)commandBuffer).SetDebugName(name); +//} +// +//static Result NRI_CALL BeginCommandBuffer(CommandBuffer& commandBuffer, const DescriptorPool* descriptorPool) { +// return ((CommandBufferMTL&)commandBuffer).Begin(descriptorPool); +//} +// +//static Result NRI_CALL EndCommandBuffer(CommandBuffer& commandBuffer) { +// return ((CommandBufferMTL&)commandBuffer).End(); +//} +// +//static void NRI_CALL CmdSetPipelineLayout(CommandBuffer& commandBuffer, const PipelineLayout& pipelineLayout) { +// ((CommandBufferMTL&)commandBuffer).SetPipelineLayout(pipelineLayout); +//} +// +//static void NRI_CALL CmdSetPipeline(CommandBuffer& commandBuffer, const Pipeline& pipeline) { +// ((CommandBufferMTL&)commandBuffer).SetPipeline(pipeline); +//} +// +//static void NRI_CALL CmdBarrier(CommandBuffer& commandBuffer, const BarrierGroupDesc& barrierGroupDesc) { +// ((CommandBufferMTL&)commandBuffer).Barrier(barrierGroupDesc); +//} +// +//static void NRI_CALL CmdSetDescriptorPool(CommandBuffer& commandBuffer, const DescriptorPool& descriptorPool) { +// ((CommandBufferMTL&)commandBuffer).SetDescriptorPool(descriptorPool); +//} +// +//static void NRI_CALL CmdSetDescriptorSet(CommandBuffer& commandBuffer, uint32_t setIndexInPipelineLayout, const DescriptorSet& descriptorSet, const uint32_t* dynamicConstantBufferOffsets) { +// ((CommandBufferMTL&)commandBuffer).SetDescriptorSet(setIndexInPipelineLayout, descriptorSet, dynamicConstantBufferOffsets); +//} +// +//static void NRI_CALL CmdSetConstants(CommandBuffer& commandBuffer, uint32_t pushConstantIndex, const void* data, uint32_t size) { +// ((CommandBufferMTL&)commandBuffer).SetConstants(pushConstantIndex, data, size); +//} +// +//static void NRI_CALL CmdBeginRendering(CommandBuffer& commandBuffer, const AttachmentsDesc& attachmentsDesc) { +// ((CommandBufferMTL&)commandBuffer).BeginRendering(attachmentsDesc); +//} +// +//static void NRI_CALL CmdEndRendering(CommandBuffer& commandBuffer) { +// ((CommandBufferMTL&)commandBuffer).EndRendering(); +//} +// +//static void NRI_CALL CmdSetViewports(CommandBuffer& commandBuffer, const Viewport* viewports, uint32_t viewportNum) { +// ((CommandBufferMTL&)commandBuffer).SetViewports(viewports, viewportNum); +//} +// +//static void NRI_CALL CmdSetScissors(CommandBuffer& commandBuffer, const nri::Rect* rects, uint32_t rectNum) { +// ((CommandBufferMTL&)commandBuffer).SetScissors(rects, rectNum); +//} +// +//static void NRI_CALL CmdSetDepthBounds(CommandBuffer& commandBuffer, float boundsMin, float boundsMax) { +// ((CommandBufferMTL&)commandBuffer).SetDepthBounds(boundsMin, boundsMax); +//} +// +//static void NRI_CALL CmdSetStencilReference(CommandBuffer& commandBuffer, uint8_t frontRef, uint8_t backRef) { +// ((CommandBufferMTL&)commandBuffer).SetStencilReference(frontRef, backRef); +//} +// +//static void NRI_CALL CmdSetSamplePositions(CommandBuffer& commandBuffer, const SamplePosition* positions, Sample_t positionNum, Sample_t sampleNum) { +// ((CommandBufferMTL&)commandBuffer).SetSamplePositions(positions, positionNum, sampleNum); +//} +// +//static void NRI_CALL CmdSetBlendConstants(CommandBuffer& commandBuffer, const Color32f& color) { +// ((CommandBufferMTL&)commandBuffer).SetBlendConstants(color); +//} +// +//static void NRI_CALL CmdSetShadingRate(CommandBuffer& commandBuffer, const ShadingRateDesc& shadingRateDesc) { +// ((CommandBufferMTL&)commandBuffer).SetShadingRate(shadingRateDesc); +//} +// +//static void NRI_CALL CmdSetDepthBias(CommandBuffer& commandBuffer, const DepthBiasDesc& depthBiasDesc) { +// //((CommandBufferMTL&)commandBuffer).SetDepthBias(depthBiasDesc); +//} +// +//static void NRI_CALL CmdClearAttachments(CommandBuffer& commandBuffer, const ClearDesc* clearDescs, uint32_t clearDescNum, const nri::Rect* rects, uint32_t rectNum) { +// ((CommandBufferMTL&)commandBuffer).ClearAttachments(clearDescs, clearDescNum, rects, rectNum); +//} +// +//static void NRI_CALL CmdSetIndexBuffer(CommandBuffer& commandBuffer, const Buffer& buffer, uint64_t offset, IndexType indexType) { +// ((CommandBufferMTL&)commandBuffer).SetIndexBuffer(buffer, offset, indexType); +//} +// +//static void NRI_CALL CmdSetVertexBuffers(CommandBuffer& commandBuffer, uint32_t baseSlot, uint32_t bufferNum, const Buffer* const* buffers, const uint64_t* offsets) { +// ((CommandBufferMTL&)commandBuffer).SetVertexBuffers(baseSlot, bufferNum, buffers, offsets); +//} +// +//static void NRI_CALL CmdDraw(CommandBuffer& commandBuffer, const DrawDesc& drawDesc) { +// ((CommandBufferMTL&)commandBuffer).Draw(drawDesc); +//} +// +//static void NRI_CALL CmdDrawIndexed(CommandBuffer& commandBuffer, const DrawIndexedDesc& drawIndexedDesc) { +// ((CommandBufferMTL&)commandBuffer).DrawIndexed(drawIndexedDesc); +//} +// +//static void NRI_CALL CmdDrawIndirect(CommandBuffer& commandBuffer, const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride, const Buffer* countBuffer, uint64_t countBufferOffset) { +// ((CommandBufferMTL&)commandBuffer).DrawIndirect(buffer, offset, drawNum, stride, countBuffer, countBufferOffset); +//} +// +//static void NRI_CALL CmdDrawIndexedIndirect(CommandBuffer& commandBuffer, const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride, const Buffer* countBuffer, uint64_t countBufferOffset) { +// ((CommandBufferMTL&)commandBuffer).DrawIndexedIndirect(buffer, offset, drawNum, stride, countBuffer, countBufferOffset); +//} +// +//static void NRI_CALL CmdDispatch(CommandBuffer& commandBuffer, const DispatchDesc& dispatchDesc) { +// ((CommandBufferMTL&)commandBuffer).Dispatch(dispatchDesc); +//} +// +//static void NRI_CALL CmdDispatchIndirect(CommandBuffer& commandBuffer, const Buffer& buffer, uint64_t offset) { +// ((CommandBufferMTL&)commandBuffer).DispatchIndirect(buffer, offset); +//} +// +//static void NRI_CALL CmdBeginQuery(CommandBuffer& commandBuffer, const QueryPool& queryPool, uint32_t offset) { +// ((CommandBufferMTL&)commandBuffer).BeginQuery(queryPool, offset); +//} +// +//static void NRI_CALL CmdEndQuery(CommandBuffer& commandBuffer, const QueryPool& queryPool, uint32_t offset) { +// ((CommandBufferMTL&)commandBuffer).EndQuery(queryPool, offset); +//} +// +//static void NRI_CALL CmdBeginAnnotation(CommandBuffer& commandBuffer, const char* name) { +// ((CommandBufferMTL&)commandBuffer).BeginAnnotation(name); +//} +// +//static void NRI_CALL CmdEndAnnotation(CommandBuffer& commandBuffer) { +// ((CommandBufferMTL&)commandBuffer).EndAnnotation(); +//} +// +//static void NRI_CALL CmdClearStorageBuffer(CommandBuffer& commandBuffer, const ClearStorageBufferDesc& clearDesc) { +// ((CommandBufferMTL&)commandBuffer).ClearStorageBuffer(clearDesc); +//} +// +//static void NRI_CALL CmdClearStorageTexture(CommandBuffer& commandBuffer, const ClearStorageTextureDesc& clearDesc) { +// ((CommandBufferMTL&)commandBuffer).ClearStorageTexture(clearDesc); +//} +// +//static void NRI_CALL CmdCopyBuffer(CommandBuffer& commandBuffer, Buffer& dstBuffer, uint64_t dstOffset, const Buffer& srcBuffer, uint64_t srcOffset, uint64_t size) { +// ((CommandBufferMTL&)commandBuffer).CopyBuffer(dstBuffer, dstOffset, srcBuffer, srcOffset, size); +//} +// +//static void NRI_CALL CmdCopyTexture( +// CommandBuffer& commandBuffer, Texture& dstTexture, const TextureRegionDesc* dstRegionDesc, const Texture& srcTexture, const TextureRegionDesc* srcRegionDesc) { +// ((CommandBufferMTL&)commandBuffer).CopyTexture(dstTexture, dstRegionDesc, srcTexture, srcRegionDesc); +//} +// +//static void NRI_CALL CmdUploadBufferToTexture(CommandBuffer& commandBuffer, Texture& dstTexture, const TextureRegionDesc& dstRegionDesc, const Buffer& srcBuffer, const TextureDataLayoutDesc& srcDataLayoutDesc) { +// ((CommandBufferMTL&)commandBuffer).UploadBufferToTexture(dstTexture, dstRegionDesc, srcBuffer, srcDataLayoutDesc); +//} +// +//static void NRI_CALL CmdReadbackTextureToBuffer(CommandBuffer& commandBuffer, Buffer& dstBuffer, const TextureDataLayoutDesc& dstDataLayoutDesc, const Texture& srcTexture, const TextureRegionDesc& srcRegionDesc) { +// //((CommandBufferMTL&)commandBuffer).ReadbackTextureToBuffer(dstBuffer, dstDataLayoutDesc, srcTexture, srcRegionDesc); +//} +// +//static void NRI_CALL CmdCopyQueries(CommandBuffer& commandBuffer, const QueryPool& queryPool, uint32_t offset, uint32_t num, Buffer& dstBuffer, uint64_t dstOffset) { +// ((CommandBufferMTL&)commandBuffer).CopyQueries(queryPool, offset, num, dstBuffer, dstOffset); +//} +// +//static void NRI_CALL CmdResetQueries(CommandBuffer& commandBuffer, const QueryPool& queryPool, uint32_t offset, uint32_t num) { +// ((CommandBufferMTL&)commandBuffer).ResetQueries(queryPool, offset, num); +//} +// +//static void* NRI_CALL GetCommandBufferNativeObject(const CommandBuffer& commandBuffer) { +// if (!(&commandBuffer)) +// return nullptr; +// +// return nullptr; +// // return (CommandBufferMTL)((CommandBufferMTL&)commandBuffer); +//} +// +//#pragma endregion +// +// +// +// +//Define_Core_CommandBuffer_PartiallyFillFunctionTable(VK); + diff --git a/Source/Metal/CommandBufferMTL.mm b/Source/Metal/CommandBufferMTL.mm new file mode 100644 index 00000000..9ce4b7e5 --- /dev/null +++ b/Source/Metal/CommandBufferMTL.mm @@ -0,0 +1,689 @@ +#include "SharedMTL.h" + +#include "CommandBufferMTL.h" + +#include "BufferMTL.h" +#include "CommandBufferMTL.h" +#include "CommandQueueMTL.h" +#include "DescriptorMTL.h" +#include "DescriptorSetMTL.h" +#include "PipelineLayoutMTL.h" +#include "PipelineMTL.h" +#include "PipelineLayoutMTL.h" +#include "TextureMTL.h" + +using namespace nri; + +CommandBufferMTL::~CommandBufferMTL() { + +} + + +CommandBufferMTL::CommandBufferMTL(DeviceMTL& device): m_Device(device) { + m_Annotations = [NSMutableArray alloc]; +} + +void CommandBufferMTL::SetDebugName(const char* name) { + [m_Handle setLabel:[NSString stringWithUTF8String:name]]; +} + +Result CommandBufferMTL::Begin(const DescriptorPool* descriptorPool) { +} + +Result CommandBufferMTL::End() { + InsertBarriers(); + EndCurrentEncoders(); +} + +void CommandBufferMTL::SetPipeline(const Pipeline& pipeline) { + if (m_CurrentPipeline == (PipelineMTL*)&pipeline) + return; + + PipelineMTL& pipelineImpl = (PipelineMTL&)pipeline; + m_CurrentPipeline = &pipelineImpl; + switch(m_CurrentPipeline->GetPipelineType()) { + case PipelineType::Compute: { + if(!m_ComputeEncoder) { + MTLComputePassDescriptor* computePassDescriptor = [MTLComputePassDescriptor computePassDescriptor]; + m_ComputeEncoder = [m_Handle computeCommandEncoderWithDescriptor:computePassDescriptor]; + + while(m_Annotations.count > 0) { + NSObject* obj = m_Annotations[m_Annotations.count - 1]; + if([obj isKindOfClass: [NSNull class]]) { + [m_ComputeEncoder popDebugGroup]; + } else { + [m_ComputeEncoder insertDebugSignpost: (NSString*)obj]; + } + [m_Annotations removeLastObject]; + } + + } + [m_ComputeEncoder setComputePipelineState: m_CurrentPipeline->GetComputePipeline()]; + break; + } + case PipelineType::Graphics: { + if(!m_RendererEncoder) { + m_RendererEncoder = [m_Handle renderCommandEncoderWithDescriptor: m_renderPassDescriptor]; + + uint32_t vertexSlot = 0; + for( uint32_t attr = m_dirtyVertexBufferBits; attr > 0; attr = ( attr >> 1 ), vertexSlot++ ) + [m_RendererEncoder setVertexBuffer: m_vertexBuffers[vertexSlot].m_Buffer->GetHandle() + offset: m_vertexBuffers[vertexSlot].m_Offset + atIndex: vertexSlot]; + + while(m_Annotations.count > 0) { + NSObject* obj = m_Annotations[m_Annotations.count - 1]; + if([obj isKindOfClass: [NSNull class]]) { + [m_RendererEncoder popDebugGroup]; + } else { + [m_RendererEncoder insertDebugSignpost: (NSString*)obj]; + } + [m_Annotations removeLastObject]; + } + if(m_numViewports > 0) + [m_RendererEncoder setViewports: m_Viewports count: m_numViewports]; + if(m_numScissors > 0) + [m_RendererEncoder setScissorRects: m_Scissors count: m_numScissors]; + if(m_DirtyBits & CommandBufferDirtyBits::CMD_DIRTY_BLEND_CONSTANT) + [m_RendererEncoder setBlendColorRed: m_BlendColor.x + green: m_BlendColor.y + blue: m_BlendColor.z + alpha: m_BlendColor.w]; + if(m_DirtyBits & CommandBufferDirtyBits::CMD_DIRTY_STENCIL) + [m_RendererEncoder + setStencilFrontReferenceValue: m_StencilFront + backReferenceValue: m_StencilBack]; + } + + [m_RendererEncoder setRenderPipelineState: m_CurrentPipeline->GetGraphicsPipeline()]; + break; + } + case PipelineType::Raytracing: { + break; + } + } +} + +void CommandBufferMTL::SetPipelineLayout(const PipelineLayout& pipelineLayout) { + PipelineLayoutMTL& pipelineLayoutMTL = (PipelineLayoutMTL&)pipelineLayout; + m_CurrentPipelineLayout = &pipelineLayoutMTL; +} + +void CommandBufferMTL::SetDescriptorSet(uint32_t setIndexInPipelineLayout, const DescriptorSet& descriptorSet, const uint32_t* dynamicConstantBufferOffsets) { + const DescriptorSetMTL& descriptorSetImpl = (DescriptorSetMTL&)descriptorSet; + auto* layout = m_CurrentPipelineLayout->GetDescriptorSetLayout(setIndexInPipelineLayout); + const uint32_t space = layout->m_DescriptorSetDesc.registerSpace; + + StageBits stageBits = (StageBits)0; + for(size_t i = 0; i < layout->m_DescriptorSetDesc.rangeNum; i++) { + if(layout->m_DescriptorSetDesc.ranges[i].shaderStages == StageBits::NONE) + continue; + stageBits |= layout->m_DescriptorSetDesc.ranges[i].shaderStages ; + } + if(stageBits == StageBits::ALL || + stageBits & StageBits::FRAGMENT_SHADER) { + [m_RendererEncoder setFragmentBuffer: descriptorSetImpl.GetArgumentBuffer() + offset: descriptorSetImpl.GetArugmentBufferOffset() + atIndex: space]; + } + if(stageBits == StageBits::ALL || + stageBits & StageBits::VERTEX_SHADER) { + [m_RendererEncoder setVertexBuffer: descriptorSetImpl.GetArgumentBuffer() + offset: descriptorSetImpl.GetArugmentBufferOffset() + atIndex: space]; + + } + + if(stageBits == StageBits::ALL || + stageBits & StageBits::COMPUTE_SHADER) { + [m_ComputeEncoder setBuffer: descriptorSetImpl.GetArgumentBuffer() + offset: descriptorSetImpl.GetArugmentBufferOffset() + atIndex: space]; + + } + +} + +void CommandBufferMTL::SetConstants(uint32_t pushConstantIndex, const void* data, uint32_t size) { + const struct RootConstantDesc* pDesc = m_CurrentPipelineLayout->GetPushBinding(pushConstantIndex); + + + if (pDesc->shaderStages == StageBits::ALL || + pDesc->shaderStages & StageBits::VERTEX_SHADER) + { + [m_RendererEncoder setVertexBytes:data length:size atIndex:pDesc->registerIndex]; + } + + if (pDesc->shaderStages == StageBits::ALL || + pDesc->shaderStages & StageBits::FRAGMENT_SHADER ) + { + [m_RendererEncoder setFragmentBytes:data length:size atIndex:pDesc->registerIndex]; + } + + if (pDesc->shaderStages == StageBits::ALL || + pDesc->shaderStages & StageBits::COMPUTE_SHADER ) + { + [m_ComputeEncoder setBytes:data length:size atIndex:pDesc->registerIndex]; + } +} + +void CommandBufferMTL::SetDescriptorPool(const DescriptorPool& descriptorPool) { + +} + + +void CommandBufferMTL::InsertBarriers() { + if(m_RendererEncoder) { + if (m_barrierFlags & BarrierBits::BARRIER_FLAG_BUFFERS) + { + [m_RendererEncoder memoryBarrierWithScope:MTLBarrierScopeBuffers + afterStages:MTLRenderStageFragment + beforeStages:MTLRenderStageVertex]; + } + + if (m_barrierFlags & BarrierBits::BARRIER_FLAG_TEXTURES) + { + [m_RendererEncoder memoryBarrierWithScope:MTLBarrierScopeTextures + afterStages:MTLRenderStageFragment + beforeStages:MTLRenderStageVertex]; + } + } + + if(m_ComputeEncoder) { + if (m_barrierFlags & BarrierBits::BARRIER_FLAG_BUFFERS) + { + [m_ComputeEncoder memoryBarrierWithScope:MTLBarrierScopeBuffers]; + } + + if (m_barrierFlags & BarrierBits::BARRIER_FLAG_TEXTURES) + { + [m_ComputeEncoder memoryBarrierWithScope:MTLBarrierScopeTextures]; + } + + } + + m_barrierFlags = BarrierBits::NONE; +} + +void CommandBufferMTL::Barrier(const BarrierGroupDesc& barrierGroupDesc) { + + if(barrierGroupDesc.bufferNum) { + m_barrierFlags |= BarrierBits::BARRIER_FLAG_BUFFERS; + } + + if(barrierGroupDesc.textureNum) { + m_barrierFlags |= BarrierBits::BARRIER_FLAG_TEXTURES; + } +// +// const size_t totalResources = barrierGroupDesc.bufferNum + barrierGroupDesc.textureNum; +// Scratch> resourceBarrier = AllocateScratch(m_Device, id, totalResources); +// size_t barrierCount = 0; +// for(size_t i = 0; i < barrierGroupDesc.bufferNum; i++) { +// const BufferBarrierDesc& in = barrierGroupDesc.buffers[i]; +// const BufferMTL& bufferImpl = *(const BufferMTL*)in.buffer; +// resourceBarrier[barrierCount++] = bufferImpl.GetHandle(); +// } +// +// for(size_t i = 0; i < barrierGroupDesc.textureNum; i++) { +// const TextureBarrierDesc& in = barrierGroupDesc.textures[i]; +// const TextureMTL& textureImpl = *(const TextureMTL*)in.texture; +// resourceBarrier[barrierCount++] = textureImpl.GetHandle(); +// } + +// [m_RendererEncoder memoryBarrierWithResources: resourceBarrier +// count: barrierCount +// afterStages: MTLRenderStageFragment +// beforeStages: MTLRenderStageVertex]; +} +void CommandBufferMTL::BeginRendering(const AttachmentsDesc& attachmentsDesc) { + m_renderPassDescriptor = [MTLRenderPassDescriptor alloc]; + + for(uint32_t i = 0; i < attachmentsDesc.colorNum; i++) { + DescriptorMTL& descriptorMTL = *(DescriptorMTL*)attachmentsDesc.colors[i]; + + m_renderPassDescriptor.colorAttachments[i].texture = descriptorMTL.GetTextureHandle(); + m_renderPassDescriptor.colorAttachments[i].clearColor = MTLClearColorMake(0, 0, 0, 1); + m_renderPassDescriptor.colorAttachments[i].loadAction = MTLLoadActionLoad; + m_renderPassDescriptor.colorAttachments[i].storeAction = MTLStoreActionStore; + + } + + if(attachmentsDesc.depthStencil) { + DescriptorMTL& descriptorMTL = *(DescriptorMTL*)attachmentsDesc.depthStencil; + m_renderPassDescriptor.depthAttachment.texture = descriptorMTL.GetTextureHandle(); + m_renderPassDescriptor.depthAttachment.loadAction = MTLLoadActionLoad; + m_renderPassDescriptor.depthAttachment.storeAction = MTLStoreActionStore; + } +} + +void CommandBufferMTL::EndRendering() { + EndCurrentEncoders(); + m_numScissors = 0; + m_numViewports = 0; + m_DirtyBits = CommandBufferDirtyBits::NONE; +} + +void CommandBufferMTL::SetViewports(const Viewport* viewports, uint32_t viewportNum) { + for(size_t i = 0; i < viewportNum; i++) { + m_Viewports[i].originX = viewports[i].x; + m_Viewports[i].originY = viewports[i].y; + m_Viewports[i].width = viewports[i].width; + m_Viewports[i].height = viewports[i].height; + m_Viewports[i].znear = viewports[i].depthMin; + m_Viewports[i].zfar = viewports[i].depthMax; + } + m_numViewports = viewportNum; + if(m_RendererEncoder && m_numViewports > 0) + [m_RendererEncoder + setViewports: m_Viewports + count: m_numViewports]; +} + + +void CommandBufferMTL::SetScissors(const Rect* rects, uint32_t rectNum) { + for(size_t i = 0; i < rectNum; i++) { + m_Scissors[i].x = rects[i].x; + m_Scissors[i].y = rects[i].y; + m_Scissors[i].width = rects[i].width; + m_Scissors[i].height = rects[i].height; + } + m_numScissors = rectNum; + if(m_RendererEncoder && m_numScissors > 0) + [m_RendererEncoder + setScissorRects: m_Scissors + count: m_numScissors]; + +} +void CommandBufferMTL::SetDepthBounds(float boundsMin, float boundsMax) { + //[m_RendererEncoder set] +} +void CommandBufferMTL::SetStencilReference(uint8_t frontRef, uint8_t backRef) { + m_DirtyBits |= CommandBufferDirtyBits::CMD_DIRTY_STENCIL; + m_StencilFront = frontRef; + m_StencilBack = backRef; + if (m_RendererEncoder) + [m_RendererEncoder + setStencilFrontReferenceValue: frontRef + backReferenceValue: backRef]; +} + +void CommandBufferMTL::SetBlendConstants(const Color32f& color) { + m_BlendColor = color; + m_DirtyBits |= CommandBufferDirtyBits::CMD_DIRTY_BLEND_CONSTANT; + if (m_RendererEncoder) + [m_RendererEncoder setBlendColorRed: m_BlendColor.x + green: m_BlendColor.y + blue: m_BlendColor.z + alpha: m_BlendColor.w]; + + +} +void CommandBufferMTL::SetShadingRate(const ShadingRateDesc& shadingRateDesc) { + m_shadingRateDesc = shadingRateDesc; + m_DirtyBits |= CommandBufferDirtyBits::CMD_DIRTY_SHADING_RATE; +} + +void CommandBufferMTL::ClearAttachments(const ClearDesc* clearDescs, uint32_t clearDescNum, const Rect* rects, uint32_t rectNum) { + MTLRenderPassDescriptor* renderPassDesc = [MTLRenderPassDescriptor alloc]; + id rendererEncoder = [m_Handle renderCommandEncoderWithDescriptor: renderPassDesc]; + + simd::float4 vertices[6 * 16]; + size_t vtxIndex= 0; + simd::float4 clearColors[16]; + + for(size_t i = 0; i < clearDescNum; i++) { + + simd::float2 srcBL = simd_make_float2(rects[i].x / m_Viewports[i].width, + (rects[i].y + rects[i].height) / m_Viewports[i].height); + simd::float2 srcTR = simd_make_float2((rects[i].x + rects[i].width) / m_Viewports[i].width, + rects[i].y / m_Viewports[i].height); + + float leftPos = rects[i].x / m_Viewports[i].width; + float rightPos = (rects[i].width / m_Viewports[i].width) + leftPos; + float bottomPos = rects[i].y / m_Viewports[i].height; + float topPos = (rects[i].height / m_Viewports[i].height) + bottomPos; + + clearColors[i] = simd_make_float4( + clearDescs[i].value.color.f.x, + clearDescs[i].value.color.f.y, + clearDescs[i].value.color.f.z, + clearDescs[i].value.color.f.w); + + simd::float4 vtx; + vtx.z = 0.0; + vtx.w = clearDescs[i].colorAttachmentIndex; + + // Top left vertex - First triangle + vtx.y = topPos; + vtx.x = leftPos; + vertices[vtxIndex++] = vtx; + + // Bottom left vertex + vtx.y = bottomPos; + vtx.x = leftPos; + vertices[vtxIndex++] = vtx; + + // Bottom right vertex + vtx.y = bottomPos; + vtx.x = rightPos; + vertices[vtxIndex++] = vtx; + + // Bottom right vertex - Second triangle + vertices[vtxIndex++] = vtx; + + // Top right vertex + vtx.y = topPos; + vtx.x = rightPos; + vertices[vtxIndex++] = vtx; + + // Top left vertex + vtx.y = topPos; + vtx.x = leftPos; + vertices[vtxIndex++] = vtx; + } + + if(m_numViewports > 0) + [rendererEncoder + setViewports: m_Viewports + count: m_numViewports]; + + [rendererEncoder setCullMode: MTLCullModeNone]; + [rendererEncoder setTriangleFillMode: MTLTriangleFillModeFill]; + [rendererEncoder setDepthBias: 0 slopeScale: 0 clamp: 0]; + [rendererEncoder setRenderPipelineState: m_Device.GetClearPipeline(clearDescs, clearDescNum)]; + [rendererEncoder setVertexBytes: vertices length: vtxIndex atIndex: 0]; + [rendererEncoder drawPrimitives: MTLPrimitiveTypeTriangle vertexStart: 0 vertexCount: vtxIndex]; + [rendererEncoder endEncoding]; + +} + +void CommandBufferMTL::EndCurrentEncoders() { + if(m_RendererEncoder) { + [m_RendererEncoder endEncoding]; + m_RendererEncoder = nil; + } + + if(m_ComputeEncoder) { + [m_ComputeEncoder endEncoding]; + m_ComputeEncoder = nil; + } + + if(m_BlitEncoder) { + [m_BlitEncoder endEncoding]; + m_BlitEncoder = nil; + } +} + +void CommandBufferMTL::SetIndexBuffer(const Buffer& buffer, uint64_t offset, IndexType indexType) { + m_indexBuffer.m_Buffer = &(BufferMTL&)buffer; + switch(indexType) { + case IndexType::UINT16: + m_indexBuffer.m_Type = MTLIndexType::MTLIndexTypeUInt16; + break; + default: + case IndexType::UINT32: + m_indexBuffer.m_Type = MTLIndexType::MTLIndexTypeUInt32; + break; + } + m_indexBuffer.m_Offset = offset; +} + + +void CommandBufferMTL::SetVertexBuffers(uint32_t baseSlot, uint32_t bufferNum, const Buffer* const* buffers, const uint64_t* offsets) { + for(size_t i = 0; i < bufferNum; i++) { + BufferMTL* mtlBuffer = (BufferMTL*)buffers[i]; + + const size_t slotIndex = i + baseSlot; + m_vertexBuffers[slotIndex].m_Offset = offsets[i]; + m_vertexBuffers[slotIndex].m_Buffer = mtlBuffer; + m_dirtyVertexBufferBits |= (1 << slotIndex); + + if(m_RendererEncoder) + [m_RendererEncoder setVertexBuffer: mtlBuffer->GetHandle() + offset: offsets[i] + atIndex: i + baseSlot]; + } + +} + +void CommandBufferMTL::Draw(const DrawDesc& drawDesc) { + [m_RendererEncoder drawPrimitives: m_CurrentPipeline->GetPrimitiveType() + vertexStart:drawDesc.baseVertex + vertexCount:drawDesc.vertexNum + instanceCount:drawDesc.instanceNum + baseInstance: drawDesc.baseInstance]; + +} + +void CommandBufferMTL::DrawIndexed(const DrawIndexedDesc& drawIndexedDesc) { + id indexBuffer = m_indexBuffer.m_Buffer->GetHandle(); + [m_RendererEncoder drawIndexedPrimitives: m_CurrentPipeline->GetPrimitiveType() + indexCount: drawIndexedDesc.indexNum + indexType: m_indexBuffer.m_Type + indexBuffer: indexBuffer + indexBufferOffset: m_indexBuffer.m_Offset]; +} + +void CommandBufferMTL::DrawIndirect(const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride, const Buffer* countBuffer, uint64_t countBufferOffset) { + InsertBarriers(); + [m_RendererEncoder + drawPrimitives: m_CurrentPipeline->GetPrimitiveType() + indirectBuffer:((BufferMTL&)buffer).GetHandle() + indirectBufferOffset: offset]; +} +void CommandBufferMTL::DrawIndexedIndirect(const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride, const Buffer* countBuffer, uint64_t countBufferOffset) { + InsertBarriers(); + + id indexBuffer = m_indexBuffer.m_Buffer->GetHandle(); + const BufferMTL& bufferImpl = (const BufferMTL&)buffer; + [m_RendererEncoder drawIndexedPrimitives: m_CurrentPipeline->GetPrimitiveType() + indexCount: drawNum + indexType: m_indexBuffer.m_Type + indexBuffer: indexBuffer + indexBufferOffset: m_indexBuffer.m_Offset + ]; +} +void CommandBufferMTL::Dispatch(const DispatchDesc& dispatchDesc) { + InsertBarriers(); + + MTLSize threadgroupCount = MTLSizeMake(dispatchDesc.x, dispatchDesc.y, dispatchDesc.z); +// MTLSize threadPerThreadGroup = MTLSizeMake(dispatchDesc.x, dispatchDesc.y, dispatchDesc.z); +// [m_ComputeEncoder +// dispatchThreadgroups: threadgroupCount +// threadsPerThreadgroup: threadPerThreadGroup]; +} +void CommandBufferMTL::DispatchIndirect(const Buffer& buffer, uint64_t offset) { + InsertBarriers(); + + const BufferMTL& bufferImpl = (const BufferMTL&)buffer; + id dispatchBuffer = bufferImpl.GetHandle(); +// MTLSize threadPerThreadGroup = MTLSizeMake(0, 0, 0); +// [m_ComputeEncoder +// dispatchThreadgroupsWithIndirectBuffer: dispatchBuffer +// indirectBufferOffset: offset +// threadsPerThreadgroup: threadPerThreadGroup]; +} +void CommandBufferMTL::BeginQuery(const QueryPool& queryPool, uint32_t offset) { + +} +void CommandBufferMTL::EndQuery(const QueryPool& queryPool, uint32_t offset) { + +} + + +void CommandBufferMTL::BeginAnnotation(const char* name) { + if(m_RendererEncoder) { + [m_RendererEncoder pushDebugGroup: [NSString stringWithUTF8String:name]]; + return; + } + + if(m_ComputeEncoder) { + [m_ComputeEncoder pushDebugGroup: [NSString stringWithUTF8String:name]]; + return; + } + + if(m_BlitEncoder) { + [m_BlitEncoder pushDebugGroup: [NSString stringWithUTF8String:name]]; + return; + } + + [m_Annotations addObject: [NSString stringWithUTF8String:name]]; + +} +void CommandBufferMTL::EndAnnotation() { + if(m_RendererEncoder) { + [m_RendererEncoder popDebugGroup]; + return; + } + + if(m_ComputeEncoder) { + [m_ComputeEncoder popDebugGroup]; + return; + } + + if(m_BlitEncoder) { + [m_BlitEncoder popDebugGroup]; + return; + } + [m_Annotations addObject: [NSNull null]]; +// m_DirtyBits |= CommandBufferDirtyBits::CMD_DIRTY_END_ANNOTATION; +} +void CommandBufferMTL::ClearStorageBuffer(const ClearStorageBufferDesc& clearDesc) { + +} +void CommandBufferMTL::ClearStorageTexture(const ClearStorageTextureDesc& clearDesc) { + +} + +void CommandBufferMTL::CopyBuffer(Buffer& dstBuffer, uint64_t dstOffset, const Buffer& srcBuffer, uint64_t srcOffset, uint64_t size) { + const BufferMTL& src = (const BufferMTL&)srcBuffer; + const BufferMTL& dst = (const BufferMTL&)dstBuffer; + + if(!m_BlitEncoder) { + EndCurrentEncoders(); + m_BlitEncoder = [m_Handle blitCommandEncoder]; + } + + [m_BlitEncoder + copyFromBuffer:src.GetHandle() + sourceOffset:srcOffset + toBuffer: dst.GetHandle() + destinationOffset:dstOffset + size:size]; +} + +void CommandBufferMTL::CopyTexture(Texture& dstTexture, const TextureRegionDesc* dstRegionDesc, const Texture& srcTexture, const TextureRegionDesc* srcRegionDesc) { + const TextureMTL& src = (const TextureMTL&)srcTexture; + const TextureMTL& dst = (const TextureMTL&)dstTexture; + if(!m_BlitEncoder) { + EndCurrentEncoders(); + m_BlitEncoder = [m_Handle blitCommandEncoder]; + } + + bool isWholeResource = !dstRegionDesc && !srcRegionDesc; + if (isWholeResource) { + [m_BlitEncoder + copyFromTexture: src.GetHandle() + toTexture: dst.GetHandle()]; + } else { + TextureRegionDesc wholeResource = {}; + if (!srcRegionDesc) + srcRegionDesc = &wholeResource; + if (!dstRegionDesc) + dstRegionDesc = &wholeResource; + const MTLSize sourceSize = MTLSizeMake( + (srcRegionDesc->width == WHOLE_SIZE) ? src.GetSize(0, srcRegionDesc->mipOffset) : srcRegionDesc->width, + (srcRegionDesc->height == WHOLE_SIZE) ? src.GetSize(1, srcRegionDesc->mipOffset) : srcRegionDesc->height, + (srcRegionDesc->depth == WHOLE_SIZE) ? src.GetSize(2, srcRegionDesc->mipOffset) : srcRegionDesc->depth + ); + + // Copy to the texture's final subresourc e. + [m_BlitEncoder copyFromTexture: src.GetHandle() + sourceSlice: srcRegionDesc->layerOffset + sourceLevel: srcRegionDesc->mipOffset + sourceOrigin: MTLOriginMake(srcRegionDesc->x, srcRegionDesc->y, srcRegionDesc->z) + sourceSize: sourceSize + toTexture: dst.GetHandle() + destinationSlice: dstRegionDesc->layerOffset + destinationLevel: dstRegionDesc->mipOffset + destinationOrigin: MTLOriginMake(dstRegionDesc->x, dstRegionDesc->y, dstRegionDesc->z) + ]; + } +} +void CommandBufferMTL::UploadBufferToTexture(Texture& dstTexture, const TextureRegionDesc& dstRegionDesc, const Buffer& srcBuffer, const TextureDataLayoutDesc& srcDataLayoutDesc) { + const BufferMTL& src = (const BufferMTL&)srcBuffer; + const TextureMTL& dst = (const TextureMTL&)dstTexture; + + if(!m_BlitEncoder) { + EndCurrentEncoders(); + m_BlitEncoder = [m_Handle blitCommandEncoder]; + } + + const MTLSize sourceSize = MTLSizeMake( + (dstRegionDesc.width == WHOLE_SIZE) ? dst.GetSize(0, dstRegionDesc.mipOffset) : dstRegionDesc.width, + (dstRegionDesc.height == WHOLE_SIZE) ? dst.GetSize(1, dstRegionDesc.mipOffset) : dstRegionDesc.height, + (dstRegionDesc.depth == WHOLE_SIZE) ? dst.GetSize(2, dstRegionDesc.mipOffset) : dstRegionDesc.depth + ); + [m_BlitEncoder + copyFromBuffer: src.GetHandle() + sourceOffset: srcDataLayoutDesc.offset + sourceBytesPerRow: srcDataLayoutDesc.rowPitch + sourceBytesPerImage: srcDataLayoutDesc.slicePitch + sourceSize: sourceSize + toTexture: dst.GetHandle() + destinationSlice: dstRegionDesc.layerOffset + destinationLevel: dstRegionDesc.mipOffset + destinationOrigin: MTLOriginMake(dstRegionDesc.x, dstRegionDesc.y, dstRegionDesc.z) + options: MTLBlitOptionNone]; +} +void CommandBufferMTL::ReadbackTextureToBuffer(Buffer& dstBuffer, const TextureDataLayoutDesc& dstDataLayoutDesc, const Texture& srcTexture, const TextureRegionDesc& srcRegionDesc) { + const TextureMTL& src = (const TextureMTL&)srcTexture; + const BufferMTL& dst = (const BufferMTL&)dstBuffer; + + if(!m_BlitEncoder) { + EndCurrentEncoders(); + m_BlitEncoder = [m_Handle blitCommandEncoder]; + } + + const MTLSize sourceSize = MTLSizeMake( + (srcRegionDesc.width == WHOLE_SIZE) ? src.GetSize(0, srcRegionDesc.mipOffset) : srcRegionDesc.width, + (srcRegionDesc.height == WHOLE_SIZE) ? src.GetSize(1, srcRegionDesc.mipOffset) : srcRegionDesc.height, + (srcRegionDesc.depth == WHOLE_SIZE) ? src.GetSize(2, srcRegionDesc.mipOffset) : srcRegionDesc.depth + ); + [m_BlitEncoder copyFromTexture: src.GetHandle() + sourceSlice: srcRegionDesc.layerOffset + sourceLevel: srcRegionDesc.mipOffset + sourceOrigin: MTLOriginMake(srcRegionDesc.x, srcRegionDesc.y, srcRegionDesc.z) + sourceSize: sourceSize + toBuffer: dst.GetHandle() + destinationOffset: dstDataLayoutDesc.offset + destinationBytesPerRow: dstDataLayoutDesc.rowPitch + destinationBytesPerImage: dstDataLayoutDesc.slicePitch + options: MTLBlitOptionNone]; +} +void CommandBufferMTL::CopyQueries(const QueryPool& queryPool, uint32_t offset, uint32_t num, Buffer& dstBuffer, uint64_t dstOffset) {} +void CommandBufferMTL::ResetQueries(const QueryPool& queryPool, uint32_t offset, uint32_t num) {} +void CommandBufferMTL::BuildTopLevelAccelerationStructure(uint32_t instanceNum, const Buffer& buffer, uint64_t bufferOffset, AccelerationStructureBuildBits flags, AccelerationStructure& dst, Buffer& scratch, uint64_t scratchOffset) {} +void CommandBufferMTL::BuildBottomLevelAccelerationStructure(uint32_t geometryObjectNum, const GeometryObject* geometryObjects, AccelerationStructureBuildBits flags, AccelerationStructure& dst, Buffer& scratch, uint64_t scratchOffset) {} +void CommandBufferMTL::UpdateTopLevelAccelerationStructure(uint32_t instanceNum, const Buffer& buffer, uint64_t bufferOffset, AccelerationStructureBuildBits flags, AccelerationStructure& dst, AccelerationStructure& src, Buffer& scratch, uint64_t scratchOffset) {} +void CommandBufferMTL::UpdateBottomLevelAccelerationStructure(uint32_t geometryObjectNum, const GeometryObject* geometryObjects, AccelerationStructureBuildBits flags, AccelerationStructure& dst, AccelerationStructure& src, Buffer& scratch, uint64_t scratchOffset) {} +void CommandBufferMTL::CopyAccelerationStructure(AccelerationStructure& dst, AccelerationStructure& src, CopyMode copyMode) {} +void CommandBufferMTL::WriteAccelerationStructureSize(const AccelerationStructure* const* accelerationStructures, uint32_t accelerationStructureNum, QueryPool& queryPool, uint32_t queryPoolOffset) {} +void CommandBufferMTL::DispatchRays(const DispatchRaysDesc& dispatchRaysDesc) {} +void CommandBufferMTL::DispatchRaysIndirect(const Buffer& buffer, uint64_t offset) {} +void CommandBufferMTL::DrawMeshTasks(const DrawMeshTasksDesc& drawMeshTasksDesc) {} +void CommandBufferMTL::DrawMeshTasksIndirect(const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride) { + +} + + +void CommandBufferMTL::Create(const struct CommandQueueMTL* queue) { + m_CommandQueue = queue; + MTLCommandBufferDescriptor* pDesc = [[MTLCommandBufferDescriptor alloc] init]; + pDesc.errorOptions = MTLCommandBufferErrorOptionEncoderExecutionStatus; + m_Handle = [m_CommandQueue->GetHandle() commandBufferWithDescriptor: pDesc]; + +} + +#include "CommandBufferMTL.hpp" + diff --git a/Source/Metal/CommandQueueMTL.h b/Source/Metal/CommandQueueMTL.h new file mode 100644 index 00000000..e11f016b --- /dev/null +++ b/Source/Metal/CommandQueueMTL.h @@ -0,0 +1,51 @@ +// © 2021 NVIDIA Corporation +#pragma once + +#import + +namespace nri { + +struct DeviceMTL; + +struct CommandQueueMTL { + + inline CommandQueueMTL(DeviceMTL& device) + : m_Device(device) { + } + + ~CommandQueueMTL(); + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + inline CommandQueueType GetType() const { + return m_Type; + } + + inline Lock& GetLock() { + return m_Lock; + } + + inline id GetHandle() const { + return m_Handle; + } + + void SetDebugName(const char* name); + void Submit(const QueueSubmitDesc& queueSubmitDesc, const SwapChain* swapChain); + Result UploadData(const TextureUploadDesc* textureUploadDescs, uint32_t textureUploadDescNum, const BufferUploadDesc* bufferUploadDescs, uint32_t bufferUploadDescNum); + Result WaitForIdle(); + + Result Create(CommandQueueType type); + +private: + DeviceMTL& m_Device; + CommandQueueType m_Type = CommandQueueType(-1); + id m_Handle; + Lock m_Lock; + +}; + +} + + diff --git a/Source/Metal/CommandQueueMTL.mm b/Source/Metal/CommandQueueMTL.mm new file mode 100644 index 00000000..6f35d7f2 --- /dev/null +++ b/Source/Metal/CommandQueueMTL.mm @@ -0,0 +1,60 @@ +// © 2021 NVIDIA Corporation + +#include "SharedMTL.h" + +#include "CommandQueueMTL.h" +#include "CommandBufferMTL.h" + +#include "HelperDataUpload.h" + +using namespace nri; + +CommandQueueMTL::~CommandQueueMTL() { + m_Handle = nil; +} + +Result CommandQueueMTL::Create(CommandQueueType type) { + m_Type = type; + const char* queueNames[] = { + "GRAPHICS_QUEUE", // GRAPHICS + "TRANSFER_QUEUE", // TRANSFER + "COMPUTE_QUEUE" // COMPUTE + }; + + m_Handle = [m_Device newCommandQueueWithMaxCommandBufferCount:512]; + SetDebugName(queueNames[(uint32_t)type]); + + return Result::SUCCESS; +} + + +void CommandQueueMTL::Submit(const QueueSubmitDesc& queueSubmitDesc, const SwapChain* swapChain) { + + for(uint32_t i = 0; i < queueSubmitDesc.commandBufferNum; i++) { + const struct CommandBufferMTL& cmd = (const CommandBufferMTL&)queueSubmitDesc.commandBuffers[i]; + [cmd.GetHandle() commit]; + } +} + + +void CommandQueueMTL::SetDebugName(const char* name) { + [m_Handle setLabel:[NSString stringWithUTF8String:name]]; +} + + + +Result CommandQueueMTL::UploadData(const TextureUploadDesc* textureUploadDescs, uint32_t textureUploadDescNum, const BufferUploadDesc* bufferUploadDescs, uint32_t bufferUploadDescNum) { + HelperDataUpload helperDataUpload(m_Device.GetCoreInterface(), (Device&)m_Device, (CommandQueue&)*this); + + return helperDataUpload.UploadData(textureUploadDescs, textureUploadDescNum, bufferUploadDescs, bufferUploadDescNum); +} + +Result CommandQueueMTL::WaitForIdle() { + + id waitCmdBuf = [m_Handle commandBufferWithUnretainedReferences]; + + [waitCmdBuf commit]; + [waitCmdBuf waitUntilCompleted]; + + waitCmdBuf = nil; +} diff --git a/Source/Metal/ConversionMTL.h b/Source/Metal/ConversionMTL.h new file mode 100644 index 00000000..57f62fff --- /dev/null +++ b/Source/Metal/ConversionMTL.h @@ -0,0 +1,302 @@ +#pragma once + +#include + +namespace nri { + +constexpr std::array DEFAULT_MEMORY_RESOURCE_OPTION_MEMORY_LOCATION ={ + MTLResourceStorageModePrivate, // DEVICE + MTLResourceStorageModeShared | MTLResourceCPUCacheModeWriteCombined, // DEVICE_UPLOAD + MTLResourceStorageModeShared | MTLResourceCPUCacheModeWriteCombined, // HOST_UPLOAD + MTLResourceStorageModeShared | MTLResourceCPUCacheModeDefaultCache // HOST_READBACK +}; + +constexpr std::array DEFAULT_CACHE_MODE_MEMORY_LOCATION ={ + MTLCPUCacheModeDefaultCache, // DEVICE + MTLCPUCacheModeWriteCombined, // DEVICE_UPLOAD + MTLCPUCacheModeWriteCombined, // HOST_UPLOAD + MTLCPUCacheModeDefaultCache // HOST_READBACK +}; + +constexpr std::array DEFAULT_STORAGE_MODE_MEMORY_LOCATION ={ + MTLStorageModePrivate, // DEVICE + MTLStorageModeShared, // DEVICE_UPLOAD + MTLStorageModeShared, // HOST_UPLOAD + MTLStorageModeShared // HOST_READBACK +}; + + +constexpr std::array MTL_NRI_FORMAT_TO_VERTEX_FORMAT = { + MTLVertexFormatInvalid, // UNKNOWN + MTLVertexFormatUCharNormalized, // R8_UNORM + MTLVertexFormatCharNormalized, // R8_SNORM + MTLVertexFormatUChar, // R8_UINT + MTLVertexFormatChar, // R8_SINT + MTLVertexFormatUChar2Normalized, // RG8_UNORM + MTLVertexFormatChar2Normalized, // RG8_SNORM + MTLVertexFormatUChar2, // RG8_UINT + MTLVertexFormatChar2, // RG8_SINT + MTLVertexFormatUChar4Normalized, // BGRA8_UNORM + MTLVertexFormatInvalid, // BGRA8_SRGB + MTLVertexFormatUChar4Normalized, // RGBA8_UNORM + MTLVertexFormatInvalid, // RGBA8_SRGB + MTLVertexFormatChar4Normalized, // RGBA8_SNORM + MTLVertexFormatUChar4, // RGBA8_UINT + MTLVertexFormatChar4, // RGBA8_SINT + MTLVertexFormatUShortNormalized, // R16_UNORM + MTLVertexFormatShortNormalized, // R16_SNORM + MTLVertexFormatUShort, // R16_UINT + MTLVertexFormatShort, // R16_SINT + MTLVertexFormatHalf, // R16_SFLOAT + MTLVertexFormatUShort2Normalized, // RG16_UNORM + MTLVertexFormatShort2Normalized, // RG16_SNORM + MTLVertexFormatUShort2, // RG16_UINT + MTLVertexFormatShort2, // RG16_SINT + MTLVertexFormatHalf2, // RG16_SFLOAT + MTLVertexFormatUShort4Normalized, // RGBA16_UNORM + MTLVertexFormatShort4Normalized, // RGBA16_SNORM + MTLVertexFormatUShort4, // RGBA16_UINT + MTLVertexFormatShort4, // RGBA16_SINT + MTLVertexFormatHalf4, // RGBA16_SFLOAT + MTLVertexFormatUInt, // R32_UINT + MTLVertexFormatInt, // R32_SINT + MTLVertexFormatFloat, // R32_SFLOAT + MTLVertexFormatUInt2, // RG32_UINT + MTLVertexFormatInt2, // RG32_SINT + MTLVertexFormatFloat2, // RG32_SFLOAT + MTLVertexFormatInvalid, // RGB32_UINT //TODO: lookup correct values + MTLVertexFormatInvalid, // RGB32_SINT //TODO: lookup correct values + MTLVertexFormatInvalid, // RGB32_SFLOAT //TODO: lookup correct values + MTLVertexFormatUInt4, // RGBA32_UINT + MTLVertexFormatInt4, // RGBA32_SINT + MTLVertexFormatFloat4, // RGBA32_SFLOAT + MTLVertexFormatInvalid, // B5_G6_R5_UNORM + MTLVertexFormatInvalid, // B5_G5_R5_A1_UNORM + MTLVertexFormatInvalid, // B4_G4_R4_A4_UNORM + MTLVertexFormatInvalid, // R10_G10_B10_A2_UNORM + MTLVertexFormatInvalid, // R10_G10_B10_A2_UINT + MTLVertexFormatInvalid, // R11_G11_B10_UFLOAT + MTLVertexFormatInvalid, // R9_G9_B9_E5_UFLOAT + MTLVertexFormatInvalid, // BC1_RGBA_UNORM + MTLVertexFormatInvalid, // BC1_RGBA_SRGB + MTLVertexFormatInvalid, // BC2_RGBA_UNORM + MTLVertexFormatInvalid, // BC2_RGBA_SRGB + MTLVertexFormatInvalid, // BC3_RGBA_UNORM + MTLVertexFormatInvalid, // BC3_RGBA_SRGB + MTLVertexFormatInvalid, // BC4_R_UNORM + MTLVertexFormatInvalid, // BC4_R_SNORM + MTLVertexFormatInvalid, // BC5_RG_UNORM + MTLVertexFormatInvalid, // BC5_RG_SNORM + MTLVertexFormatInvalid, // BC6H_RGB_UFLOAT + MTLVertexFormatInvalid, // BC6H_RGB_SFLOAT + MTLVertexFormatInvalid, // BC7_RGBA_UNORM + MTLVertexFormatInvalid, // BC7_RGBA_SRGB + MTLVertexFormatInvalid, // D16_UNORM + MTLVertexFormatInvalid, // D24_UNORM_S8_UINT + MTLVertexFormatInvalid, // D32_SFLOAT + MTLVertexFormatInvalid, // D32_SFLOAT_S8_UINT_X24 + MTLVertexFormatInvalid, // R24_UNORM_X8 + MTLVertexFormatInvalid, // X24_G8_UINT + MTLVertexFormatInvalid, // R32_SFLOAT_X8_X24 + MTLVertexFormatInvalid, // X32_G8_UINT_X24 +}; + +constexpr std::array BLEND_OP = { + MTLBlendOperationAdd, // ADD + MTLBlendOperationSubtract, // SUBTRACT + MTLBlendOperationReverseSubtract, // REVERSE_SUBTRACT + MTLBlendOperationMin, // MIN + MTLBlendOperationMax // MAX +}; +constexpr MTLBlendOperation GetBlendOp(BlendFunc blendFunc) { + return BLEND_OP[(size_t)blendFunc]; +} + +constexpr std::array IMAGE_TYPES = { + MTLTextureType1D, // TEXTURE_1D + MTLTextureType2D, // TEXTURE_2D + MTLTextureType3D, // TEXTURE_3D +}; + +constexpr MTLTextureType GetImageTypeMTL(TextureType type) { + return IMAGE_TYPES[(size_t)type]; +} + +constexpr std::array BLEND_FACTOR = { + MTLBlendFactorZero, // ZERO + MTLBlendFactorOne, // ONE + MTLBlendFactorSourceColor, // SRC_COLOR + MTLBlendFactorOneMinusSourceColor, // ONE_MINUS_SRC_COLOR + MTLBlendFactorDestinationColor, // DST_COLOR + MTLBlendFactorOneMinusDestinationColor, // ONE_MINUS_DST_COLOR + MTLBlendFactorSourceAlpha, // SRC_ALPHA + MTLBlendFactorOneMinusSourceAlpha, // ONE_MINUS_SRC_ALPHA + MTLBlendFactorDestinationAlpha, // DST_ALPHA + MTLBlendFactorOneMinusDestinationAlpha, // ONE_MINUS_DST_ALPHA + MTLBlendFactorBlendColor, // CONSTANT_COLOR + MTLBlendFactorOneMinusBlendColor, // ONE_MINUS_CONSTANT_COLOR + MTLBlendFactorBlendAlpha, // CONSTANT_ALPHA + MTLBlendFactorOneMinusBlendAlpha, // ONE_MINUS_CONSTANT_ALPHA + MTLBlendFactorSourceAlphaSaturated, // SRC_ALPHA_SATURATE + MTLBlendFactorSource1Color, // SRC1_COLOR + MTLBlendFactorOneMinusSource1Color, // ONE_MINUS_SRC1_COLOR + MTLBlendFactorSource1Alpha, // SRC1_ALPHA + MTLBlendFactorOneMinusSource1Alpha, // ONE_MINUS_SRC1_ALPHA +}; + +constexpr MTLBlendFactor GetBlendFactor(BlendFactor blendFactor) { + return BLEND_FACTOR[(size_t)blendFactor]; +} + +constexpr MTLColorWriteMask GetColorComponent(ColorWriteBits colorWriteMask) { + return MTLColorWriteMask(colorWriteMask) & MTLColorWriteMaskAll; +} + +constexpr std::array DESCRIPTOR_TYPES = { + MTLDataTypeSampler, // SAMPLER + MTLDataTypeNone, // CONSTANT_BUFFER + MTLDataTypeTexture, // TEXTURE + MTLDataTypeNone, // STORAGE_TEXTURE + MTLDataTypeStruct, // BUFFER + MTLDataTypeStruct, // STORAGE_BUFFER + MTLDataTypeArray, // STRUCTURED_BUFFER + MTLDataTypeStruct, // STORAGE_STRUCTURED_BUFFER + MTLDataTypePrimitiveAccelerationStructure // ACCELERATION_STRUCTURE +}; + +constexpr MTLDataType GetDescriptorType(DescriptorType type) { + return DESCRIPTOR_TYPES[(size_t)type]; +} + + + +constexpr std::array COMPARE_OP = { + MTLCompareFunctionNever, // NONE + MTLCompareFunctionAlways, // ALWAYS + MTLCompareFunctionNever, // NEVER + MTLCompareFunctionEqual, // EQUAL + MTLCompareFunctionNotEqual, // NOT_EQUAL + MTLCompareFunctionLess, // LESS + MTLCompareFunctionLessEqual, // LESS_EQUAL + MTLCompareFunctionGreater, // GREATER + MTLCompareFunctionGreaterEqual, // GREATER_EQUAL +}; + +constexpr MTLCompareFunction GetCompareOp(CompareFunc compareFunc) { + return COMPARE_OP[(size_t)compareFunc]; +} + +constexpr std::array STENCIL_OP = { + MTLStencilOperationKeep, // KEEP + MTLStencilOperationZero, // ZERO + MTLStencilOperationReplace, // REPLACE + MTLStencilOperationIncrementClamp, // INCREMENT_AND_CLAMP + MTLStencilOperationDecrementClamp, // DECREMENT_AND_CLAMP + MTLStencilOperationInvert, // INVERT + MTLStencilOperationIncrementWrap, // INCREMENT_AND_WRAP + MTLStencilOperationDecrementWrap // DECREMENT_AND_WRAP +}; + +constexpr MTLStencilOperation GetStencilOp(StencilFunc stencilFunc) { + return STENCIL_OP[(size_t)stencilFunc]; +} + + +constexpr std::array CULL_MODES = { + MTLCullModeNone, // NONE + MTLCullModeFront, // FRONT + MTLCullModeBack // BACK +}; + +constexpr MTLCullMode GetCullMode(CullMode cullMode) { + return CULL_MODES[(size_t)cullMode]; +} + +constexpr std::array POLYGON_MODES = { + MTLTriangleFillModeFill, // SOLID + MTLTriangleFillModeLines // WIREFRAME +}; + +constexpr MTLTriangleFillMode GetPolygonMode(FillMode fillMode) { + return POLYGON_MODES[(size_t)fillMode]; +} + +constexpr std::array SAMPLER_ADDRESS_MODE = { + MTLSamplerAddressModeRepeat, // REPEAT, + MTLSamplerAddressModeMirrorRepeat, // MIRRORED_REPEAT, + MTLSamplerAddressModeClampToEdge, // CLAMP_TO_EDGE, + MTLSamplerAddressModeClampToBorderColor, // CLAMP_TO_BORDER, + MTLSamplerAddressModeClampToEdge // MIRROR_CLAMP_TO_EDGE +}; + +constexpr std::array MIN_MAG_FILTER = { + MTLSamplerMinMagFilterNearest, // NEAREST + MTLSamplerMinMagFilterLinear // LINEAR +}; + +constexpr MTLSamplerMinMagFilter GetFilter(Filter filter) { + return MIN_MAG_FILTER[(size_t)filter]; +} + +constexpr MTLSamplerAddressMode GetSamplerAddressMode(AddressMode addressMode) { + return SAMPLER_ADDRESS_MODE[(size_t)addressMode]; +} + +constexpr std::array TOPOLOGIES_CLASSES = { + MTLPrimitiveTopologyClassPoint, // POINT_LIST + MTLPrimitiveTopologyClassLine, // LINE_LIST + MTLPrimitiveTopologyClassLine, // LINE_STRIP + MTLPrimitiveTopologyClassTriangle, // TRIANGLE_LIST + MTLPrimitiveTopologyClassTriangle, // TRIANGLE_STRIP + MTLPrimitiveTopologyClassLine, // LINE_LIST_WITH_ADJACENCY + MTLPrimitiveTopologyClassLine, // LINE_STRIP_WITH_ADJACENCY + MTLPrimitiveTopologyClassTriangle, // TRIANGLE_LIST_WITH_ADJACENCY + MTLPrimitiveTopologyClassTriangle, // TRIANGLE_STRIP_WITH_ADJACENCY + MTLPrimitiveTopologyClassTriangle // PATCH_LIST TODO: not sure +}; + + +constexpr MTLPrimitiveTopologyClass GetTopologyMTL(Topology topology) { + return TOPOLOGIES_CLASSES [(size_t)topology]; +} + + +inline MTLVertexFormat GetVertexFormatMTL(Format format) { + return (MTLVertexFormat)MTL_NRI_FORMAT_TO_VERTEX_FORMAT[(size_t)format]; +} + +inline MTLPixelFormat GetFormatMTL(Format format, bool demoteSrgb = false) { + if (demoteSrgb) { + const FormatProps& formatProps = GetFormatProps(format); + if (formatProps.isSrgb) + format = (Format)((uint32_t)format - 1); + } + + return (MTLPixelFormat)NRIFormatToMTLFormat(format); +} + + +constexpr TextureType GetTextureType(MTLTextureType type) { + switch(type) { + case MTLTextureType1D: + case MTLTextureType1DArray: + return TextureType::TEXTURE_1D; + case MTLTextureType2D: + case MTLTextureType2DArray: + case MTLTextureType2DMultisample: + case MTLTextureType2DMultisampleArray: + case MTLTextureTypeCube: + case MTLTextureTypeCubeArray: + return TextureType::TEXTURE_2D; + case MTLTextureType3D: + return TextureType::TEXTURE_3D; + default: + break; + } + + return TextureType::MAX_NUM; +} + + +}; + diff --git a/Source/Metal/ConversionMTL.mm b/Source/Metal/ConversionMTL.mm new file mode 100644 index 00000000..ef200713 --- /dev/null +++ b/Source/Metal/ConversionMTL.mm @@ -0,0 +1,87 @@ +#include "SharedMTL.h" + +#include "ConversionMTL.h" + +using namespace nri; + +// Each depth/stencil format is only compatible with itself in VK +constexpr std::array MTL_PIXEL_FORMAT = { + MTLPixelFormatInvalid, // UNKNOWN + MTLPixelFormatR8Unorm, // R8_UNORM + MTLPixelFormatR8Snorm, // R8_SNORM + MTLPixelFormatR8Uint, // R8_UINT + MTLPixelFormatR8Sint, // R8_SINT + MTLPixelFormatRG8Unorm, // RG8_UNORM + MTLPixelFormatRG8Snorm, // RG8_SNORM + MTLPixelFormatRG8Uint, // RG8_UINT + MTLPixelFormatRG8Sint, // RG8_SINT + MTLPixelFormatBGRA8Unorm, // BGRA8_UNORM + MTLPixelFormatBGRA8Unorm_sRGB, // BGRA8_SRGB + MTLPixelFormatRGBA8Unorm, // RGBA8_UNORM + MTLPixelFormatRGBA8Unorm_sRGB, // RGBA8_SRGB + MTLPixelFormatRGBA8Snorm, // RGBA8_SNORM + MTLPixelFormatRGBA8Uint, // RGBA8_UINT + MTLPixelFormatRGBA8Sint, // RGBA8_SINT + MTLPixelFormatR16Unorm, // R16_UNORM + MTLPixelFormatR16Snorm, // R16_SNORM + MTLPixelFormatR16Uint, // R16_UINT + MTLPixelFormatR16Sint, // R16_SINT + MTLPixelFormatR16Float, // R16_SFLOAT + MTLPixelFormatRG16Unorm, // RG16_UNORM + MTLPixelFormatRG16Snorm, // RG16_SNORM + MTLPixelFormatRG16Uint, // RG16_UINT + MTLPixelFormatRG16Sint, // RG16_SINT + MTLPixelFormatRG16Float, // RG16_SFLOAT + MTLPixelFormatRGBA16Unorm, // RGBA16_UNORM + MTLPixelFormatRGBA16Snorm, // RGBA16_SNORM + MTLPixelFormatRGBA16Uint, // RGBA16_UINT + MTLPixelFormatRGBA16Sint, // RGBA16_SINT + MTLPixelFormatRGBA16Float, // RGBA16_SFLOAT + MTLPixelFormatR32Uint, // R32_UINT + MTLPixelFormatR32Sint, // R32_SINT + MTLPixelFormatR32Float, // R32_SFLOAT + MTLPixelFormatRG32Uint, // RG32_UINT + MTLPixelFormatRG32Sint, // RG32_SINT + MTLPixelFormatRG32Float, // RG32_SFLOAT + MTLPixelFormatInvalid, // RGB32_UINT //TODO: lookup correct values + MTLPixelFormatInvalid, // RGB32_SINT //TODO: lookup correct values + MTLPixelFormatInvalid, // RGB32_SFLOAT //TODO: lookup correct values + MTLPixelFormatRGBA32Uint, // RGB32_UINT + MTLPixelFormatRGBA32Sint, // RGB32_SINT + MTLPixelFormatRGBA32Float, // RGB32_SFLOAT + MTLPixelFormatB5G6R5Unorm, // B5_G6_R5_UNORM + MTLPixelFormatA1BGR5Unorm, // B5_G5_R5_A1_UNORM + MTLPixelFormatABGR4Unorm, // B4_G4_R4_A4_UNORM + MTLPixelFormatRGB10A2Unorm, // R10_G10_B10_A2_UNORM + MTLPixelFormatRGB10A2Uint, // R10_G10_B10_A2_UINT + MTLPixelFormatRG11B10Float, // R11_G11_B10_UFLOAT + MTLPixelFormatRGB9E5Float, // R9_G9_B9_E5_UFLOAT + MTLPixelFormatBC1_RGBA, // BC1_RGBA_UNORM + MTLPixelFormatBC1_RGBA_sRGB, // BC1_RGBA_SRGB + MTLPixelFormatBC2_RGBA, // BC2_RGBA_UNORM + MTLPixelFormatBC2_RGBA_sRGB, // BC2_RGBA_SRGB + MTLPixelFormatBC3_RGBA, // BC3_RGBA_UNORM + MTLPixelFormatBC3_RGBA_sRGB, // BC3_RGBA_SRGB + MTLPixelFormatBC4_RUnorm, // BC4_R_UNORM + MTLPixelFormatBC4_RSnorm, // BC4_R_SNORM + MTLPixelFormatBC5_RGUnorm, // BC5_RG_UNORM + MTLPixelFormatBC5_RGSnorm, // BC5_RG_SNORM + MTLPixelFormatBC6H_RGBUfloat, // BC6H_RGB_UFLOAT + MTLPixelFormatBC6H_RGBFloat, // BC6H_RGB_SFLOAT + MTLPixelFormatBC7_RGBAUnorm, // BC7_RGBA_UNORM + MTLPixelFormatBC7_RGBAUnorm_sRGB, // BC7_RGBA_SRGB + MTLPixelFormatDepth16Unorm, // D16_UNORM + MTLPixelFormatDepth24Unorm_Stencil8, // D24_UNORM_S8_UINT + MTLPixelFormatDepth32Float, // D32_SFLOAT + MTLPixelFormatDepth32Float_Stencil8, // D32_SFLOAT_S8_UINT_X24 + MTLPixelFormatDepth24Unorm_Stencil8, // R24_UNORM_X8 + MTLPixelFormatDepth24Unorm_Stencil8, // X24_G8_UINT + MTLPixelFormatDepth32Float_Stencil8, // R32_SFLOAT_X8_X24 + MTLPixelFormatDepth32Float_Stencil8, // X32_G8_UINT_X24 +}; + + +uint32_t NRIFormatToMTLFormat(Format format) { + return (uint32_t)MTL_PIXEL_FORMAT[(uint32_t)format]; +} + diff --git a/Source/Metal/DescriptorMTL.h b/Source/Metal/DescriptorMTL.h new file mode 100644 index 00000000..37af247a --- /dev/null +++ b/Source/Metal/DescriptorMTL.h @@ -0,0 +1,70 @@ +// © 2021 NVIDIA Corporation + +#pragma once + +namespace nri { + +struct DeviceMTL; + +//struct DescriptorView { +//}; + +enum class DescriptorTypeMTL { + NONE, + IMAGE_VIEW_1D, + IMAGE_VIEW_2D, + IMAGE_VIEW_3D, + SAMPLER, + BUFFER_VIEW +}; + +struct DescriptorMTL { +public: + inline DescriptorMTL (DeviceMTL& device) + : m_Device(device) { + } + + ~DescriptorMTL(); + inline DescriptorTypeMTL GetType() { + return m_Type; + } + inline id GetTextureHandle() { + return m_Texture; + } + inline id GetBufferHandle() { + return m_Buffer; + } + inline id GetSamplerStateHandler() { + return m_SamplerState; + } + + inline struct BufferViewDesc& BufferView() { + return m_BufferViewDesc; + } + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + Result Create(const BufferViewDesc& bufferViewDesc); + Result Create(const Texture1DViewDesc& textureViewDesc); + Result Create(const Texture2DViewDesc& textureViewDesc); + Result Create(const Texture3DViewDesc& textureViewDesc); + Result Create(const SamplerDesc& samplerDesc); + +private: + + void EndCurrentEncoders(bool forceBarrier); + + DeviceMTL& m_Device; + DescriptorTypeMTL m_Type = DescriptorTypeMTL::NONE; + id m_Texture; + id m_Buffer; + id m_SamplerState; + union { + BufferViewDesc m_BufferViewDesc; + SamplerDesc m_SamplerViewDesc; + }; +}; + +} // namespace nri diff --git a/Source/Metal/DescriptorMTL.mm b/Source/Metal/DescriptorMTL.mm new file mode 100644 index 00000000..36a1c8cc --- /dev/null +++ b/Source/Metal/DescriptorMTL.mm @@ -0,0 +1,101 @@ +#include "SharedMTL.h" + +#include "DescriptorMTL.h" + +#include "BufferMTL.h" +#include "TextureMTL.h" + +#include "ConversionMTL.h" + +namespace nri { + +DescriptorMTL::~DescriptorMTL() { + +} + +Result DescriptorMTL::Create(const BufferViewDesc& bufferViewDesc) { + m_Type = DescriptorTypeMTL::BUFFER_VIEW; + const BufferMTL& buffer = *(const BufferMTL*)bufferViewDesc.buffer; + m_Buffer = buffer.GetHandle(); + return Result::SUCCESS; +} + +Result DescriptorMTL::Create(const Texture1DViewDesc& textureViewDesc) { + TextureMTL& texture = *(TextureMTL*)textureViewDesc.texture; + const Mip_t remainingMips = textureViewDesc.mipNum - textureViewDesc.mipOffset; + const Dim_t remainingLayers = textureViewDesc.layerNum - textureViewDesc.layerOffset; + + NSRange level; + level.location = textureViewDesc.mipOffset; + level.length = textureViewDesc.mipNum == REMAINING_MIPS ? remainingMips: textureViewDesc.mipNum; + NSRange slices; + slices.location = textureViewDesc.layerNum; + slices.length = textureViewDesc.layerNum == REMAINING_LAYERS ? remainingLayers : textureViewDesc.layerNum; + m_Texture = [texture.GetHandle() + newTextureViewWithPixelFormat: GetFormatMTL(textureViewDesc.format) + textureType: MTLTextureType1D + levels:level + slices:slices]; + m_Type = DescriptorTypeMTL::IMAGE_VIEW_1D; + + return Result::SUCCESS; + +} +Result DescriptorMTL::Create(const Texture2DViewDesc& textureViewDesc) { + TextureMTL& texture = *(TextureMTL*)textureViewDesc.texture; + const Mip_t remainingMips = textureViewDesc.mipNum - textureViewDesc.mipOffset; + const Dim_t remainingLayers = textureViewDesc.layerNum - textureViewDesc.layerOffset; + + NSRange level; + level.location = textureViewDesc.mipOffset; + level.length = textureViewDesc.mipNum == REMAINING_MIPS ? remainingMips: textureViewDesc.mipNum; + NSRange slices; + slices.location = textureViewDesc.layerNum; + slices.length = textureViewDesc.layerNum == REMAINING_LAYERS ? remainingLayers : textureViewDesc.layerNum; + m_Texture = [texture.GetHandle() + newTextureViewWithPixelFormat: GetFormatMTL(textureViewDesc.format) + textureType: MTLTextureType2D + levels:level + slices:slices]; + m_Type = DescriptorTypeMTL::IMAGE_VIEW_2D; + + return Result::SUCCESS; +} +Result DescriptorMTL::Create(const Texture3DViewDesc& textureViewDesc){ + TextureMTL& texture = *(TextureMTL*)textureViewDesc.texture; + const Mip_t remainingMips = textureViewDesc.mipNum - textureViewDesc.mipOffset; + const Dim_t remainingLayers = textureViewDesc.sliceNum - textureViewDesc.sliceOffset; + + NSRange level; + level.location = textureViewDesc.mipOffset; + level.length = textureViewDesc.mipNum == REMAINING_MIPS ? remainingMips: textureViewDesc.mipNum; + NSRange slices; + slices.location = textureViewDesc.sliceOffset; + slices.length = textureViewDesc.sliceNum == REMAINING_LAYERS ? remainingLayers : textureViewDesc.sliceOffset; + m_Texture = [texture.GetHandle() + newTextureViewWithPixelFormat: GetFormatMTL(textureViewDesc.format) + textureType: MTLTextureType3D + levels:level + slices:slices]; + m_Type = DescriptorTypeMTL::IMAGE_VIEW_3D; + + return Result::SUCCESS; +} + +Result DescriptorMTL::Create(const SamplerDesc& samplerDesc){ + MTLSamplerDescriptor* mtlDesc = [[MTLSamplerDescriptor alloc] init]; + [mtlDesc setMagFilter: GetFilter(samplerDesc.filters.mag)]; + [mtlDesc setMinFilter: GetFilter(samplerDesc.filters.min)]; + [mtlDesc setRAddressMode: GetSamplerAddressMode(samplerDesc.addressModes.w)]; + [mtlDesc setSAddressMode: GetSamplerAddressMode(samplerDesc.addressModes.u)]; + [mtlDesc setTAddressMode: GetSamplerAddressMode(samplerDesc.addressModes.v)]; + [mtlDesc setMaxAnisotropy: samplerDesc.anisotropy]; + [mtlDesc setCompareFunction: GetCompareOp(samplerDesc.compareFunc)]; + [mtlDesc setLodMinClamp: samplerDesc.mipMin]; + [mtlDesc setLodMaxClamp: samplerDesc.mipMax]; + m_SamplerState = [m_Device newSamplerStateWithDescriptor: mtlDesc]; + m_Type = DescriptorTypeMTL::SAMPLER; + return Result::SUCCESS; +} + +} diff --git a/Source/Metal/DescriptorPoolMTL.h b/Source/Metal/DescriptorPoolMTL.h new file mode 100644 index 00000000..c21b0fbd --- /dev/null +++ b/Source/Metal/DescriptorPoolMTL.h @@ -0,0 +1,45 @@ +// © 2021 NVIDIA Corporation + +#pragma once + +#import + +namespace nri { + +struct DeviceMTL; +struct DescriptorSetMTL; + +struct DescriptorPoolMTL { + inline DescriptorPoolMTL(DeviceMTL& device) + : m_Device(device) + , m_AllocatedSets(device.GetStdAllocator()) { + m_AllocatedSets.reserve(64); + } + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + ~DescriptorPoolMTL(); + Result Create(const DescriptorPoolDesc& descriptorPoolDesc); + + //================================================================================================================ + // NRI + //================================================================================================================ + +// size_t GetNumberOfArugmentsAlloc(); + void SetDebugName(const char* name); + void Reset(); + Result AllocateDescriptorSets(const PipelineLayout& pipelineLayout, uint32_t setIndex, DescriptorSet** descriptorSets, uint32_t instanceNum, uint32_t variableDescriptorNum); + +private: + DeviceMTL& m_Device; + size_t m_ArgumentOffset = 0; + Vector m_AllocatedSets; + id m_ArgumentBuffer; + + uint32_t m_UsedSets = 0; + bool m_OwnsNativeObjects = true; +}; + +} // namespace nri diff --git a/Source/Metal/DescriptorPoolMTL.mm b/Source/Metal/DescriptorPoolMTL.mm new file mode 100644 index 00000000..fc0531ec --- /dev/null +++ b/Source/Metal/DescriptorPoolMTL.mm @@ -0,0 +1,74 @@ + +#include "SharedMTL.h" +#include "DescriptorPoolMTL.h" +#include "DescriptorSetMTL.h" +#include "PipelineLayoutMTL.h" + +using namespace nri; + + +DescriptorPoolMTL::~DescriptorPoolMTL() { + +} + +Result DescriptorPoolMTL::Create(const DescriptorPoolDesc& descriptorPoolDesc) { + size_t numArgs = descriptorPoolDesc.samplerMaxNum + + descriptorPoolDesc.constantBufferMaxNum + + descriptorPoolDesc.dynamicConstantBufferMaxNum + + descriptorPoolDesc.textureMaxNum + + descriptorPoolDesc.storageTextureMaxNum + + descriptorPoolDesc.bufferMaxNum + + descriptorPoolDesc.storageBufferMaxNum + + descriptorPoolDesc.structuredBufferMaxNum + + descriptorPoolDesc.accelerationStructureMaxNum; + + m_ArgumentBuffer = [m_Device + newBufferWithLength: numArgs * sizeof(uint32_t) options:MTLResourceStorageModeShared]; +} + + +//size_t DescriptorPoolMTL::GetNumberOfArugmentsAlloc() { +// return [m_ArgumentBuffer length] / sizeof(uint32_t); +//} + +//================================================================================================================ +// NRI +//================================================================================================================ + +void DescriptorPoolMTL::SetDebugName(const char* name) { + +} +void DescriptorPoolMTL::Reset() { + m_ArgumentOffset = 0; + m_AllocatedSets.clear(); + +} + +Result DescriptorPoolMTL::AllocateDescriptorSets(const PipelineLayout& pipelineLayout, uint32_t setIndex, DescriptorSet** descriptorSets, uint32_t instanceNum, uint32_t variableDescriptorNum) { + PipelineLayoutMTL* pipelineLayoutMTL = (PipelineLayoutMTL*)&pipelineLayout; + + uint32_t freeSetNum = (uint32_t)m_AllocatedSets.size() - m_UsedSets; + if (freeSetNum < instanceNum) { + uint32_t newSetNum = instanceNum - freeSetNum; + uint32_t prevSetNum = (uint32_t)m_AllocatedSets.size(); + m_AllocatedSets.resize(prevSetNum + newSetNum); + for (size_t i = 0; i < newSetNum; i++) { + Construct(m_AllocatedSets[prevSetNum + i], 1, m_Device); + } + } + + const struct DescriptorSetLayout* setLayoutMTL = pipelineLayoutMTL->GetDescriptorSetLayout(setIndex); + for(uint32_t i = 0; i < instanceNum; i++) { + descriptorSets[i] = (DescriptorSet*)m_AllocatedSets[m_UsedSets++]; + ((DescriptorSetMTL*)descriptorSets[i])->Create( + m_ArgumentOffset, + m_ArgumentBuffer, + setLayoutMTL->m_ArgumentDescriptors, + &setLayoutMTL->m_DescriptorSetDesc); + m_ArgumentOffset += ((DescriptorSetMTL*)descriptorSets[i])->getDescriptorLength(); + } + + + return Result::SUCCESS; +} + diff --git a/Source/Metal/DescriptorSetMTL.h b/Source/Metal/DescriptorSetMTL.h new file mode 100644 index 00000000..06405e42 --- /dev/null +++ b/Source/Metal/DescriptorSetMTL.h @@ -0,0 +1,39 @@ +// © 2021 NVIDIA Corporation + +#pragma once + +namespace nri { + +struct DeviceVK; +struct DescriptorSetMTL { +public: + inline DescriptorSetMTL (DeviceMTL& device) + : m_Device(device) { + } + + void Create(size_t argumentBufferOffset, id argumentBuffer, NSArray* argDesc, const struct DescriptorSetDesc* desc); + void UpdateDescriptorRanges(uint32_t rangeOffset, uint32_t rangeNum, const DescriptorRangeUpdateDesc* rangeUpdateDescs); + inline id GetArgumentHandle() { + return m_ArgumentEncoder; + } + size_t getDescriptorLength(); + + inline id GetArgumentBuffer() const { + return m_ArgumentBuffer; + } + + inline size_t GetArugmentBufferOffset() const { + return m_ArgumentBufferOffset; + } + +private: + DeviceMTL& m_Device; + id m_ArgumentEncoder; + id m_ArgumentBuffer; + size_t m_ArgumentBufferOffset; + NSArray* m_ArgumentDescriptor; + const DescriptorSetDesc* m_Desc = nullptr; +}; + +} // namespace nri + diff --git a/Source/Metal/DescriptorSetMTL.mm b/Source/Metal/DescriptorSetMTL.mm new file mode 100644 index 00000000..6e96909f --- /dev/null +++ b/Source/Metal/DescriptorSetMTL.mm @@ -0,0 +1,51 @@ + +#include "SharedMTL.h" + +#include "DescriptorSetMTL.h" +#include "DescriptorMTL.h" + +using namespace nri; + + +void DescriptorSetMTL::Create(size_t argumentBufferOffset, id argumentBuffer, NSArray* argDesc, const struct DescriptorSetDesc* desc) { + m_ArgumentDescriptor = argDesc; + m_ArgumentBuffer = argumentBuffer; + m_ArgumentBufferOffset = argumentBufferOffset; + m_Desc = desc; + m_ArgumentEncoder = [m_Device newArgumentEncoderWithArguments: argDesc]; + [m_ArgumentEncoder setArgumentBuffer: m_ArgumentBuffer offset:argumentBufferOffset]; +} + +size_t DescriptorSetMTL::getDescriptorLength() { + return [m_ArgumentEncoder encodedLength]; +} + +void DescriptorSetMTL::UpdateDescriptorRanges(uint32_t rangeOffset, uint32_t rangeNum, const DescriptorRangeUpdateDesc* rangeUpdateDescs) { + + for(size_t j = 0; j < rangeNum; j++) { + const DescriptorRangeUpdateDesc& update = rangeUpdateDescs[j]; + for(size_t descIdx = 0; descIdx < update.descriptorNum; descIdx++) { + DescriptorMTL* descriptorImpl = (DescriptorMTL*)&update.descriptors[descIdx]; + const DescriptorRangeDesc& rangeDesc = m_Desc->ranges[rangeOffset + j]; + + switch(descriptorImpl->GetType()) { + case DescriptorTypeMTL::IMAGE_VIEW_1D: + case DescriptorTypeMTL::IMAGE_VIEW_2D: + case DescriptorTypeMTL::IMAGE_VIEW_3D: + [m_ArgumentEncoder setTexture: descriptorImpl->GetTextureHandle() atIndex: rangeDesc.baseRegisterIndex + descIdx]; + break; + case DescriptorTypeMTL::SAMPLER: + [m_ArgumentEncoder setSamplerState: descriptorImpl->GetSamplerStateHandler() atIndex:rangeDesc.baseRegisterIndex + descIdx]; // not sure if this is correct + break; + case DescriptorTypeMTL::BUFFER_VIEW: { + BufferViewDesc* view = &descriptorImpl->BufferView(); + [m_ArgumentEncoder setBuffer: descriptorImpl->GetBufferHandle() offset: view->offset atIndex: rangeDesc.baseRegisterIndex + descIdx]; + break; + } + default: + break; + } + + } + } +} diff --git a/Source/Metal/DeviceMTL.h b/Source/Metal/DeviceMTL.h new file mode 100644 index 00000000..857ea56d --- /dev/null +++ b/Source/Metal/DeviceMTL.h @@ -0,0 +1,89 @@ +#pragma once + +#import + +namespace nri { + +struct CommandQueueMTL; + +struct DeviceMTL final : public DeviceBase { +public: + DeviceMTL(const CallbackInterface& callbacks, const StdAllocator& stdAllocator); + ~DeviceMTL(); + + + Result GetCommandQueue(CommandQueueType commandQueueType, CommandQueue*& commandQueue); + + inline operator id() const { + return m_Device; + } + + inline id GetHandle() const { + return m_Device; + } + + template + inline Result CreateImplementation(Interface*& entity, const Args&... args) { + Implementation* impl = Allocate(GetStdAllocator(), *this); + Result result = impl->Create(args...); + + if (result != Result::SUCCESS) { + Destroy(GetStdAllocator(), impl); + entity = nullptr; + } else { + entity = (Interface*)impl; + } + + return result; + } + + + inline const CoreInterface& GetCoreInterface() const { + return m_CoreInterface; + } + + //void GetMemoryTypeInfo(MemoryLocation memoryLocation, MemoryDesc& memoryDesc) const; + void GetMemoryDesc(const BufferDesc& bufferDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) const; + void GetMemoryDesc(const TextureDesc& textureDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) const; + void GetMemoryDesc(const AccelerationStructureDesc& accelerationStructureDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) const; + //bool GetMemoryTypeInfo(MemoryLocation memoryLocation, MemoryTypeInfo& memoryTypeInfo) const; + + const DeviceDesc& GetDesc() const override { + return m_Desc; + } + + id GetClearPipeline(const ClearDesc* desc, size_t numFormat); + + void Destruct() override; + Result FillFunctionTable(CoreInterface& table) const override; + Result FillFunctionTable(HelperInterface& table) const override; + Result FillFunctionTable(LowLatencyInterface& table) const override; + Result FillFunctionTable(MeshShaderInterface& table) const override; + Result FillFunctionTable(RayTracingInterface& table) const override; + Result FillFunctionTable(StreamerInterface& table) const override; + Result FillFunctionTable(SwapChainInterface& table) const override; + Result FillFunctionTable(ResourceAllocatorInterface& table) const override; + + Result BindBufferMemory(const BufferMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum); + Result BindTextureMemory(const TextureMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum); + + Result Create(const DeviceCreationDesc& deviceCreationDesc, const DeviceCreationMTLDesc& deviceCreationVKDesc, bool isWrapper); + + struct ClearPipelineKey { + + + }; +private: + //Lock m_Lock; + id m_Device; + std::array m_CommandQueues = {}; + CoreInterface m_CoreInterface = {}; + DeviceDesc m_Desc = {}; + MTLGPUFamily m_Family; + bool m_OwnsNativeObjects = true; + Lock m_Lock; + + std::unordered_map> m_clearPipelineState; + +}; +}; // namespace nri diff --git a/Source/Metal/DeviceMTL.hpp b/Source/Metal/DeviceMTL.hpp new file mode 100644 index 00000000..c6dd5d91 --- /dev/null +++ b/Source/Metal/DeviceMTL.hpp @@ -0,0 +1,260 @@ +// © 2021 NVIDIA Corporation + +//Declare_PartiallyFillFunctionTable_Functions(MTL); +// +//#pragma region[ Core ] +// +//static const DeviceDesc& NRI_CALL GetDeviceDesc(const Device& device) { +// return ((const DeviceMTL&)device).GetDesc(); +//} +// +//static const BufferDesc& NRI_CALL GetBufferDesc(const Buffer& buffer) { +// return ((const BufferMTL&)buffer).GetDesc(); +//} +// +//static const TextureDesc& NRI_CALL GetTextureDesc(const Texture& texture) { +// return ((const TextureMTL&)texture).GetDesc(); +//} +// +//static FormatSupportBits NRI_CALL GetFormatSupport(const Device& device, Format format) { +// return (FormatSupportBits)0; +// //return ((const DeviceDesc&)device).GetFormatSupport(format); +//} +// +//static void NRI_CALL GetBufferMemoryDesc(const Device& device, const BufferDesc& bufferDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) { +// //D3D12_RESOURCE_DESC desc = {}; +// //GetResourceDesc(&desc, bufferDesc); +// +// //((const DeviceD3D12&)device).GetMemoryDesc(memoryLocation, desc, memoryDesc); +//} +// +//static void NRI_CALL GetTextureMemoryDesc(const Device& device, const TextureDesc& textureDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) { +// //return ((const DeviceMTL&)device).GetMemoryDesc(textureDesc, memoryLocation, memoryDesc); +// +//} +// +//static Result NRI_CALL GetCommandQueue(Device& device, CommandQueueType commandQueueType, CommandQueue*& commandQueue) { +// return ((DeviceMTL&)device).GetCommandQueue(commandQueueType, commandQueue); +//} +// +//static Result NRI_CALL CreateCommandAllocator(const CommandQueue& commandQueue, CommandAllocator*& commandAllocator) { +// //DeviceMTL& device = ((CommandQueueD3D12&)commandQueue).GetDevice(); +// //return device.CreateImplementation(commandAllocator, commandQueue); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreateDescriptorPool(Device& device, const DescriptorPoolDesc& descriptorPoolDesc, DescriptorPool*& descriptorPool) { +// //return ((DeviceMTL&)device).CreateImplementation(descriptorPool, descriptorPoolDesc); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreateBuffer(Device& device, const BufferDesc& bufferDesc, Buffer*& buffer) { +// return ((DeviceMTL&)device).CreateImplementation(buffer, bufferDesc); +//} +// +//static Result NRI_CALL CreateTexture(Device& device, const TextureDesc& textureDesc, Texture*& texture) { +// return ((DeviceMTL&)device).CreateImplementation(texture, textureDesc); +//} +// +//static Result NRI_CALL CreateBufferView(const BufferViewDesc& bufferViewDesc, Descriptor*& bufferView) { +// //DeviceMTL& device = ((const BufferD3D12*)bufferViewDesc.buffer)->GetDevice(); +// //return device.CreateImplementation(bufferView, bufferViewDesc); +// return Result::SUCCESS; +//} +// +// +//static Result NRI_CALL CreateTexture1DView(const Texture1DViewDesc& textureViewDesc, Descriptor*& textureView) { +// //DeviceMTL& device = ((const TextureMTL*)textureViewDesc.texture)->GetDevice(); +// //return device.CreateImplementation(textureView, textureViewDesc); +// +// +// //DeviceMTL& device = ((const TextureD3D12*)textureViewDesc.texture)->GetDevice(); +// //return device.CreateImplementation(textureView, textureViewDesc); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreateTexture2DView(const Texture2DViewDesc& textureViewDesc, Descriptor*& textureView) { +// //DeviceMTL& device = ((const TextureD3D12*)textureViewDesc.texture)->GetDevice(); +// //return device.CreateImplementation(textureView, textureViewDesc); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreateTexture3DView(const Texture3DViewDesc& textureViewDesc, Descriptor*& textureView) { +// //DeviceMTL& device = ((const TextureD3D12*)textureViewDesc.texture)->GetDevice(); +// //return device.CreateImplementation(textureView, textureViewDesc); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreateSampler(Device& device, const SamplerDesc& samplerDesc, Descriptor*& sampler) { +// //return ((DeviceMTL&)device).CreateImplementation(sampler, samplerDesc); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreatePipelineLayout(Device& device, const PipelineLayoutDesc& pipelineLayoutDesc, PipelineLayout*& pipelineLayout) { +// //return ((DeviceMTL&)device).CreateImplementation(pipelineLayout, pipelineLayoutDesc); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreateGraphicsPipeline(Device& device, const GraphicsPipelineDesc& graphicsPipelineDesc, Pipeline*& pipeline) { +// //return ((DeviceMTL&)device).CreateImplementation(pipeline, graphicsPipelineDesc); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreateComputePipeline(Device& device, const ComputePipelineDesc& computePipelineDesc, Pipeline*& pipeline) { +// //return ((DeviceMTL&)device).CreateImplementation(pipeline, computePipelineDesc); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreateFence(Device& device, uint64_t initialValue, Fence*& fence) { +// //return ((DeviceMTL&)device).CreateImplementation(fence, initialValue); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL CreateQueryPool(Device& device, const QueryPoolDesc& queryPoolDesc, QueryPool*& queryPool) { +// //return ((DeviceMTL&)device).CreateImplementation(queryPool, queryPoolDesc); +// return Result::SUCCESS; +//} +// +//static void NRI_CALL DestroyCommandBuffer(CommandBuffer& commandBuffer) { +// //Destroy((CommandBufferD3D12*)&commandBuffer); +//} +// +//static void NRI_CALL DestroyCommandAllocator(CommandAllocator& commandAllocator) { +// //Destroy((CommandAllocatorD3D12*)&commandAllocator); +//} +// +//static void NRI_CALL DestroyDescriptorPool(DescriptorPool& descriptorPool) { +// //Destroy((DescriptorPoolD3D12*)&descriptorPool); +//} +// +//static void NRI_CALL DestroyBuffer(Buffer& buffer) { +// //Destroy((BufferD3D12*)&buffer); +//} +// +//static void NRI_CALL DestroyTexture(Texture& texture) { +// //Destroy((TextureD3D12*)&texture); +//} +// +//static void NRI_CALL DestroyDescriptor(Descriptor& descriptor) { +// //Destroy((DescriptorD3D12*)&descriptor); +//} +// +//static void NRI_CALL DestroyPipelineLayout(PipelineLayout& pipelineLayout) { +// //Destroy((PipelineLayoutD3D12*)&pipelineLayout); +//} +// +//static void NRI_CALL DestroyPipeline(Pipeline& pipeline) { +// //Destroy((PipelineD3D12*)&pipeline); +//} +// +//static void NRI_CALL DestroyQueryPool(QueryPool& queryPool) { +// //Destroy((QueryPoolD3D12*)&queryPool); +//} +// +//static void NRI_CALL DestroyFence(Fence& fence) { +// Destroy((FenceMTL*)&fence); +//} +// +//static Result NRI_CALL AllocateMemory(Device& device, const AllocateMemoryDesc& allocateMemoryDesc, Memory*& memory) { +// return Result::SUCCESS; +// //return ((DeviceMTL&)device).CreateImplementation(memory, allocateMemoryDesc); +//} +// +//static Result NRI_CALL BindBufferMemory(Device& device, const BufferMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum) { +// //return ((DeviceMTL&)device).BindBufferMemory(memoryBindingDescs, memoryBindingDescNum); +// return Result::SUCCESS; +//} +// +//static Result NRI_CALL BindTextureMemory(Device& device, const TextureMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum) { +// //return ((DeviceMTL&)device).BindTextureMemory(memoryBindingDescs, memoryBindingDescNum); +// return Result::SUCCESS; +//} +// +//static void NRI_CALL FreeMemory(Memory& memory) { +//// Destroy((MemoryD3D12*)&memory); +//} +// +//static void NRI_CALL SetDeviceDebugName(Device& device, const char* name) { +//// ((DeviceMTL&)device).SetDebugName(name); +//} +// +//static void NRI_CALL SetPipelineDebugName(Pipeline& pipeline, const char* name) { +//// ((PipelineD3D12&)pipeline).SetDebugName(name); +//} +// +//static void NRI_CALL SetPipelineLayoutDebugName(PipelineLayout& pipelineLayout, const char* name) { +//// ((PipelineLayoutD3D12&)pipelineLayout).SetDebugName(name); +//} +// +//static void NRI_CALL SetMemoryDebugName(Memory& memory, const char* name) { +//// ((MemoryMetal&)memory).SetDebugName(name); +//} +// +//static void* NRI_CALL GetDeviceNativeObject(const Device& device) { +// if (!(&device)) +// return nullptr; +// return (DeviceMTL*)&((DeviceMTL&)device); +// +// //return ((DeviceMetal&)device).GetNativeObject(); +//} +// +////Result DeviceMTL::FillFunctionTable(CoreInterface& table) const { +//// table = {}; +//// // Core_Device_PartiallyFillFunctionTableMTL(table); +//// // Core_Buffer_PartiallyFillFunctionTableMTL(table); +//// // Core_CommandAllocator_PartiallyFillFunctionTableMTL(table); +//// // Core_CommandBuffer_PartiallyFillFunctionTableMTL(table); +//// // Core_CommandQueue_PartiallyFillFunctionTableMTL(table); +//// // Core_Descriptor_PartiallyFillFunctionTableMTL(table); +//// // Core_DescriptorPool_PartiallyFillFunctionTableMTL(table); +//// // Core_DescriptorSet_PartiallyFillFunctionTableMTL(table); +//// // Core_Fence_PartiallyFillFunctionTableMTL(table); +//// // Core_QueryPool_PartiallyFillFunctionTableMTL(table); +//// // Core_Texture_PartiallyFillFunctionTableMTL(table); +//// // return ValidateFunctionTable(table); +//// return Result::UNSUPPORTED; +////} +// +//#pragma endregion +// +////Result DeviceMTL::FillFunctionTable(HelperInterface& table) const { +//// table = {}; +//// return Result::UNSUPPORTED; +////} +//// +////Result DeviceMTL::FillFunctionTable(LowLatencyInterface& table) const { +//// table = {}; +//// return Result::UNSUPPORTED; +////} +// +////Result DeviceMTL::FillFunctionTable(MeshShaderInterface& table) const { +//// table = {}; +//// return Result::UNSUPPORTED; +////} +// +////Result DeviceMTL::FillFunctionTable(RayTracingInterface& table) const { +//// table = {}; +//// return Result::UNSUPPORTED; +////} +//// +////Result DeviceMTL::FillFunctionTable(StreamerInterface& table) const { +//// table = {}; +//// return Result::UNSUPPORTED; +////} +//// +////Result DeviceMTL::FillFunctionTable(SwapChainInterface& table) const { +//// table = {}; +//// return Result::UNSUPPORTED; +////} +//// +////Result DeviceMTL::FillFunctionTable(ResourceAllocatorInterface& table) const { +//// table = {}; +//// return Result::UNSUPPORTED; +////} +// +////Dfine_Core_Device_PartiallyFillFunctionTable(MTL); +////Define_Helper_Device_PartiallyFillFunctionTable(MTL); +////Define_RayTracing_Device_PartiallyFillFunctionTable(MTL); +////Define_Streamer_Device_PartiallyFillFunctionTable(MTL); +////Define_SwapChain_Device_PartiallyFillFunctionTable(MTL); +////Define_ResourceAllocator_Device_PartiallyFillFunctionTable(MTL); diff --git a/Source/Metal/DeviceMTL.mm b/Source/Metal/DeviceMTL.mm new file mode 100644 index 00000000..92bb88c0 --- /dev/null +++ b/Source/Metal/DeviceMTL.mm @@ -0,0 +1,515 @@ + + +#include "SharedMTL.h" + +#include "CommandQueueMTL.h" +#include "DeviceMTL.h" +#include "BufferMTL.h" +#include "CommandQueueMTL.h" +#include "TextureMTL.h" +#include "FenceMTL.h" +#include "MemoryMTL.h" +#include "PipelineLayoutMTL.h" +#include "PipelineMTL.h" + +using namespace nri; + +static bool FindMTLGpuFamily(id device, + const MTLGPUFamily *families, size_t len, + MTLGPUFamily* current) { + for(size_t i = 0; i < len; i++) { + if( [device supportsFamily: families[i]]) { + *current = families[i]; + return true; + } + } + return false; +} + +// referenced from Molten VK +static uint32_t GetEntryProperty(io_registry_entry_t entry, CFStringRef propertyName) { + + uint32_t value = 0; + + CFTypeRef cfProp = IORegistryEntrySearchCFProperty(entry, + kIOServicePlane, + propertyName, + kCFAllocatorDefault, + kIORegistryIterateRecursively | + kIORegistryIterateParents); + if (cfProp) { + const uint32_t* pValue = reinterpret_cast(CFDataGetBytePtr((CFDataRef)cfProp)); + if (pValue) { value = *pValue; } + CFRelease(cfProp); + } + + return value; +} + +DeviceMTL::DeviceMTL(const CallbackInterface& callbacks, const StdAllocator& stdAllocator) +: DeviceBase(callbacks, stdAllocator) { + m_Desc.graphicsAPI = GraphicsAPI::MTL; + m_Desc.nriVersionMajor = NRI_VERSION_MAJOR; + m_Desc.nriVersionMinor = NRI_VERSION_MINOR; +} + + +void DeviceMTL::Destruct() { + for (uint32_t i = 0; i < m_CommandQueues.size(); i++) + Destroy(GetStdAllocator(), m_CommandQueues[i]); + Destroy(GetStdAllocator(), this); +} + +DeviceMTL::~DeviceMTL() { + +} + + +//FormatSupportBits DeviceMTL::GetFormatSupport(const Device& device, Format format) { +// int currentFamily = HIGHEST_GPU_FAMILY; +// for (; currentFamily >= (int)MTLGPUFamilyApple1; currentFamily--) { +// if ([m_Device supportsFamily:(MTLGPUFamily)currentFamily]) { +// highestAppleFamily = (MTLGPUFamily)currentFamily; +// break; +// } +// } +//} + + +static id initShaderFromSource(id dev, NSString* src, NSString* method) { + id mtlFunc = nil; + NSError* err = nil; + + MTLCompileOptions* options = [MTLCompileOptions alloc]; + id mtlLib = [dev newLibraryWithSource: src + options: options + error: &err]; // temp retain + NSCAssert(err, @"Failed to load Metal shader library %@", err ); + + return [mtlLib newFunctionWithName: method]; +} + + +static id CreateClearPipeline(id device, const ClearDesc* desc, size_t numFormats) { + NSString* clearVert = [NSString stringWithCString: "\ +#include \n\ +using namespace metal; \n\ +typedef struct { \n\ + float4 a_position [[attribute(0)]]; \n\ +} AttributesPos; \n\ +typedef struct { \n\ + float4 colors[16]; \n\ +} ClearColorsIn; \n\ +typedef struct { \n\ + float4 v_position [[position]]; \n\ + uint layer [[render_target_array_index]]; \n\ +} VaryingsPos; \n\ +vertex VaryingsPos vertClear(AttributesPos attributes [[stage_in]], constant ClearColorsIn& ccIn [[buffer(0)]]) { \n\ + VaryingsPos varyings; \n \ + varyings.v_position = float4(attributes.a_position.x, -attributes.a_position.y, ccIn.colors[4].r, 1.0); \n\ + varyings.layer = uint(attributes.a_position.w); \n\ + return varyings; \n\ +}" encoding: NSASCIIStringEncoding]; + + NSMutableString* clearFrag = [NSMutableString alloc]; + [clearFrag appendString: @"\ + #include \n\ + using namespace metal; \n\ + typedef struct { \n\ + loat4 v_position [[position]]; \n\ + } VaryingsPos; \n\ + typedef struct { \n\ + float4 colors[16]; \n\ + } ClearColorsIn; \n\ + typedef struct { \n\ + "]; + for(uint32_t i = 0; i < numFormats; i++) { + [clearFrag appendFormat: @"float4 color%u [[color(%u)]];", i, desc[i].colorAttachmentIndex]; + } + [clearFrag appendString: @"\ + } ClearColorsOut; \n\ + fragment ClearColorsOut fragClear(VaryingsPos varyings [[stage_in]], constant ClearColorsIn& ccIn [[buffer(0)]]) { \n\ + ClearColorsOut ccOut; \n"]; + for(uint32_t i = 0; i < numFormats; i++) { + [clearFrag appendFormat: @"ccOut.color%u = float4(ccIn.colors[%u]);", i, i]; + } + [clearFrag appendString: @"\ +return ccOut;\n\ +}"]; + + id vtxFunc = initShaderFromSource(device, clearVert, @"vertClear"); + id fragFunc = initShaderFromSource(device, clearFrag, @"fragClear"); + MTLRenderPipelineDescriptor* renderPipelineDesc = [MTLRenderPipelineDescriptor new]; // temp retain + // owner->setMetalObjectLabel(plDesc, @"ClearRenderAttachments"); + renderPipelineDesc.vertexFunction = vtxFunc; + renderPipelineDesc.fragmentFunction = fragFunc; + // plDesc.sampleCount = 1; + renderPipelineDesc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle; + + MTLVertexDescriptor* vtxDesc = renderPipelineDesc.vertexDescriptor; + + MTLVertexAttributeDescriptorArray* vaDescArray = vtxDesc.attributes; + MTLVertexAttributeDescriptor* vaDesc; + NSUInteger vtxBuffIdx = 0; + NSUInteger vtxStride = 0; + + // Vertex location + vaDesc = vaDescArray[0]; + vaDesc.format = MTLVertexFormatFloat4; + vaDesc.bufferIndex = vtxBuffIdx; + vaDesc.offset = vtxStride; + vtxStride += sizeof(simd::float4); + + // Vertex attribute buffer. + MTLVertexBufferLayoutDescriptorArray* vbDescArray = vtxDesc.layouts; + MTLVertexBufferLayoutDescriptor* vbDesc = vbDescArray[vtxBuffIdx]; + vbDesc.stepFunction = MTLVertexStepFunctionPerVertex; + vbDesc.stepRate = 1; + vbDesc.stride = vtxStride; + + NSError* error = nil; + id rps = [device newRenderPipelineStateWithDescriptor:renderPipelineDesc error: &error]; + + [vtxFunc release]; // temp release + [fragFunc release]; // temp release + [renderPipelineDesc release]; // temp release + + return rps; +} + +//TODO: implement this differently +id DeviceMTL::GetClearPipeline(const ClearDesc* desc, size_t numFormats) { + uint32_t key = 0; + for(uint32_t i = 0; i < numFormats; i++) { + key |= (1 << desc[i].colorAttachmentIndex); + } + id rps = CreateClearPipeline(m_Device, desc, numFormats); + m_clearPipelineState[key] = rps; + return rps; +} + + +void DeviceMTL::GetMemoryDesc(const BufferDesc& bufferDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) const { + MemoryTypeInfo memoryTypeInfo; + memoryTypeInfo.options = (uint32_t)DEFAULT_MEMORY_RESOURCE_OPTION_MEMORY_LOCATION[(size_t)memoryLocation]; + memoryTypeInfo.cacheMode = (uint32_t)DEFAULT_CACHE_MODE_MEMORY_LOCATION[(size_t)memoryLocation]; + memoryTypeInfo.storageMode = (uint32_t)DEFAULT_STORAGE_MODE_MEMORY_LOCATION[(size_t)memoryLocation]; + MTLTextureDescriptor* mtlTextureDesc = [[MTLTextureDescriptor alloc] init]; + MTLSizeAndAlign sizeAlign = [m_Device heapBufferSizeAndAlignWithLength: bufferDesc.size options: (MTLResourceOptions)memoryTypeInfo.options]; + + memoryDesc.size = sizeAlign.size; + memoryDesc.alignment = (uint32_t)sizeAlign.align; + memoryDesc.type = memoryTypeInfo.value; + +} + +void DeviceMTL::GetMemoryDesc(const TextureDesc& textureDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) const { + MTLTextureDescriptor* mtlTextureDesc = [[MTLTextureDescriptor alloc] init]; + + MemoryTypeInfo memoryTypeInfo; + memoryTypeInfo.options = (uint32_t)DEFAULT_MEMORY_RESOURCE_OPTION_MEMORY_LOCATION[(size_t)memoryLocation]; + memoryTypeInfo.cacheMode = (uint32_t)DEFAULT_CACHE_MODE_MEMORY_LOCATION[(size_t)memoryLocation]; + memoryTypeInfo.storageMode = (uint32_t)DEFAULT_STORAGE_MODE_MEMORY_LOCATION[(size_t)memoryLocation]; + nri::fillMTLTextureDescriptor(textureDesc, mtlTextureDesc); + const MTLSizeAndAlign sizeAlign = [m_Device heapTextureSizeAndAlignWithDescriptor: mtlTextureDesc]; + + memoryDesc.size = sizeAlign.size; + memoryDesc.alignment = (uint32_t)sizeAlign.align; + memoryDesc.type = memoryTypeInfo.value; +} + +void DeviceMTL::GetMemoryDesc(const AccelerationStructureDesc& accelerationStructureDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) const { +// MTLAccelerationStructureDescriptor* mtlAcceleration = [[MTLAccelerationStructureDescriptor alloc] init]; +// [mtlAcceleration set] + + // [m_Device heapAccelerationStructureSizeAndAlignWithSize: accelerationStructureDesc.geometryObjects] + // TODO: need to add ray traced +} + + +Result DeviceMTL::GetCommandQueue(CommandQueueType commandQueueType, CommandQueue*& commandQueue) { + ExclusiveScope lock(m_Lock); + + // Check if already created (or wrapped) + uint32_t index = (uint32_t)commandQueueType; + if (m_CommandQueues[index]) { + commandQueue = (CommandQueue*)m_CommandQueues[index]; + return Result::SUCCESS; + } + Result result = CreateImplementation(commandQueue, commandQueueType); + if (result == Result::SUCCESS) + m_CommandQueues[index] = (CommandQueueMTL*)commandQueue; + + return result; +} + +Result DeviceMTL::BindBufferMemory(const BufferMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum) { + if (!memoryBindingDescNum) + return Result::SUCCESS; + + for (uint32_t i = 0; i < memoryBindingDescNum; i++) { + const BufferMemoryBindingDesc& memoryBindingDesc = memoryBindingDescs[i]; + + BufferMTL& bufferImpl = *(BufferMTL*)memoryBindingDesc.buffer; + MemoryMTL& memoryImpl = *(MemoryMTL*)memoryBindingDesc.memory; + + bufferImpl.FinishMemoryBinding(memoryImpl, memoryBindingDesc.offset); + } + + return Result::SUCCESS; +} + +Result DeviceMTL::BindTextureMemory(const TextureMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum) { + if (!memoryBindingDescNum) + return Result::SUCCESS; + + for (uint32_t i = 0; i < memoryBindingDescNum; i++) { + const TextureMemoryBindingDesc& memoryBindingDesc = memoryBindingDescs[i]; + + TextureMTL& textureImpl = *(TextureMTL*)memoryBindingDesc.texture; + MemoryMTL& memoryImpl = *(MemoryMTL*)memoryBindingDesc.memory; + + textureImpl.FinishMemoryBinding(memoryImpl, memoryBindingDesc.offset); + } + + return Result::SUCCESS; +} + + +Result DeviceMTL::Create(const DeviceCreationDesc& deviceCreationDesc, const DeviceCreationMTLDesc& deviceCreationMTLDesc, bool isWrapper) { + m_OwnsNativeObjects = !isWrapper; + if(isWrapper) { + m_Device = *(id*)&deviceCreationMTLDesc.MtlDevice; + } else { + NSArray>* devices = MTLCopyAllDevices(); + uint32_t i = 0; + for(i = 0; i < devices.count; i++) { + if(deviceCreationDesc.adapterDesc) { + const uint64_t luid = [devices[i] registryID]; + if(deviceCreationDesc.adapterDesc->luid == luid) { + m_Device = devices[i]; + break; + } + } else { + break; + } + } + RETURN_ON_FAILURE(this, i != devices.count, Result::INVALID_ARGUMENT, "Can't create a device: physical device not found"); + } + + strncpy(m_Desc.adapterDesc.name, [m_Device.name UTF8String], sizeof(m_Desc.adapterDesc.name)); + // No vendor id, device id for Apple GPUs + if (strstr(m_Desc.adapterDesc.name, "Apple")) { + m_Desc.adapterDesc.vendor = nri::Vendor::APPLE; + } + + const uint64_t regID = [m_Device registryID]; + if (regID) + { + io_registry_entry_t entry = IOServiceGetMatchingService(MACH_PORT_NULL, IORegistryEntryIDMatching(regID)); + if (entry) + { + // That returned the IOGraphicsAccelerator nub. Its parent, then, is the actual PCI device. + io_registry_entry_t deviceEntry; + if (IORegistryEntryGetParentEntry(entry, kIOServicePlane, &deviceEntry) == kIOReturnSuccess) + { + m_Desc.adapterDesc.vendor = GetVendorFromID(GetEntryProperty(deviceEntry, CFSTR("vendor-id"))) ; + m_Desc.adapterDesc.deviceId = GetEntryProperty(deviceEntry, CFSTR("device-id")); + } + } + } else { + m_Desc.adapterDesc.vendor = nri::Vendor::APPLE; + } + + + MTLArgumentBuffersTier argumentBufferTier = MTLArgumentBuffersTier1; + if ([m_Device respondsToSelector: @selector(argumentBuffersSupport)]) { + argumentBufferTier = [m_Device argumentBuffersSupport]; + } + + for (uint32_t sc = 1; sc <= 64; sc <<= 1) { + if([m_Device supportsTextureSampleCount: sc]) { + m_Desc.colorSampleMaxNum |= sc; + m_Desc.depthSampleMaxNum |= sc; + m_Desc.stencilSampleMaxNum |= sc; + m_Desc.zeroAttachmentsSampleMaxNum |= sc; + m_Desc.textureColorSampleMaxNum |= sc; + m_Desc.textureIntegerSampleMaxNum |= sc; + m_Desc.textureDepthSampleMaxNum |= sc; + m_Desc.textureStencilSampleMaxNum |= sc; + m_Desc.storageTextureSampleMaxNum |= sc; + } + } + + + m_Desc.viewportMaxNum = 16; + m_Desc.viewportBoundsRange[0] = -32768; + m_Desc.viewportBoundsRange[1] = 32767; + + m_Desc.attachmentMaxDim = 16384; + m_Desc.attachmentLayerMaxNum = 2048; + m_Desc.colorAttachmentMaxNum = 8; + + m_Desc.colorSampleMaxNum = 32; + m_Desc.depthSampleMaxNum = 32; + m_Desc.stencilSampleMaxNum = 32; + m_Desc.zeroAttachmentsSampleMaxNum = 32; + m_Desc.textureColorSampleMaxNum = 32; + m_Desc.textureIntegerSampleMaxNum = 32; + m_Desc.textureDepthSampleMaxNum = 32; + m_Desc.textureStencilSampleMaxNum = 32; + m_Desc.storageTextureSampleMaxNum = 32; + + m_Desc.textureArrayLayerMaxNum = 16384; + m_Desc.typedBufferMaxDim = uint32_t(-1); + + m_Desc.deviceUploadHeapSize = 256 * 1024 * 1024; + m_Desc.memoryAllocationMaxNum = uint32_t(-1); + m_Desc.samplerAllocationMaxNum = 4096; + m_Desc.constantBufferMaxRange = 64 * 1024; + m_Desc.storageBufferMaxRange = uint32_t(-1); + m_Desc.bufferTextureGranularity = 1; + m_Desc.bufferMaxSize = [m_Device maxBufferLength]; + + m_Desc.uploadBufferTextureRowAlignment = 1; + m_Desc.uploadBufferTextureSliceAlignment = 1; + m_Desc.bufferShaderResourceOffsetAlignment = 1; + m_Desc.constantBufferOffsetAlignment = 1; + m_Desc.shaderBindingTableAlignment = 1; + m_Desc.scratchBufferOffsetAlignment = 1; + + m_Desc.pipelineLayoutDescriptorSetMaxNum = 64; + m_Desc.pipelineLayoutRootConstantMaxSize = 256; + m_Desc.pipelineLayoutRootDescriptorMaxNum = 64; + + m_Desc.perStageDescriptorSamplerMaxNum = 1000000; + m_Desc.perStageDescriptorConstantBufferMaxNum = 1000000; + m_Desc.perStageDescriptorStorageBufferMaxNum = 1000000; + m_Desc.perStageDescriptorTextureMaxNum = 1000000; + m_Desc.perStageDescriptorStorageTextureMaxNum = 1000000; + m_Desc.perStageResourceMaxNum = 1000000; + + m_Desc.descriptorSetSamplerMaxNum = m_Desc.perStageDescriptorSamplerMaxNum; + m_Desc.descriptorSetConstantBufferMaxNum = m_Desc.perStageDescriptorConstantBufferMaxNum; + m_Desc.descriptorSetStorageBufferMaxNum = m_Desc.perStageDescriptorStorageBufferMaxNum; + m_Desc.descriptorSetTextureMaxNum = m_Desc.perStageDescriptorTextureMaxNum; + m_Desc.descriptorSetStorageTextureMaxNum = m_Desc.perStageDescriptorStorageTextureMaxNum; + + m_Desc.vertexShaderAttributeMaxNum = 32; + m_Desc.vertexShaderStreamMaxNum = 32; + m_Desc.vertexShaderOutputComponentMaxNum = 128; + + m_Desc.tessControlShaderGenerationMaxLevel = 64.0f; + m_Desc.tessControlShaderPatchPointMaxNum = 32; + m_Desc.tessControlShaderPerVertexInputComponentMaxNum = 128; + m_Desc.tessControlShaderPerVertexOutputComponentMaxNum = 128; + m_Desc.tessControlShaderPerPatchOutputComponentMaxNum = 128; + m_Desc.tessControlShaderTotalOutputComponentMaxNum = m_Desc.tessControlShaderPatchPointMaxNum * m_Desc.tessControlShaderPerVertexOutputComponentMaxNum + m_Desc.tessControlShaderPerPatchOutputComponentMaxNum; + + m_Desc.tessEvaluationShaderInputComponentMaxNum = 128; + m_Desc.tessEvaluationShaderOutputComponentMaxNum = 128; + + m_Desc.geometryShaderInvocationMaxNum = 32; + m_Desc.geometryShaderInputComponentMaxNum = 128; + m_Desc.geometryShaderOutputComponentMaxNum = 128; + m_Desc.geometryShaderOutputVertexMaxNum = 1024; + m_Desc.geometryShaderTotalOutputComponentMaxNum = 1024; + + m_Desc.fragmentShaderInputComponentMaxNum = 128; + m_Desc.fragmentShaderOutputAttachmentMaxNum = 8; + m_Desc.fragmentShaderDualSourceAttachmentMaxNum = 1; + + +// m_Desc.computeShaderSharedMemoryMaxSize = [m_Device maxThreadgroupMemoryLength]; +// const MTLSize threadGroupSize = [m_Device maxThreadsPerThreadgroup]; +// //familiesm_Desc.computeShaderWorkGroupMaxNum = threadGroupSize.width; +// m_Desc.computeShaderWorkGroupMaxNum[0] = threadGroupSize.width; +// m_Desc.computeShaderWorkGroupMaxNum[1] = threadGroupSize.height; +// m_Desc.computeShaderWorkGroupMaxNum[2] = threadGroupSize.depth; + m_Desc.computeShaderSharedMemoryMaxSize = 64 * 1024; + m_Desc.computeShaderWorkGroupMaxNum[0] = 64 * 1024; + m_Desc.computeShaderWorkGroupMaxNum[1] = 64 * 1024; + m_Desc.computeShaderWorkGroupMaxNum[2] = 64 * 1024; + m_Desc.computeShaderWorkGroupInvocationMaxNum = 64 * 1024; + m_Desc.computeShaderWorkGroupMaxDim[0] = 64 * 1024; + m_Desc.computeShaderWorkGroupMaxDim[1] = 64 * 1024; + m_Desc.computeShaderWorkGroupMaxDim[2] = 64 * 1024; + + m_Desc.rayTracingShaderGroupIdentifierSize = 32; + m_Desc.rayTracingShaderTableMaxStride = (uint32_t)(-1); + m_Desc.rayTracingShaderRecursionMaxDepth = 31; + m_Desc.rayTracingGeometryObjectMaxNum = (uint32_t)(-1); + + m_Desc.meshControlSharedMemoryMaxSize = 64 * 1024; + m_Desc.meshControlWorkGroupInvocationMaxNum = 128; + m_Desc.meshControlPayloadMaxSize = 64 * 1024; + m_Desc.meshEvaluationOutputVerticesMaxNum = 256; + m_Desc.meshEvaluationOutputPrimitiveMaxNum = 256; + m_Desc.meshEvaluationOutputComponentMaxNum = 128; + m_Desc.meshEvaluationSharedMemoryMaxSize = 64 * 1024; + m_Desc.meshEvaluationWorkGroupInvocationMaxNum = 128; + + m_Desc.viewportPrecisionBits = 8; + m_Desc.subPixelPrecisionBits = 8; + m_Desc.subTexelPrecisionBits = 8; + m_Desc.mipmapPrecisionBits = 8; + + m_Desc.drawIndirectMaxNum = uint32_t(-1); + m_Desc.samplerLodBiasMin = -16.0f; + m_Desc.samplerLodBiasMax = 16.0f; + m_Desc.samplerAnisotropyMax = 16; + m_Desc.texelOffsetMin = -8; + m_Desc.texelOffsetMax = 7; + m_Desc.texelGatherOffsetMin = -8; + m_Desc.texelGatherOffsetMax = 7; + m_Desc.clipDistanceMaxNum = 8; + m_Desc.cullDistanceMaxNum = 8; + m_Desc.combinedClipAndCullDistanceMaxNum = 8; + m_Desc.shadingRateAttachmentTileSize = 16; + m_Desc.shaderModel = 69; + + m_Desc.conservativeRasterTier = 3; + m_Desc.sampleLocationsTier = 2; + m_Desc.shadingRateTier = 2; + m_Desc.bindlessTier = 2; + m_Desc.bindlessTier = 2; + + m_Desc.isRayTracingSupported = [m_Device supportsRaytracing]; + + const MTLGPUFamily appleFamilyGPUs[] = { + MTLGPUFamilyApple9, + MTLGPUFamilyApple8, + MTLGPUFamilyApple7, + MTLGPUFamilyApple6, + MTLGPUFamilyApple5, + MTLGPUFamilyApple4, + MTLGPUFamilyApple3, + MTLGPUFamilyApple2, + MTLGPUFamilyApple1 + }; + + const MTLGPUFamily macFamilyGPUs[] = { + MTLGPUFamilyMac2 + }; + + // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf + MTLGPUFamily maxSelectedGPU; + m_Desc.texture3DMaxDim = 2048; + if(FindMTLGpuFamily(m_Device, appleFamilyGPUs, GetCountOf(appleFamilyGPUs), &maxSelectedGPU)) { + m_Desc.texture2DMaxDim = (maxSelectedGPU >= MTLGPUFamilyApple3) ? 16384 : 8192; + m_Desc.texture1DMaxDim = (maxSelectedGPU >= MTLGPUFamilyApple3) ? 16384 : 8192; + + } else if(FindMTLGpuFamily(m_Device, macFamilyGPUs, GetCountOf(macFamilyGPUs), &maxSelectedGPU)) { + m_Desc.texture2DMaxDim = 16384; + m_Desc.texture1DMaxDim = 16384; + } else { + return Result::UNSUPPORTED; + } + + + return Result::SUCCESS; + +} + +#include "DeviceMTL.hpp" + diff --git a/Source/Metal/FencMTL.mm b/Source/Metal/FencMTL.mm new file mode 100644 index 00000000..e8b0402e --- /dev/null +++ b/Source/Metal/FencMTL.mm @@ -0,0 +1,21 @@ +#include "SharedMTL.h" + +#include "FenceMTL.h" + +using namespace nri; + +FenceMTL::~FenceMTL() { + +} + +Result FenceMTL::Create(uint64_t initialValue) { + m_Handle = dispatch_semaphore_create(initialValue); +} + +void FenceMTL::SetDebugName(const char* name) { + +} + +void FenceMTL::Wait(uint64_t value) { + dispatch_semaphore_wait(m_Handle, DISPATCH_TIME_FOREVER); +} diff --git a/Source/Metal/FenceMTL.h b/Source/Metal/FenceMTL.h new file mode 100644 index 00000000..cb933545 --- /dev/null +++ b/Source/Metal/FenceMTL.h @@ -0,0 +1,31 @@ +// © 2021 NVIDIA Corporation + +#pragma once + +#import + +namespace nri { + +struct DeviceMTL; + +struct FenceMTL { + inline FenceMTL(DeviceMTL& device) + : m_Device(device) { + } + ~FenceMTL(); + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + Result Create(uint64_t initialValue); + + void SetDebugName(const char* name); + //uint64_t GetFenceValue() const; + void Wait(uint64_t value); +private: + dispatch_semaphore_t m_Handle; + DeviceMTL& m_Device; +}; + +} // namespace nri diff --git a/Source/Metal/ImplMTL.mm b/Source/Metal/ImplMTL.mm new file mode 100644 index 00000000..3758ae9a --- /dev/null +++ b/Source/Metal/ImplMTL.mm @@ -0,0 +1,686 @@ +// © 2021 NVIDIA Corporation + +#include "SharedMTL.h" + +using namespace nri; + +#include "BufferMTL.h" +#include "CommandAllocatorMTL.h" +#include "CommandBufferMTL.h" +#include "DeviceMTL.h" +#include "DescriptorMTL.h" +#include "TextureMTL.h" +#include "PipelineLayoutMTL.h" +#include "PipelineMTL.h" +#include "DescriptorMTL.h" +#include "MemoryMTL.h" +#include "HelperDeviceMemoryAllocator.h" +#include "CommandQueueMTL.h" +#include "SwapChainMTL.h" +#include "FenceMTL.h" +#include "DescriptorPoolMTL.h" +#include "DescriptorSetMTL.h" + +Result CreateDeviceMTL(const DeviceCreationDesc& desc, DeviceBase*& device) { + StdAllocator allocator(desc.allocationCallbacks); + DeviceMTL* impl = Allocate(allocator, desc.callbackInterface, allocator); + Result result = impl->Create(desc, {}, false); + + MTLPurgeableState a; + MTLStorageMode mode; + if (result != Result::SUCCESS) { + Destroy(allocator, impl); + device = nullptr; + } else + device = (DeviceBase*)impl; + return result; +} + + +Result CreateDeviceMTL(const DeviceCreationMTLDesc& desc, DeviceBase*& device) { + return Result::SUCCESS; +} +//============================================================================================================================================================================================ +#pragma region[ Core ] + + +static void NRI_CALL SetBufferDebugName(Buffer& buffer, const char* name) { + ((BufferMTL&)buffer).SetDebugName(name); +} + +static uint64_t NRI_CALL GetBufferNativeObject(const Buffer& buffer) { + if (!(&buffer)) + return 0; + return uint64_t(((BufferMTL&)buffer).GetHandle()); +} + + +static void* NRI_CALL MapBuffer(Buffer& buffer, uint64_t offset, uint64_t size) { + return ((BufferMTL&)buffer).Map(offset, size); +} + +static void NRI_CALL UnmapBuffer(Buffer& buffer) { + ((BufferMTL&)buffer).Unmap(); +} + +static void NRI_CALL SetCommandAllocatorDebugName(CommandAllocator& commandAllocator, const char* name) { + ((CommandAllocatorMTL&)commandAllocator).SetDebugName(name); +} + +static Result NRI_CALL CreateCommandBuffer(CommandAllocator& commandAllocator, CommandBuffer*& commandBuffer) { + return ((CommandAllocatorMTL&)commandAllocator).CreateCommandBuffer(commandBuffer); +} + +static Result NRI_CALL CreateDescriptorPool(Device& device, const DescriptorPoolDesc& descriptorPoolDesc, DescriptorPool*& descriptorPool) { + return ((DeviceMTL&)device).CreateImplementation(descriptorPool, descriptorPoolDesc); +} + +static void NRI_CALL ResetCommandAllocator(CommandAllocator& commandAllocator) { + ((CommandAllocatorMTL&)commandAllocator).Reset(); +} + +static void NRI_CALL SetCommandBufferDebugName(CommandBuffer& commandBuffer, const char* name) { + ((CommandBufferMTL&)commandBuffer).SetDebugName(name); +} + +static Result NRI_CALL BeginCommandBuffer(CommandBuffer& commandBuffer, const DescriptorPool* descriptorPool) { + return ((CommandBufferMTL&)commandBuffer).Begin(descriptorPool); +} + +static Result NRI_CALL EndCommandBuffer(CommandBuffer& commandBuffer) { + return ((CommandBufferMTL&)commandBuffer).End(); +} + +static void NRI_CALL CmdSetPipelineLayout(CommandBuffer& commandBuffer, const PipelineLayout& pipelineLayout) { + ((CommandBufferMTL&)commandBuffer).SetPipelineLayout(pipelineLayout); +} + +static void NRI_CALL CmdSetPipeline(CommandBuffer& commandBuffer, const Pipeline& pipeline) { + ((CommandBufferMTL&)commandBuffer).SetPipeline(pipeline); +} + +static void NRI_CALL CmdBarrier(CommandBuffer& commandBuffer, const BarrierGroupDesc& barrierGroupDesc) { + ((CommandBufferMTL&)commandBuffer).Barrier(barrierGroupDesc); +} + +static void NRI_CALL CmdSetDescriptorPool(CommandBuffer& commandBuffer, const DescriptorPool& descriptorPool) { + ((CommandBufferMTL&)commandBuffer).SetDescriptorPool(descriptorPool); +} + +static void NRI_CALL CmdSetDescriptorSet(CommandBuffer& commandBuffer, uint32_t setIndex, const DescriptorSet& descriptorSet, const uint32_t* dynamicConstantBufferOffsets) { + ((CommandBufferMTL&)commandBuffer).SetDescriptorSet(setIndex, descriptorSet, dynamicConstantBufferOffsets); +} + +static void NRI_CALL CmdSetRootConstants(CommandBuffer& commandBuffer, uint32_t rootConstantIndex, const void* data, uint32_t size) { + //((CommandBufferMTL&)commandBuffer).SetRootConstants(rootConstantIndex, data, size); +} + +static void NRI_CALL CmdSetRootDescriptor(CommandBuffer& commandBuffer, uint32_t rootDescriptorIndex, Descriptor& descriptor) { + //((CommandBufferMTL&)commandBuffer).SetRootDescriptor(rootDescriptorIndex, descriptor); +} + +static void NRI_CALL CmdBeginRendering(CommandBuffer& commandBuffer, const AttachmentsDesc& attachmentsDesc) { + ((CommandBufferMTL&)commandBuffer).BeginRendering(attachmentsDesc); +} + +static void NRI_CALL CmdEndRendering(CommandBuffer& commandBuffer) { + ((CommandBufferMTL&)commandBuffer).EndRendering(); +} + +static void NRI_CALL CmdSetViewports(CommandBuffer& commandBuffer, const Viewport* viewports, uint32_t viewportNum) { + ((CommandBufferMTL&)commandBuffer).SetViewports(viewports, viewportNum); +} + +static void NRI_CALL CmdSetScissors(CommandBuffer& commandBuffer, const nri::Rect* rects, uint32_t rectNum) { + ((CommandBufferMTL&)commandBuffer).SetScissors(rects, rectNum); +} + +static void NRI_CALL CmdSetDepthBounds(CommandBuffer& commandBuffer, float boundsMin, float boundsMax) { + ((CommandBufferMTL&)commandBuffer).SetDepthBounds(boundsMin, boundsMax); +} + +static void NRI_CALL CmdSetStencilReference(CommandBuffer& commandBuffer, uint8_t frontRef, uint8_t backRef) { + ((CommandBufferMTL&)commandBuffer).SetStencilReference(frontRef, backRef); +} + +static void NRI_CALL CmdSetSampleLocations(CommandBuffer& commandBuffer, const SampleLocation* locations, Sample_t locationNum, Sample_t sampleNum) { + //((CommandBufferMTL&)commandBuffer).SetSampleLocations(locations, locationNum, sampleNum); +} + +static void NRI_CALL CmdSetBlendConstants(CommandBuffer& commandBuffer, const Color32f& color) { + ((CommandBufferMTL&)commandBuffer).SetBlendConstants(color); +} + +static void NRI_CALL CmdSetShadingRate(CommandBuffer& commandBuffer, const ShadingRateDesc& shadingRateDesc) { + ((CommandBufferMTL&)commandBuffer).SetShadingRate(shadingRateDesc); +} + +static void NRI_CALL CmdSetDepthBias(CommandBuffer& commandBuffer, const DepthBiasDesc& depthBiasDesc) { + // ((CommandBufferMTL&)commandBuffer).SetDepthBias(depthBiasDesc); +} + +static void NRI_CALL CmdClearAttachments(CommandBuffer& commandBuffer, const ClearDesc* clearDescs, uint32_t clearDescNum, const nri::Rect* rects, uint32_t rectNum) { + //((CommandBufferMTL&)commandBuffer).ClearAttachments(clearDescs, clearDescNum, rects, rectNum); +} + +static void NRI_CALL CmdSetIndexBuffer(CommandBuffer& commandBuffer, const Buffer& buffer, uint64_t offset, IndexType indexType) { + ((CommandBufferMTL&)commandBuffer).SetIndexBuffer(buffer, offset, indexType); +} + +static void NRI_CALL CmdSetVertexBuffers(CommandBuffer& commandBuffer, uint32_t baseSlot, uint32_t bufferNum, const Buffer* const* buffers, const uint64_t* offsets) { + ((CommandBufferMTL&)commandBuffer).SetVertexBuffers(baseSlot, bufferNum, buffers, offsets); +} + +static void NRI_CALL CmdDraw(CommandBuffer& commandBuffer, const DrawDesc& drawDesc) { + ((CommandBufferMTL&)commandBuffer).Draw(drawDesc); +} + +static void NRI_CALL CmdDrawIndexed(CommandBuffer& commandBuffer, const DrawIndexedDesc& drawIndexedDesc) { + ((CommandBufferMTL&)commandBuffer).DrawIndexed(drawIndexedDesc); +} + +static void NRI_CALL CmdDrawIndirect(CommandBuffer& commandBuffer, const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride, const Buffer* countBuffer, uint64_t countBufferOffset) { + ((CommandBufferMTL&)commandBuffer).DrawIndirect(buffer, offset, drawNum, stride, countBuffer, countBufferOffset); +} + +static void NRI_CALL CmdDrawIndexedIndirect(CommandBuffer& commandBuffer, const Buffer& buffer, uint64_t offset, uint32_t drawNum, uint32_t stride, const Buffer* countBuffer, uint64_t countBufferOffset) { + ((CommandBufferMTL&)commandBuffer).DrawIndexedIndirect(buffer, offset, drawNum, stride, countBuffer, countBufferOffset); +} + +static void NRI_CALL CmdDispatch(CommandBuffer& commandBuffer, const DispatchDesc& dispatchDesc) { + ((CommandBufferMTL&)commandBuffer).Dispatch(dispatchDesc); +} + +static void NRI_CALL CmdDispatchIndirect(CommandBuffer& commandBuffer, const Buffer& buffer, uint64_t offset) { + ((CommandBufferMTL&)commandBuffer).DispatchIndirect(buffer, offset); +} + +static void NRI_CALL CmdBeginQuery(CommandBuffer& commandBuffer, const QueryPool& queryPool, uint32_t offset) { + ((CommandBufferMTL&)commandBuffer).BeginQuery(queryPool, offset); +} + +static void NRI_CALL CmdEndQuery(CommandBuffer& commandBuffer, const QueryPool& queryPool, uint32_t offset) { + ((CommandBufferMTL&)commandBuffer).EndQuery(queryPool, offset); +} + +static void NRI_CALL CmdBeginAnnotation(CommandBuffer& commandBuffer, const char* name, uint32_t bgra) { + ((CommandBufferMTL&)commandBuffer).BeginAnnotation(name); +} + +static void NRI_CALL CmdEndAnnotation(CommandBuffer& commandBuffer) { + ((CommandBufferMTL&)commandBuffer).EndAnnotation(); +} + +static void NRI_CALL CmdClearStorageBuffer(CommandBuffer& commandBuffer, const ClearStorageBufferDesc& clearDesc) { + ((CommandBufferMTL&)commandBuffer).ClearStorageBuffer(clearDesc); +} + +static void NRI_CALL CmdClearStorageTexture(CommandBuffer& commandBuffer, const ClearStorageTextureDesc& clearDesc) { + ((CommandBufferMTL&)commandBuffer).ClearStorageTexture(clearDesc); +} + +static void NRI_CALL CmdResolveTexture(CommandBuffer& commandBuffer, Texture& dstTexture, const TextureRegionDesc* dstRegionDesc, const Texture& srcTexture, const TextureRegionDesc* srcRegionDesc) { + //((CommandBufferMTL&)commandBuffer).ResolveTexture(dstTexture, dstRegionDesc, srcTexture, srcRegionDesc); +} + + +static void NRI_CALL Wait(Fence& fence, uint64_t value) { + ((FenceMTL&)fence).Wait(value); +} + +static void NRI_CALL CmdCopyBuffer(CommandBuffer& commandBuffer, Buffer& dstBuffer, uint64_t dstOffset, const Buffer& srcBuffer, uint64_t srcOffset, uint64_t size) { + ((CommandBufferMTL&)commandBuffer).CopyBuffer(dstBuffer, dstOffset, srcBuffer, srcOffset, size); +} + +static void NRI_CALL CmdCopyTexture( + CommandBuffer& commandBuffer, Texture& dstTexture, const TextureRegionDesc* dstRegionDesc, const Texture& srcTexture, const TextureRegionDesc* srcRegionDesc) { + ((CommandBufferMTL&)commandBuffer).CopyTexture(dstTexture, dstRegionDesc, srcTexture, srcRegionDesc); +} + +static void NRI_CALL CmdUploadBufferToTexture(CommandBuffer& commandBuffer, Texture& dstTexture, const TextureRegionDesc& dstRegionDesc, const Buffer& srcBuffer, const TextureDataLayoutDesc& srcDataLayoutDesc) { + ((CommandBufferMTL&)commandBuffer).UploadBufferToTexture(dstTexture, dstRegionDesc, srcBuffer, srcDataLayoutDesc); +} + +static void NRI_CALL CmdReadbackTextureToBuffer(CommandBuffer& commandBuffer, Buffer& dstBuffer, const TextureDataLayoutDesc& dstDataLayoutDesc, const Texture& srcTexture, const TextureRegionDesc& srcRegionDesc) { + ((CommandBufferMTL&)commandBuffer).ReadbackTextureToBuffer(dstBuffer, dstDataLayoutDesc, srcTexture, srcRegionDesc); +} + +static void NRI_CALL CmdCopyQueries(CommandBuffer& commandBuffer, const QueryPool& queryPool, uint32_t offset, uint32_t num, Buffer& dstBuffer, uint64_t dstOffset) { + ((CommandBufferMTL&)commandBuffer).CopyQueries(queryPool, offset, num, dstBuffer, dstOffset); +} + +static Result NRI_CALL AllocateMemory(Device& device, const AllocateMemoryDesc& allocateMemoryDesc, Memory*& memory) { + return ((DeviceMTL&)device).CreateImplementation(memory, allocateMemoryDesc); +} + +static Result NRI_CALL BindBufferMemory(Device& device, const BufferMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum) { + return ((DeviceMTL&)device).BindBufferMemory(memoryBindingDescs, memoryBindingDescNum); +} + +static Result NRI_CALL BindTextureMemory(Device& device, const TextureMemoryBindingDesc* memoryBindingDescs, uint32_t memoryBindingDescNum) { + return ((DeviceMTL&)device).BindTextureMemory(memoryBindingDescs, memoryBindingDescNum); +} + + +static void NRI_CALL CmdResetQueries(CommandBuffer& commandBuffer, QueryPool& queryPool, uint32_t offset, uint32_t num) { + ((CommandBufferMTL&)commandBuffer).ResetQueries(queryPool, offset, num); +} + +static const DeviceDesc& NRI_CALL GetDeviceDesc(const Device& device) { + return ((DeviceMTL&)device).GetDesc(); +} + +static Result NRI_CALL CreateTexture(Device& device, const TextureDesc& textureDesc, Texture*& texture) { + return ((DeviceMTL&)device).CreateImplementation(texture, textureDesc); +} + +static Result NRI_CALL CreateCommandAllocator(const CommandQueue& commandQueue, CommandAllocator*& commandAllocator) { + DeviceMTL& device = ((CommandQueueMTL&)commandQueue).GetDevice(); + return device.CreateImplementation(commandAllocator, commandQueue); +} + +static Result NRI_CALL CreateBufferView(const BufferViewDesc& bufferViewDesc, Descriptor*& bufferView) { + DeviceMTL& device = ((const BufferMTL*)bufferViewDesc.buffer)->GetDevice(); + return device.CreateImplementation(bufferView, bufferViewDesc); +} + +static Result NRI_CALL CreateBuffer(Device& device, const BufferDesc& bufferDesc, Buffer*& buffer) { + return ((DeviceMTL&)device).CreateImplementation(buffer, bufferDesc); +} + +static Result NRI_CALL CreateTexture1DView(const Texture1DViewDesc& textureViewDesc, Descriptor*& textureView) { + DeviceMTL& device = ((const TextureMTL*)textureViewDesc.texture)->GetDevice(); + return device.CreateImplementation(textureView, textureViewDesc); +} + +static Result NRI_CALL CreateTexture2DView(const Texture2DViewDesc& textureViewDesc, Descriptor*& textureView) { + DeviceMTL& device = ((const TextureMTL*)textureViewDesc.texture)->GetDevice(); + return device.CreateImplementation(textureView, textureViewDesc); +} + +static Result NRI_CALL CreateTexture3DView(const Texture3DViewDesc& textureViewDesc, Descriptor*& textureView) { + DeviceMTL& device = ((const TextureMTL*)textureViewDesc.texture)->GetDevice(); + return device.CreateImplementation(textureView, textureViewDesc); +} + + +static void NRI_CALL UpdateDynamicConstantBuffers(DescriptorSet& descriptorSet, uint32_t baseDynamicConstantBuffer, uint32_t dynamicConstantBufferNum, const Descriptor* const* descriptors) { +// ((DescriptorSetMTL&)descriptorSet).UpdateDynamicConstantBuffers(baseDynamicConstantBuffer, dynamicConstantBufferNum, descriptors); +} + +static void NRI_CALL CopyDescriptorSet(DescriptorSet& descriptorSet, const DescriptorSetCopyDesc& descriptorSetCopyDesc) { +// ((DescriptorSetMTL&)descriptorSet).Copy(descriptorSetCopyDesc); +} + + +static void NRI_CALL UpdateDescriptorRanges(DescriptorSet& descriptorSet, uint32_t baseRange, uint32_t rangeNum, const DescriptorRangeUpdateDesc* rangeUpdateDescs) { + ((DescriptorSetMTL&)descriptorSet).UpdateDescriptorRanges(baseRange, rangeNum, rangeUpdateDescs); +} + + +static Result NRI_CALL CreateSampler(Device& device, const SamplerDesc& samplerDesc, Descriptor*& sampler) { + return ((DeviceMTL&)device).CreateImplementation(sampler, samplerDesc); +} + +static Result NRI_CALL CreatePipelineLayout(Device& device, const PipelineLayoutDesc& pipelineLayoutDesc, PipelineLayout*& pipelineLayout) { + return ((DeviceMTL&)device).CreateImplementation(pipelineLayout, pipelineLayoutDesc); +} + +static void NRI_CALL QueueSubmit(CommandQueue& commandQueue, const QueueSubmitDesc& workSubmissionDesc) { + ((CommandQueueMTL&)commandQueue).Submit(workSubmissionDesc, nullptr); +} + + +static void NRI_CALL DestroyCommandBuffer(CommandBuffer& commandBuffer) { + Destroy((CommandBufferMTL*)&commandBuffer); +} + +static Result NRI_CALL CreateFence(Device& device, uint64_t initialValue, Fence*& fence) { + return ((DeviceMTL&)device).CreateImplementation(fence, initialValue); +} + + +static void NRI_CALL DestroyCommandAllocator(CommandAllocator& commandAllocator) { + Destroy((CommandAllocatorMTL*)&commandAllocator); +} + +static void NRI_CALL DestroyDescriptorPool(DescriptorPool& descriptorPool) { + Destroy((DescriptorPoolMTL*)&descriptorPool); +} + +static void NRI_CALL DestroyBuffer(Buffer& buffer) { + Destroy((BufferMTL*)&buffer); +} + +static void NRI_CALL DestroyTexture(Texture& texture) { + Destroy((TextureMTL*)&texture); +} + +static void NRI_CALL DestroyDescriptor(Descriptor& descriptor) { + Destroy((DescriptorMTL*)&descriptor); +} + +static void NRI_CALL DestroyPipelineLayout(PipelineLayout& pipelineLayout) { + Destroy((PipelineLayoutMTL*)&pipelineLayout); +} + +static void NRI_CALL DestroyPipeline(Pipeline& pipeline) { + Destroy((PipelineMTL*)&pipeline); +} + +static void NRI_CALL DestroyQueryPool(QueryPool& queryPool) { + //Destroy((QueryPoolVK*)&queryPool); +} + +static void NRI_CALL DestroyFence(Fence& fence) { + Destroy((FenceMTL*)&fence); +} + +static void NRI_CALL FreeMemory(Memory& memory) { + Destroy((MemoryMTL*)&memory); +} + +static void NRI_CALL SetFenceDebugName(Fence& fence, const char* name) { + ((FenceMTL&)fence).SetDebugName(name); +} + +static void NRI_CALL SetDeviceDebugName(Device& device, const char* name) { +// ((DeviceMTL&)device).SetDebugName(name); +} + +static void NRI_CALL SetPipelineDebugName(Pipeline& pipeline, const char* name) { +// ((PipelineMTL&)pipeline).SetDebugName(name); +} + +static void NRI_CALL SetPipelineLayoutDebugName(PipelineLayout& pipelineLayout, const char* name) { +// ((PipelineLayoutMTL&)pipelineLayout).SetDebugName(name); +} + +static void NRI_CALL SetMemoryDebugName(Memory& memory, const char* name) { + ((MemoryMTL&)memory).SetDebugName(name); +} + + +static void* NRI_CALL GetDeviceNativeObject(const Device& device) { + if (!(&device)) + return nullptr; + + return (id)((DeviceMTL&)device); +} + +static const BufferDesc& NRI_CALL GetBufferDesc(const Buffer& buffer) { + return ((const BufferMTL&)buffer).GetDesc(); +} + +static const TextureDesc& NRI_CALL GetTextureDesc(const Texture& texture) { + return ((const TextureMTL&)texture).GetDesc(); +} + +static void NRI_CALL GetBufferMemoryDesc(const Device& device, const BufferDesc& bufferDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) { + ((const DeviceMTL&)device).GetMemoryDesc(bufferDesc, memoryLocation, memoryDesc); +} + +static void NRI_CALL GetTextureMemoryDesc(const Device& device, const TextureDesc& textureDesc, MemoryLocation memoryLocation, MemoryDesc& memoryDesc) { + ((const DeviceMTL&)device).GetMemoryDesc(textureDesc, memoryLocation, memoryDesc); +} + +static Result NRI_CALL GetCommandQueue(Device& device, CommandQueueType commandQueueType, CommandQueue*& commandQueue) { + return ((DeviceMTL&)device).GetCommandQueue(commandQueueType, commandQueue); +} + + +static Result NRI_CALL CreateGraphicsPipeline(Device& device, const GraphicsPipelineDesc& graphicsPipelineDesc, Pipeline*& pipeline) { + return ((DeviceMTL&)device).CreateImplementation(pipeline, graphicsPipelineDesc); +} + +static Result NRI_CALL CreateComputePipeline(Device& device, const ComputePipelineDesc& computePipelineDesc, Pipeline*& pipeline) { + return ((DeviceMTL&)device).CreateImplementation(pipeline, computePipelineDesc); +} + + +static Result NRI_CALL AllocateDescriptorSets(DescriptorPool& descriptorPool, const PipelineLayout& pipelineLayout, uint32_t setIndex, DescriptorSet** descriptorSets, uint32_t instanceNum, uint32_t variableDescriptorNum) { + return ((DescriptorPoolMTL&)descriptorPool).AllocateDescriptorSets(pipelineLayout, setIndex, descriptorSets, instanceNum, variableDescriptorNum); +} + +static void NRI_CALL ResetDescriptorPool(DescriptorPool& descriptorPool) { + ((DescriptorPoolMTL&)descriptorPool).Reset(); +} + + +static void NRI_CALL SetDescriptorDebugName(Descriptor& descriptor, const char* name) { +// ((DescriptorMTL&)descriptor).SetDebugName(name); +} + + +Result DeviceMTL::FillFunctionTable(CoreInterface& table) const { + table.GetDeviceDesc = ::GetDeviceDesc; + table.GetBufferDesc = ::GetBufferDesc; + table.GetTextureDesc = ::GetTextureDesc; + //table.GetFormatSupport = ::GetFormatSupport; + //table.GetQuerySize = ::GetQuerySize; + table.GetBufferMemoryDesc = ::GetBufferMemoryDesc; + table.GetTextureMemoryDesc = ::GetTextureMemoryDesc; + table.GetCommandQueue = ::GetCommandQueue; + table.CreateCommandAllocator = ::CreateCommandAllocator; + table.CreateCommandBuffer = ::CreateCommandBuffer; + table.CreateDescriptorPool = ::CreateDescriptorPool; + table.CreateBuffer = ::CreateBuffer; + table.CreateTexture = ::CreateTexture; + table.CreateBufferView = ::CreateBufferView; + table.CreateTexture1DView = ::CreateTexture1DView; + table.CreateTexture2DView = ::CreateTexture2DView; + table.CreateTexture3DView = ::CreateTexture3DView; + table.CreateSampler = ::CreateSampler; + table.CreatePipelineLayout = ::CreatePipelineLayout; + table.CreateGraphicsPipeline = ::CreateGraphicsPipeline; + table.CreateComputePipeline = ::CreateComputePipeline; +// table.CreateQueryPool = ::CreateQueryPool; + table.CreateFence = ::CreateFence; + table.DestroyCommandAllocator = ::DestroyCommandAllocator; + table.DestroyCommandBuffer = ::DestroyCommandBuffer; + table.DestroyDescriptorPool = ::DestroyDescriptorPool; + table.DestroyBuffer = ::DestroyBuffer; + table.DestroyTexture = ::DestroyTexture; + table.DestroyDescriptor = ::DestroyDescriptor; + table.DestroyPipelineLayout = ::DestroyPipelineLayout; + table.DestroyPipeline = ::DestroyPipeline; + table.DestroyQueryPool = ::DestroyQueryPool; + table.DestroyFence = ::DestroyFence; + table.AllocateMemory = ::AllocateMemory; + table.BindBufferMemory = ::BindBufferMemory; + table.BindTextureMemory = ::BindTextureMemory; + table.FreeMemory = ::FreeMemory; + table.BeginCommandBuffer = ::BeginCommandBuffer; + table.CmdSetDescriptorPool = ::CmdSetDescriptorPool; + table.CmdSetDescriptorSet = ::CmdSetDescriptorSet; + table.CmdSetPipelineLayout = ::CmdSetPipelineLayout; + table.CmdSetPipeline = ::CmdSetPipeline; + table.CmdSetRootConstants = ::CmdSetRootConstants; + table.CmdSetRootDescriptor = ::CmdSetRootDescriptor; + table.CmdBarrier = ::CmdBarrier; + table.CmdSetIndexBuffer = ::CmdSetIndexBuffer; + table.CmdSetVertexBuffers = ::CmdSetVertexBuffers; + table.CmdSetViewports = ::CmdSetViewports; + table.CmdSetScissors = ::CmdSetScissors; + table.CmdSetStencilReference = ::CmdSetStencilReference; + table.CmdSetDepthBounds = ::CmdSetDepthBounds; + table.CmdSetBlendConstants = ::CmdSetBlendConstants; + table.CmdSetSampleLocations = ::CmdSetSampleLocations; + table.CmdSetShadingRate = ::CmdSetShadingRate; + table.CmdSetDepthBias = ::CmdSetDepthBias; + table.CmdBeginRendering = ::CmdBeginRendering; + table.CmdClearAttachments = ::CmdClearAttachments; + table.CmdDraw = ::CmdDraw; + table.CmdDrawIndexed = ::CmdDrawIndexed; + table.CmdDrawIndirect = ::CmdDrawIndirect; + table.CmdDrawIndexedIndirect = ::CmdDrawIndexedIndirect; + table.CmdEndRendering = ::CmdEndRendering; + table.CmdDispatch = ::CmdDispatch; + table.CmdDispatchIndirect = ::CmdDispatchIndirect; + table.CmdCopyBuffer = ::CmdCopyBuffer; + table.CmdCopyTexture = ::CmdCopyTexture; + table.CmdUploadBufferToTexture = ::CmdUploadBufferToTexture; + table.CmdReadbackTextureToBuffer = ::CmdReadbackTextureToBuffer; + table.CmdClearStorageBuffer = ::CmdClearStorageBuffer; + table.CmdClearStorageTexture = ::CmdClearStorageTexture; + table.CmdResolveTexture = ::CmdResolveTexture; + table.CmdResetQueries = ::CmdResetQueries; +// table.CmdBeginQuery = ::CmdBeginQuery; +// table.CmdEndQuery = ::CmdEndQuery; + table.CmdCopyQueries = ::CmdCopyQueries; + table.CmdBeginAnnotation = ::CmdBeginAnnotation; + table.CmdEndAnnotation = ::CmdEndAnnotation; + table.EndCommandBuffer = ::EndCommandBuffer; + table.QueueSubmit = ::QueueSubmit; + table.Wait = ::Wait; +// table.GetFenceValue = ::GetFenceValue; + table.UpdateDescriptorRanges = ::UpdateDescriptorRanges; + table.UpdateDynamicConstantBuffers = ::UpdateDynamicConstantBuffers; +// table.CopyDescriptorSet = ::CopyDescriptorSet; + table.AllocateDescriptorSets = ::AllocateDescriptorSets; + table.ResetDescriptorPool = ::ResetDescriptorPool; + table.ResetCommandAllocator = ::ResetCommandAllocator; + table.MapBuffer = ::MapBuffer; + table.UnmapBuffer = ::UnmapBuffer; + table.SetDeviceDebugName = ::SetDeviceDebugName; + table.SetFenceDebugName = ::SetFenceDebugName; + table.SetDescriptorDebugName = ::SetDescriptorDebugName; + table.SetPipelineDebugName = ::SetPipelineDebugName; + table.SetCommandBufferDebugName = ::SetCommandBufferDebugName; + table.SetBufferDebugName = ::SetBufferDebugName; +// table.SetTextureDebugName = ::SetTextureDebugName; +// table.SetCommandQueueDebugName = ::SetCommandQueueDebugName; + table.SetCommandAllocatorDebugName = ::SetCommandAllocatorDebugName; +// table.SetDescriptorPoolDebugName = ::SetDescriptorPoolDebugName; +// table.SetPipelineLayoutDebugName = ::SetPipelineLayoutDebugName; +// table.SetQueryPoolDebugName = ::SetQueryPoolDebugName; +// table.SetDescriptorSetDebugName = ::SetDescriptorSetDebugName; +// table.SetMemoryDebugName = ::SetMemoryDebugName; + table.GetDeviceNativeObject = ::GetDeviceNativeObject; +// table.GetCommandBufferNativeObject = ::GetCommandBufferNativeObject; + table.GetBufferNativeObject = ::GetBufferNativeObject; +// table.GetTextureNativeObject = ::GetTextureNativeObject; +// table.GetDescriptorNativeObject = ::GetDescriptorNativeObject; + + return Result::SUCCESS; +} + +static uint32_t NRI_CALL CalculateAllocationNumber(const Device& device, const ResourceGroupDesc& resourceGroupDesc) { + DeviceMTL& deviceMTL = (DeviceMTL&)device; + HelperDeviceMemoryAllocator allocator(deviceMTL.GetCoreInterface(), (Device&)device); + + return allocator.CalculateAllocationNumber(resourceGroupDesc); +} + +static Result NRI_CALL UploadData(CommandQueue& commandQueue, const TextureUploadDesc* textureUploadDescs, uint32_t textureUploadDescNum, const BufferUploadDesc* bufferUploadDescs, uint32_t bufferUploadDescNum) { + return ((CommandQueueMTL&)commandQueue).UploadData(textureUploadDescs, textureUploadDescNum, bufferUploadDescs, bufferUploadDescNum); +} + +static Result NRI_CALL AllocateAndBindMemory(Device& device, const ResourceGroupDesc& resourceGroupDesc, Memory** allocations) { + DeviceMTL& deviceMTL = (DeviceMTL&)device; + HelperDeviceMemoryAllocator allocator(deviceMTL.GetCoreInterface(), device); + + return allocator.AllocateAndBindMemory(resourceGroupDesc, allocations); +} + +static Result NRI_CALL WaitForIdle(CommandQueue& commandQueue) { + if (!(&commandQueue)) + return Result::SUCCESS; + + return ((CommandQueueMTL&)commandQueue).WaitForIdle(); +} + +#pragma endregion + +Result DeviceMTL::FillFunctionTable(HelperInterface& table) const { + table.CalculateAllocationNumber = ::CalculateAllocationNumber; + table.AllocateAndBindMemory = ::AllocateAndBindMemory; + table.UploadData = ::UploadData; + table.WaitForIdle = ::WaitForIdle; +// table.QueryVideoMemoryInfo = ::QueryVideoMemoryInfo; + return Result::SUCCESS; +} +Result DeviceMTL::FillFunctionTable(LowLatencyInterface& table) const { + + return Result::SUCCESS; +} +Result DeviceMTL::FillFunctionTable(MeshShaderInterface& table) const { + + return Result::SUCCESS; +} +Result DeviceMTL::FillFunctionTable(RayTracingInterface& table) const { + return Result::SUCCESS; +} +Result DeviceMTL::FillFunctionTable(StreamerInterface& table) const { + return Result::SUCCESS; +} + +static void NRI_CALL SetSwapChainDebugName(SwapChain& swapChain, const char* name) { + ((SwapChainMTL&)swapChain).SetDebugName(name); +} + +//static Result NRI_CALL GetDisplayDesc(SwapChain& swapChain, DisplayDesc& displayDesc) { +// return ((SwapChainMTL&)swapChain).GetDisplayDesc(displayDesc); +//} + +static Result NRI_CALL QueuePresent(SwapChain& swapChain) { + return ((SwapChainMTL&)swapChain).Present(); +} + +static Result NRI_CALL CreateSwapChain(Device& device, const SwapChainDesc& swapChainDesc, SwapChain*& swapChain) { + return ((DeviceMTL&)device).CreateImplementation(swapChain, swapChainDesc); +} + +static Result NRI_CALL WaitForPresent(SwapChain& swapChain) { + return ((SwapChainMTL&)swapChain).WaitForPresent(); +} + +static Texture* const* NRI_CALL GetSwapChainTextures(const SwapChain& swapChain, uint32_t& textureNum) { + return ((SwapChainMTL&)swapChain).GetTextures(textureNum); +} + +static uint32_t NRI_CALL AcquireNextSwapChainTexture(SwapChain& swapChain) { + return ((SwapChainMTL&)swapChain).AcquireNextTexture(); +} + + +static void NRI_CALL DestroySwapChain(SwapChain& swapChain) { + Destroy((SwapChainMTL*)&swapChain); +} + +Result DeviceMTL::FillFunctionTable(SwapChainInterface& table) const { + + if (!m_Desc.isSwapChainSupported) + return Result::UNSUPPORTED; + + table.CreateSwapChain = ::CreateSwapChain; + table.DestroySwapChain = ::DestroySwapChain; + table.SetSwapChainDebugName = ::SetSwapChainDebugName; + table.GetSwapChainTextures = ::GetSwapChainTextures; + table.AcquireNextSwapChainTexture = ::AcquireNextSwapChainTexture; + table.WaitForPresent = ::WaitForPresent; + table.QueuePresent = ::QueuePresent; +// table.GetDisplayDesc = ::GetDisplayDesc; + return Result::SUCCESS; +} + + +static Result AllocateBuffer(Device& device, const AllocateBufferDesc& bufferDesc, Buffer*& buffer) { + return ((DeviceMTL&)device).CreateImplementation(buffer, bufferDesc); +} + +static Result AllocateTexture(Device& device, const AllocateTextureDesc& textureDesc, Texture*& texture) { + return ((DeviceMTL&)device).CreateImplementation(texture, textureDesc); +} + +//static Result AllocateAccelerationStructure(Device& device, const AllocateAccelerationStructureDesc& accelerationStructureDesc, AccelerationStructure*& accelerationStructure) { +// return ((DeviceMTL&)device).CreateImplementation(accelerationStructure, accelerationStructureDesc); +//} + +Result DeviceMTL::FillFunctionTable(ResourceAllocatorInterface& table) const { + table.AllocateBuffer = ::AllocateBuffer; + table.AllocateTexture = ::AllocateTexture; +// table.AllocateAccelerationStructure = ::AllocateAccelerationStructure; + + return Result::SUCCESS; +} diff --git a/Source/Metal/MemoryMTL.h b/Source/Metal/MemoryMTL.h new file mode 100644 index 00000000..db196a91 --- /dev/null +++ b/Source/Metal/MemoryMTL.h @@ -0,0 +1,57 @@ +// © 2021 NVIDIA Corporation + +#pragma once + +#include + +#import + +namespace nri { + +struct DeviceMTL; + +struct MemoryMTL { + + inline MemoryMTL (DeviceMTL& device) + : m_Device(device) { + } + + inline id GetHandle() const { + return m_Handle; + } + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + inline MemoryType GetType() const { + return m_Type; + } + +// inline uint8_t* GetMappedMemory() const { +// return m_MappedMemory; +// } + + ~MemoryMTL(); + + // Result Create(const MemoryMTLDesc& memoryDesc); + Result Create(const AllocateMemoryDesc& allocateMemoryDesc); + // Result CreateDedicated(const BufferVK& buffer); + // Result CreateDedicated(const TextureVK& texture); + + //================================================================================================================ + // NRI + //================================================================================================================ + void SetDebugName(const char* name); + +private: + DeviceMTL& m_Device; + id m_Handle; + MemoryType m_Type; + float m_Priority = 0.0f; + bool m_OwnsNativeObjects = true; +}; + + +} + diff --git a/Source/Metal/MemoryMTL.mm b/Source/Metal/MemoryMTL.mm new file mode 100644 index 00000000..00accab2 --- /dev/null +++ b/Source/Metal/MemoryMTL.mm @@ -0,0 +1,62 @@ +// © 2021 NVIDIA Corporation +#include "SharedMTL.h" + +#include "MemoryMTL.h" + +using namespace nri; + +MemoryMTL::~MemoryMTL() { + //if (m_OwnsNativeObjects) { + // const auto& vk = m_Device.GetDispatchTable(); + // vk.FreeMemory(m_Device, m_Handle, m_Device.GetAllocationCallbacks()); + //} +} + +Result MemoryMTL::Create(const AllocateMemoryDesc& allocateMemoryDesc) { + MTLHeapDescriptor* heapDescriptor = [[MTLHeapDescriptor alloc] init]; + MemoryTypeInfo typeInfo; + typeInfo.value = allocateMemoryDesc.type; + [heapDescriptor setCpuCacheMode: (MTLCPUCacheMode)typeInfo.cacheMode]; + [heapDescriptor setStorageMode: (MTLStorageMode)typeInfo.storageMode]; + [heapDescriptor setResourceOptions: (MTLResourceOptions)typeInfo.options]; + [heapDescriptor setSize: allocateMemoryDesc.size]; + m_Handle = [m_Device newHeapWithDescriptor: heapDescriptor]; + m_Type = allocateMemoryDesc.type; + m_Priority = allocateMemoryDesc.priority; +} + +void MemoryMTL::SetDebugName(const char* name) { + NSString* str = [NSString stringWithUTF8String:name]; + [m_Handle setLabel: str]; +} + + +//Result MemoryMTL::Create(const MemoryMTLDesc& memoryDesc) { +// MTLHeapDescriptor* heapDescriptor = [[MTLHeapDescriptor alloc] init]; +// +// [heapDescriptor setSize:memoryDesc.size]; +// +// // [heapDescriptor setStorageMode:memoryDesc.storage]; +// +// // if (!memoryDesc.vkDeviceMemory) +// // return Result::INVALID_ARGUMENT; +// +// // MemoryTypeInfo memoryTypeInfo = {}; +// +// //bool found = m_Device.GetMemoryTypeByIndex(memoryDesc.memoryTypeIndex, memoryTypeInfo); +// //RETURN_ON_FAILURE(&m_Device, found, Result::INVALID_ARGUMENT, "Can't find memory by index"); +// +//// m_OwnsNativeObjects = false; +// // m_Buffer = memoryDesc.buffer; +//// m_MappedMemory = (uint8_t*)memoryDesc.mappedMemory; +// // m_Type = memoryDesc.options; +// +// // const auto& mtl = m_Device.GetDispatchTable(); +// //if (!m_MappedMemory && IsHostVisibleMemory(memoryTypeInfo.location)) { +// // VkResult result = mtl.MapMemory(m_Device, m_Handle, 0, memoryDesc.size, 0, (void**)&m_MappedMemory); +// // RETURN_ON_FAILURE(&m_Device, result == VK_SUCCESS, GetReturnCode(result), "vkMapMemory returned %d", (int32_t)result); +// //} +// +// return Result::SUCCESS; +//} + diff --git a/Source/Metal/PipelineLayoutMTL.h b/Source/Metal/PipelineLayoutMTL.h new file mode 100644 index 00000000..e6416b5f --- /dev/null +++ b/Source/Metal/PipelineLayoutMTL.h @@ -0,0 +1,54 @@ +#pragma once + +#import + +namespace nri { + +struct DeviceMTL; + +struct DescriptorSetLayout { + DescriptorSetDesc m_DescriptorSetDesc; + NSMutableArray* m_ArgumentDescriptors; +}; + +struct PipelineLayoutMTL { + + inline PipelineLayoutMTL (DeviceMTL& device) + : m_Device(device) + , m_HasVariableDescriptorNum(device.GetStdAllocator()) + , m_DescriptorSetRangeDescs(device.GetStdAllocator()) + , m_DynamicConstantBufferDescs(device.GetStdAllocator()) + , m_DescriptorSetLayouts(device.GetStdAllocator()) + , m_PushBindingConstants(device.GetStdAllocator()) + { + } + + ~PipelineLayoutMTL(); + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + const inline struct DescriptorSetLayout* GetDescriptorSetLayout(uint32_t setIndex) const { + return &m_DescriptorSetLayouts[setIndex]; + } + + const inline struct RootConstantDesc* GetPushBinding(uint32_t index) { + return &m_PushBindingConstants[index]; + } + + Result Create(const PipelineLayoutDesc& pipelineLayoutDesc); + + +private: + DeviceMTL& m_Device; + + Vector m_HasVariableDescriptorNum; + Vector m_DescriptorSetRangeDescs; + Vector m_DynamicConstantBufferDescs; + Vector m_DescriptorSetLayouts; + Vector m_PushBindingConstants; + +}; + +} diff --git a/Source/Metal/PipelineLayoutMTL.mm b/Source/Metal/PipelineLayoutMTL.mm new file mode 100644 index 00000000..fa88fad9 --- /dev/null +++ b/Source/Metal/PipelineLayoutMTL.mm @@ -0,0 +1,84 @@ +#include "SharedMTL.h" + +#include "PipelineLayoutMTL.h" + +using namespace nri; + +PipelineLayoutMTL::~PipelineLayoutMTL() { + +} + +Result PipelineLayoutMTL::Create(const PipelineLayoutDesc& pipelineLayoutDesc) { + + size_t rangeNum = 0; + size_t dynamicConstantBufferNum = 0; + for (uint32_t i = 0; i < pipelineLayoutDesc.descriptorSetNum; i++) { + rangeNum += pipelineLayoutDesc.descriptorSets[i].rangeNum; + dynamicConstantBufferNum += pipelineLayoutDesc.descriptorSets[i].dynamicConstantBufferNum; + } + + //m_DescriptorSetDesc.insert(m_DescriptorSetDesc.begin(), pipelineLayoutDesc.descriptorSets, pipelineLayoutDesc.descriptorSets + pipelineLayoutDesc.descriptorSetNum); + m_DescriptorSetLayouts.reserve(pipelineLayoutDesc.descriptorSetNum); + m_HasVariableDescriptorNum.reserve(pipelineLayoutDesc.descriptorSetNum); + m_DescriptorSetRangeDescs.reserve(rangeNum); + m_DynamicConstantBufferDescs.reserve(dynamicConstantBufferNum); + m_PushBindingConstants.resize(pipelineLayoutDesc.rootConstantNum); + + for (uint32_t i = 0; i < pipelineLayoutDesc.descriptorSetNum; i++) { + const DescriptorSetDesc& descriptorSetDesc = pipelineLayoutDesc.descriptorSets[i]; + + // Binding info + m_HasVariableDescriptorNum[i] = false; + m_DescriptorSetLayouts[i].m_DescriptorSetDesc = descriptorSetDesc; + m_DescriptorSetLayouts[i].m_DescriptorSetDesc.ranges = m_DescriptorSetRangeDescs.data() + m_DescriptorSetRangeDescs.size(); + m_DescriptorSetLayouts[i].m_DescriptorSetDesc.dynamicConstantBuffers = m_DynamicConstantBufferDescs.data() + m_DynamicConstantBufferDescs.size(); + m_DescriptorSetRangeDescs.insert(m_DescriptorSetRangeDescs.end(), descriptorSetDesc.ranges, descriptorSetDesc.ranges + descriptorSetDesc.rangeNum); + m_DynamicConstantBufferDescs.insert(m_DynamicConstantBufferDescs.end(), descriptorSetDesc.dynamicConstantBuffers, descriptorSetDesc.dynamicConstantBuffers + descriptorSetDesc.dynamicConstantBufferNum); + + NSMutableArray* argumentDescriptors = [[NSMutableArray alloc] init]; + for(size_t r = 0; r < descriptorSetDesc.rangeNum; r++) { + MTLArgumentDescriptor* argDescriptor = [MTLArgumentDescriptor argumentDescriptor]; + const DescriptorRangeDesc* range = &descriptorSetDesc.ranges[r]; + argDescriptor.arrayLength = range->descriptorNum; + argDescriptor.access = MTLBindingAccessReadWrite; + argDescriptor.index = range->baseRegisterIndex; + switch(range->descriptorType) { + case DescriptorType::TEXTURE: + argDescriptor.dataType = MTLDataTypeTexture; + argDescriptor.textureType = MTLTextureType2D; // descriptor type does not have this + break; + case DescriptorType::SAMPLER: + argDescriptor.dataType = MTLDataTypeSampler; + break; + case DescriptorType::CONSTANT_BUFFER: + case DescriptorType::STORAGE_TEXTURE: + case DescriptorType::BUFFER: + case DescriptorType::STORAGE_BUFFER: + case DescriptorType::STRUCTURED_BUFFER: + case DescriptorType::STORAGE_STRUCTURED_BUFFER: + argDescriptor.dataType = MTLDataTypeStruct; + break; + case DescriptorType::ACCELERATION_STRUCTURE: + argDescriptor.dataType = MTLDataTypePrimitiveAccelerationStructure; + break; + default: + break; + } + if(range->flags & DescriptorRangeBits::VARIABLE_SIZED_ARRAY) + m_HasVariableDescriptorNum[r] = true; + [argumentDescriptors addObject: argDescriptor]; + } + + m_DescriptorSetLayouts[i].m_ArgumentDescriptors = argumentDescriptors; + + } + + + for (uint32_t i = 0; i < pipelineLayoutDesc.rootConstantNum; i++) { + const RootConstantDesc& pushConstantDesc = pipelineLayoutDesc.rootConstants[i]; + m_PushBindingConstants[i] = pushConstantDesc; + } + + return Result::SUCCESS; +} + diff --git a/Source/Metal/PipelineMTL.h b/Source/Metal/PipelineMTL.h new file mode 100644 index 00000000..633401ad --- /dev/null +++ b/Source/Metal/PipelineMTL.h @@ -0,0 +1,57 @@ +#pragma once + +#import + +#include "SharedMTL.h" + +namespace nri { + +struct DeviceMTL; +struct PipelineLayoutMTL; + +struct PipelineMTL { +public: + inline PipelineMTL(DeviceMTL& device) + : m_Device(device) { + } + ~PipelineMTL(); + + Result Create(const GraphicsPipelineDesc& graphicsPipelineDesc); + Result Create(const ComputePipelineDesc& computePipelineDesc); + Result Create(const RayTracingPipelineDesc& rayTracingPipelineDesc); + + inline MTLPrimitiveType GetPrimitiveType() const { + return m_primitiveType; + } + + inline PipelineType GetPipelineType() const { + return m_PipelineType; + } + + inline id GetComputePipeline() const { + return m_ComputePipeline; + } + + + inline id GetGraphicsPipeline() const { + return m_GraphicsPipeline; + } + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + +private: + PipelineType m_PipelineType; + MTLPrimitiveTopologyClass m_topologyClass; + MTLPrimitiveType m_primitiveType; + StageBits m_usedBits; + union{ + id m_ComputePipeline = nil; + id m_GraphicsPipeline; + }; + DeviceMTL& m_Device; +}; + +} + diff --git a/Source/Metal/PipelineMTL.mm b/Source/Metal/PipelineMTL.mm new file mode 100644 index 00000000..0bf08a71 --- /dev/null +++ b/Source/Metal/PipelineMTL.mm @@ -0,0 +1,167 @@ +#include "SharedMTL.h" + +#include "PipelineMTL.h" +#include "PipelineLayoutMTL.h" + +using namespace nri; + +PipelineMTL::~PipelineMTL() { + switch(m_PipelineType) { + case PipelineType::Graphics: + m_GraphicsPipeline = nil; + break; + case PipelineType::Compute: + m_ComputePipeline = nil; + break; + case PipelineType::Raytracing: + break; + default: + break; + } + +} + +Result PipelineMTL::Create(const ComputePipelineDesc& computePipelineDesc) { + MTLComputePipelineDescriptor* pipelineDesc = [[MTLComputePipelineDescriptor alloc] init]; + NSError* error = nil; + + dispatch_data_t byteCode = dispatch_data_create( + computePipelineDesc.shader.bytecode, + computePipelineDesc.shader.size, nil, DISPATCH_DATA_DESTRUCTOR_DEFAULT); + + id lib = [m_Device newLibraryWithData: byteCode error:&error]; + NSCAssert(lib, @"Failed to load Metal shader library %@", error); // not sure how to correctly report this + RETURN_ON_FAILURE(&m_Device, lib, Result::FAILURE, "Failed to Load Metal shader library"); + // Create a MTLFunction from the loaded MTLLibrary. + NSString *entryPointNStr = [lib functionNames][0]; + if (computePipelineDesc.shader.entryPointName) { + entryPointNStr = [[NSString alloc] initWithUTF8String:computePipelineDesc.shader.entryPointName]; + } + id entryPointFunc = [lib newFunctionWithName:entryPointNStr]; + + m_PipelineType = PipelineType::Compute; + pipelineDesc.computeFunction = entryPointFunc; + NSCAssert(pipelineDesc.computeFunction, @"Failed to create Metal kernel function %@: %@", entryPointNStr, error); + + m_ComputePipeline = [m_Device newComputePipelineStateWithDescriptor: pipelineDesc + options: MTLPipelineOptionNone + reflection: nil + error:&error]; + NSCAssert(m_ComputePipeline, @"Failed to create pipeline state: %@", error); + return Result::SUCCESS; +} + +Result PipelineMTL::Create(const RayTracingPipelineDesc& rayTracingPipelineDesc) { + return Result::SUCCESS; +} + +Result PipelineMTL::Create(const GraphicsPipelineDesc& graphicsPipelineDesc) { + MTLRenderPipelineDescriptor *renderPipelineDesc = [[MTLRenderPipelineDescriptor alloc] init]; + + //m_type = PipelineMTL::Graphics; + const InputAssemblyDesc& ia = graphicsPipelineDesc.inputAssembly; + switch (ia.topology) { + case Topology::POINT_LIST: + m_primitiveType = MTLPrimitiveType::MTLPrimitiveTypePoint; + break; + case Topology::LINE_LIST: + case Topology::LINE_STRIP: + case Topology::LINE_LIST_WITH_ADJACENCY: + case Topology::LINE_STRIP_WITH_ADJACENCY: + m_primitiveType = MTLPrimitiveType::MTLPrimitiveTypeLine; + break; + case Topology::TRIANGLE_LIST: + case Topology::TRIANGLE_STRIP: + case Topology::TRIANGLE_LIST_WITH_ADJACENCY: + case Topology::TRIANGLE_STRIP_WITH_ADJACENCY: + m_primitiveType = MTLPrimitiveType::MTLPrimitiveTypeTriangle; + break; + case Topology::PATCH_LIST: + default: + break; + } + + for (uint32_t i = 0; i < graphicsPipelineDesc.shaderNum; i++) { + const ShaderDesc& shader = graphicsPipelineDesc.shaders[i]; + m_usedBits |= shader.stage; + + dispatch_data_t byteCode = dispatch_data_create(shader.bytecode, shader.size, nil, DISPATCH_DATA_DESTRUCTOR_DEFAULT); + NSError *error; + id lib = [m_Device newLibraryWithData:byteCode error:&error]; + NSCAssert(lib, @"Failed to load Metal shader library %@", error); // not sure how to correctly report this + RETURN_ON_FAILURE(&m_Device, lib, Result::FAILURE, "Failed to Load Metal shader library"); + + // Create a MTLFunction from the loaded MTLLibrary. + NSString *entryPointNStr = [lib functionNames][0]; + if (shader.entryPointName) { + entryPointNStr = [[NSString alloc] initWithUTF8String:shader.entryPointName]; + } + id entryPointFunc = [lib newFunctionWithName:entryPointNStr]; + if(shader.stage & nri::StageBits::VERTEX_SHADER) { + renderPipelineDesc.vertexFunction = entryPointFunc; + } else if(shader.stage & nri::StageBits::FRAGMENT_SHADER) { + renderPipelineDesc.fragmentFunction = entryPointFunc; + } + } + // Depth-stencil + const DepthAttachmentDesc& da = graphicsPipelineDesc.outputMerger.depth; + const StencilAttachmentDesc& sa = graphicsPipelineDesc.outputMerger.stencil; + + const PipelineLayout *pl = graphicsPipelineDesc.pipelineLayout; + const VertexInputDesc *vi = graphicsPipelineDesc.vertexInput; + if (vi) { + MTLVertexDescriptor *vertexDescriptor = [MTLVertexDescriptor new]; + for(size_t attIdx = 0; attIdx < vi->attributeNum; attIdx++) { + const nri::VertexAttributeDesc* attrib = &vi->attributes[attIdx]; + vertexDescriptor.attributes[attrib->mtl.location].offset = attrib->offset; + vertexDescriptor.attributes[attrib->mtl.location].format = GetVertexFormatMTL(attrib->format); + vertexDescriptor.attributes[attrib->mtl.location].bufferIndex = attrib->streamIndex; + } + + for(size_t layoutIdx = 0; layoutIdx < vi->streamNum; layoutIdx++) { + const nri::VertexStreamDesc* stream = &vi->streams[layoutIdx]; + vertexDescriptor.layouts[stream->bindingSlot].stride = stream->stride; + vertexDescriptor.layouts[stream->bindingSlot].stepRate = static_cast(stream->stepRate); + } + renderPipelineDesc.vertexDescriptor = vertexDescriptor; + } + + renderPipelineDesc.inputPrimitiveTopology = GetTopologyMTL(ia.topology); + + if (graphicsPipelineDesc.multisample) { + // TODO: multisampling + // + } + + // renderPipelineDesc.rasterSampleCount = pCreateInfo->pMultisampleState->pSampleMask[0]; + + + // Blending + + // assign render target pixel format for all attachments + const OutputMergerDesc& om = graphicsPipelineDesc.outputMerger; + for (uint32_t i = 0; i < om.colorNum; i++) { + + const ColorAttachmentDesc& attachmentDesc = om.colors[i]; + renderPipelineDesc.colorAttachments[i].pixelFormat = GetFormatMTL(attachmentDesc.format, false); + + renderPipelineDesc.colorAttachments[i].blendingEnabled = attachmentDesc.blendEnabled; + renderPipelineDesc.colorAttachments[i].rgbBlendOperation = GetBlendOp(attachmentDesc.colorBlend.func); + renderPipelineDesc.colorAttachments[i].alphaBlendOperation = GetBlendOp(attachmentDesc.alphaBlend.func); + + renderPipelineDesc.colorAttachments[i].sourceRGBBlendFactor = GetBlendFactor(attachmentDesc.colorBlend.srcFactor); + renderPipelineDesc.colorAttachments[i].destinationRGBBlendFactor = GetBlendFactor(attachmentDesc.colorBlend.dstFactor); + renderPipelineDesc.colorAttachments[i].sourceAlphaBlendFactor = GetBlendFactor(attachmentDesc.alphaBlend.srcFactor); + renderPipelineDesc.colorAttachments[i].destinationAlphaBlendFactor = GetBlendFactor(attachmentDesc.alphaBlend.dstFactor); + + renderPipelineDesc.colorAttachments[i].writeMask = GetColorComponent(attachmentDesc.colorWriteMask); + + } + NSError* error = nil; + m_GraphicsPipeline = [m_Device newRenderPipelineStateWithDescriptor:renderPipelineDesc error: &error]; + NSCAssert(m_GraphicsPipeline, @"Failed to create pipeline state: %@", error); + + + return Result::SUCCESS; + +} diff --git a/Source/Metal/QueryMTL.h b/Source/Metal/QueryMTL.h new file mode 100644 index 00000000..e69de29b diff --git a/Source/Metal/QueryMTL.mm b/Source/Metal/QueryMTL.mm new file mode 100644 index 00000000..e69de29b diff --git a/Source/Metal/SharedMTL.h b/Source/Metal/SharedMTL.h new file mode 100644 index 00000000..770f7870 --- /dev/null +++ b/Source/Metal/SharedMTL.h @@ -0,0 +1,41 @@ +#import + +#include "SharedExternal.h" + +#include "ConversionMTL.h" +#include "DeviceMTL.h" + +#pragma once + +NriEnum(PipelineType, uint8_t, + Compute, + Graphics, + Raytracing +); + +NriBits(BarrierBits, uint8_t, + NONE = 0, + BARRIER_FLAG_BUFFERS = NriBit(0), + BARRIER_FLAG_TEXTURES = NriBit(1), + BARRIER_FLAG_RENDERTARGETS = NriBit(2), + BARRIER_FLAG_FENCE = NriBit(3)); + + +NriBits(CommandBufferDirtyBits, uint8_t, + NONE = 0, + CMD_DIRTY_STENCIL = NriBit(0), + CMD_DIRTY_SHADING_RATE = NriBit(1), + CMD_DIRTY_BLEND_CONSTANT = NriBit(2) + ); + + +struct MemoryTypeInfo { + union { + uint32_t value; + struct { + uint32_t options: 16; // MTLResourceOptions + uint32_t storageMode: 4; // MTLStorageMode + uint32_t cacheMode: 2; // MTLCPUCacheMode + }; + }; +}; diff --git a/Source/Metal/SwapChainMTL.h b/Source/Metal/SwapChainMTL.h new file mode 100644 index 00000000..fb4a92d8 --- /dev/null +++ b/Source/Metal/SwapChainMTL.h @@ -0,0 +1,46 @@ +#pragma once + +namespace nri { + +struct TextureMTL; +struct CommandQueueMTL; + +// Let's keep things simple and hide it under the hood +constexpr uint32_t MAX_NUMBER_OF_FRAMES_IN_FLIGHT = 8; + +struct SwapChainMTL: public DisplayDescHelper { + SwapChainMTL(DeviceMTL& device) + : m_Device(device), + m_Textures(device.GetStdAllocator()) { + + } + ~SwapChainMTL(); + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + + void SetDebugName(const char* name); + Texture* const* GetTextures(uint32_t& textureNum) const; + uint32_t AcquireNextTexture(); + Result WaitForPresent(); + Result Present(); + + Result Create(const SwapChainDesc& swapChainDesc); + +private: + CAMetalLayer* m_MetalLayer; + Vector m_Textures; + + id m_MTKDrawable; + id m_PresentCommandBuffer; + CommandQueueMTL* m_CommandQueue = nullptr; + + DeviceMTL& m_Device; + uint64_t m_PresentId = 0; + uint32_t m_TextureIndex = 0; + uint8_t m_FrameIndex = 0; // in flight, not global +}; + +}; diff --git a/Source/Metal/SwapChainMTL.mm b/Source/Metal/SwapChainMTL.mm new file mode 100644 index 00000000..832d8e3f --- /dev/null +++ b/Source/Metal/SwapChainMTL.mm @@ -0,0 +1,64 @@ +#include "SharedMTL.h" + +#include "SwapChainMTL.h" +#include "TextureMTL.h" +#include "CommandQueueMTL.h" + +using namespace nri; + + +SwapChainMTL::~SwapChainMTL() { + +} + +void SwapChainMTL::SetDebugName(const char* name) { + +} + +Texture* const* SwapChainMTL::GetTextures(uint32_t& textureNum) const { + return NULL; +} + +uint32_t SwapChainMTL::AcquireNextTexture() { + m_MTKDrawable = [m_MetalLayer nextDrawable]; + m_FrameIndex = (m_FrameIndex + 1) % m_Textures.size(); + m_Textures[m_FrameIndex]->Create(m_MTKDrawable.texture); + return m_FrameIndex; +} +Result SwapChainMTL::WaitForPresent() { + return Result::SUCCESS; +} +Result SwapChainMTL::Present() { + + // after committing a command buffer no more commands can be encoded on it: create a new command buffer for future commands + m_PresentCommandBuffer = [m_CommandQueue->GetHandle() commandBuffer]; + m_PresentCommandBuffer.label = @"PRESENT"; + + [m_PresentCommandBuffer presentDrawable: m_MTKDrawable]; + m_MTKDrawable = nil; + + [m_PresentCommandBuffer commit]; + m_PresentCommandBuffer = nil; + + return Result::SUCCESS; +} + +Result SwapChainMTL::Create(const SwapChainDesc& swapChainDesc) { + m_MetalLayer = (CAMetalLayer*)swapChainDesc.window.metal.caMetalLayer; + m_CommandQueue = (CommandQueueMTL*)swapChainDesc.commandQueue; + m_PresentCommandBuffer = [m_CommandQueue->GetHandle() commandBuffer]; + +// m_Textures.resize(swapChainDesc.textureNum); + for(uint32_t i = 0; i < swapChainDesc.textureNum; i++) { + TextureDesc desc = {}; + desc.width = swapChainDesc.width; + desc.height = swapChainDesc.height; + desc.depth = 1; + desc.mipNum = 1; + desc.layerNum = 1; + desc.sampleNum = 1; + + TextureMTL* texture = Allocate(m_Device.GetStdAllocator(), m_Device); + texture->Create(desc); + } +} diff --git a/Source/Metal/TextureMTL.h b/Source/Metal/TextureMTL.h new file mode 100644 index 00000000..b53193bc --- /dev/null +++ b/Source/Metal/TextureMTL.h @@ -0,0 +1,58 @@ +// © 2021 NVIDIA Corporation +#pragma once + +#import + +namespace nri { + +struct DeviceMTL; + +class MemoryMTL; + +void fillMTLTextureDescriptor(const TextureDesc& textureDesc, MTLTextureDescriptor* mtlDescriptor); + +struct TextureMTL { +public: + inline TextureMTL(DeviceMTL& device) + : m_Device(device) { + } + ~TextureMTL(); + + inline id GetHandle() const { + return m_Handle; + } + + inline DeviceMTL& GetDevice() const { + return m_Device; + } + + inline const TextureDesc& GetDesc() const { + return m_Desc; + } + + Result Create(const TextureDesc& textureDesc); + Result Create(MTLTextureHandle textureDesc); + Result Create(const AllocateTextureDesc& textureDesc); + void FinishMemoryBinding(MemoryMTL& memory, uint64_t memoryOffset); + + inline Dim_t GetSize(Dim_t dimensionIndex, Mip_t mip = 0) const { + return GetDimension(GraphicsAPI::MTL, m_Desc, dimensionIndex, mip); + } + + //================================================================================================================ + // NRI + //================================================================================================================ + + void SetDebugName(const char* name); + +private: + + void UpdateLabel(); + NSString* m_Label = nullptr; + DeviceMTL& m_Device; + TextureDesc m_Desc = {}; + id m_Handle; + NSString* m_label = nil; +}; + +} // namespace nri diff --git a/Source/Metal/TextureMTL.mm b/Source/Metal/TextureMTL.mm new file mode 100644 index 00000000..d07bb5c4 --- /dev/null +++ b/Source/Metal/TextureMTL.mm @@ -0,0 +1,69 @@ +#include "SharedMTL.h" + +#include "TextureMTL.h" +#include "MemoryMTL.h" + +using namespace nri; + +TextureMTL::~TextureMTL() { + m_Handle = nil; +} + +void nri::fillMTLTextureDescriptor(const TextureDesc& textureDesc, MTLTextureDescriptor* info) { + info.textureType = ::GetImageTypeMTL(textureDesc.type); + info.pixelFormat = ::GetFormatMTL(textureDesc.format, true); + info.width = textureDesc.width; + info.height = textureDesc.height; + info.depth = textureDesc.depth; + info.mipmapLevelCount = textureDesc.mipNum; + info.sampleCount = textureDesc.sampleNum; + info.arrayLength = textureDesc.layerNum; +} + +Result TextureMTL::Create(const TextureDesc& textureDesc) { + m_Desc = textureDesc; + return Result::SUCCESS; +} + + +Result TextureMTL::Create(MTLTextureHandle texture) { + m_Handle = (id)texture; + m_Desc.width = m_Handle.width; + m_Desc.height = m_Handle.height; + m_Desc.depth = m_Handle.depth; + m_Desc.mipNum = m_Handle.mipmapLevelCount; + m_Desc.layerNum = m_Handle.arrayLength; + m_Desc.sampleNum = m_Handle.sampleCount; + m_Desc.type = GetTextureType(m_Handle.textureType); + m_Desc.format = MTLFormatToNRIFormat((uint32_t)m_Handle.pixelFormat); + return Result::SUCCESS; +} + + +Result TextureMTL::Create(const AllocateTextureDesc& textureDesc) { + m_Desc = textureDesc.desc; + MTLTextureDescriptor* info = [[MTLTextureDescriptor alloc] init]; + fillMTLTextureDescriptor(m_Desc, info); + m_Handle = [m_Device.GetHandle() newTextureWithDescriptor: info]; + UpdateLabel(); + return Result::SUCCESS; +} + + +void TextureMTL::FinishMemoryBinding(MemoryMTL& memory, uint64_t memoryOffset) { + MTLTextureDescriptor* info = [[MTLTextureDescriptor alloc] init]; + fillMTLTextureDescriptor(m_Desc, info); + m_Handle = [memory.GetHandle() newTextureWithDescriptor:info offset:memoryOffset]; + UpdateLabel(); +} + +void TextureMTL::UpdateLabel() { + if(m_Handle && m_Label) { + [m_Handle setLabel: m_Label]; + } +} + +void TextureMTL::SetDebugName(const char* name) { + m_label = [NSString stringWithUTF8String:name]; + UpdateLabel(); +} diff --git a/Source/Shared/SharedExternal.h b/Source/Shared/SharedExternal.h index 1e432a86..7c1197ec 100644 --- a/Source/Shared/SharedExternal.h +++ b/Source/Shared/SharedExternal.h @@ -1,4 +1,4 @@ -// © 2021 NVIDIA Corporation +// © 2021 NVIDIA Corporation #pragma once @@ -29,6 +29,7 @@ typedef uint32_t DXGI_FORMAT; #include "Extensions/NRIWrapperD3D11.h" #include "Extensions/NRIWrapperD3D12.h" #include "Extensions/NRIWrapperVK.h" +#include "Extensions/NRIWrapperMTL.h" #include "NRICompatibility.hlsli" @@ -166,9 +167,11 @@ const nri::FormatProps& GetFormatProps(nri::Format format); nri::Format DXGIFormatToNRIFormat(uint32_t dxgiFormat); nri::Format VKFormatToNRIFormat(uint32_t vkFormat); +nri::Format MTLFormatToNRIFormat(uint32_t mtlFormat); uint32_t NRIFormatToDXGIFormat(nri::Format format); uint32_t NRIFormatToVKFormat(nri::Format format); +uint32_t NRIFormatToMTLFormat(nri::Format format); // Misc inline nri::Vendor GetVendorFromID(uint32_t vendorID) { @@ -179,6 +182,8 @@ inline nri::Vendor GetVendorFromID(uint32_t vendorID) { return nri::Vendor::AMD; case 0x8086: return nri::Vendor::INTEL; + case 0x106b: + return nri::Vendor::APPLE; } return nri::Vendor::UNKNOWN; diff --git a/Source/Shared/SharedExternal.hpp b/Source/Shared/SharedExternal.hpp index 7e67e771..8d45d51c 100644 --- a/Source/Shared/SharedExternal.hpp +++ b/Source/Shared/SharedExternal.hpp @@ -792,6 +792,115 @@ nri::Format VKFormatToNRIFormat(uint32_t format) { return nri::Format::UNKNOWN; } + +nri::Format MTLFormatToNRIFormat(uint32_t format) { + switch (format) { + case 0: return nri::Format::UNKNOWN; // MTLPixelFormatInvalid = 0 + case 1: return nri::Format::UNKNOWN; // MTLPixelFormatA8Unorm = 1 + + case 10: return nri::Format::R8_UNORM; // MTLPixelFormatR8Unorm = 10, + case 11: return nri::Format::UNKNOWN; // MTLPixelFormatR8Unorm_sRGB = 11, + case 12: return nri::Format::R8_SNORM; // MTLPixelFormatR8Snorm = 12, + case 13: return nri::Format::R8_UINT; // MTLPixelFormatR8Uint = 13, + case 14: return nri::Format::R8_SINT; // MTLPixelFormatR8Sint = 14, + + case 20: return nri::Format::R16_UNORM; // MTLPixelFormatR16Unorm = 20, + + case 22: return nri::Format::R16_SNORM;// MTLPixelFormatR16Snorm = 22 + case 23: return nri::Format::R16_UINT; // MTLPixelFormatR16Uint = 23 + case 24: return nri::Format::R16_SINT; // MTLPixelFormatR16Sint = 24 + case 25: return nri::Format::R16_SFLOAT; //MTLPixelFormatR16Float = 25 + + + case 30: return nri::Format::RG8_UNORM;// MTLPixelFormatRG8Unorm = 30, + case 31: return nri::Format::UNKNOWN; // MTLPixelFormatRG8Unorm_sRGB = 31, + case 32: return nri::Format::RG8_SNORM;// MTLPixelFormatRG8Snorm = 32, + case 33: return nri::Format::RG8_UINT; // MTLPixelFormatRG8Uint = 33, + case 34: return nri::Format::RG8_SINT; // MTLPixelFormatRG8Sint = 34, + + + case 40: return nri::Format::B5_G6_R5_UNORM; // MTLPixelFormatB5G6R5Unorm = 40, + case 41: return nri::Format::B5_G5_R5_A1_UNORM; // MTLPixelFormatA1BGR5Unorm = 41, + case 42: return nri::Format::UNKNOWN; // MTLPixelFormatABGR4Unorm = 42, + case 43: return nri::Format::B5_G5_R5_A1_UNORM; // MTLPixelFormatBGR5A1Unorm = 43, + + + case 53: return nri::Format::R32_UINT; // MTLPixelFormatR32Uint = 53, + case 54: return nri::Format::R32_SINT; // MTLPixelFormatR32Sint = 54, + case 55: return nri::Format::R32_SFLOAT;// MTLPixelFormatR32Float = 55, + + case 60: return nri::Format::RG16_UNORM; //MTLPixelFormatRG16Unorm = 60, + case 62: return nri::Format::RG16_SNORM; // MTLPixelFormatRG16Snorm = 62, + case 63: return nri::Format::RG16_UINT; // MTLPixelFormatRG16Uint = 63, + case 64: return nri::Format::RG16_SINT; // MTLPixelFormatRG16Sint = 64, + case 65: return nri::Format::RG16_SFLOAT; // MTLPixelFormatRG16Float = 65, + + case 70: return nri::Format::RGBA8_UNORM; // MTLPixelFormatRGBA8Unorm = 70, + case 71: return nri::Format::RGBA8_SRGB; // MTLPixelFormatRGBA8Unorm_sRGB = 71, + case 72: return nri::Format::RGBA8_SNORM; // MTLPixelFormatRGBA8Snorm = 72, + case 73: return nri::Format::RGBA8_UINT; // MTLPixelFormatRGBA8Uint = 73, + case 74: return nri::Format::RGBA8_SINT; // MTLPixelFormatRGBA8Sint = 74, + + case 80: return nri::Format::BGRA8_UNORM;// MTLPixelFormatBGRA8Unorm = 80, + case 81: return nri::Format::BGRA8_SRGB; // MTLPixelFormatBGRA8Unorm_sRGB = 81, + + case 90: return nri::Format::R10_G10_B10_A2_UNORM;// MTLPixelFormatRGB10A2Unorm = 90, + case 91: return nri::Format::R10_G10_B10_A2_UINT;// MTLPixelFormatRGB10A2Uint = 91, + + case 92: return nri::Format::R11_G11_B10_UFLOAT; // MTLPixelFormatRG11B10Float = 92, + case 93: return nri::Format::R9_G9_B9_E5_UFLOAT; // MTLPixelFormatRGB9E5Float = 93, + + case 94: return nri::Format::UNKNOWN; // MTLPixelFormatRGB9E5Float = 94 + case 554: return nri::Format::UNKNOWN; // MTLPixelFormatBGR10_XR = 544 + case 555: return nri::Format::UNKNOWN; // MTLPixelFormatBGR10_XR_sRGB = 555 + + case 103: return nri::Format::RG32_UINT; // MTLPixelFormatRG32Uint = 103, + case 104: return nri::Format::RG32_SINT;// MTLPixelFormatRG32Sint = 104, + + case 105: return nri::Format::RG32_SFLOAT; // MTLPixelFormatRG32Float = 105, + + case 110: return nri::Format::RGBA16_UNORM;// MTLPixelFormatRGBA16Unorm = 110, + case 112: return nri::Format::RGBA16_SNORM;// MTLPixelFormatRGBA16Snorm = 112, + case 113: return nri::Format::RGBA16_UINT;// MTLPixelFormatRGBA16Uint = 113, + case 114: return nri::Format::RGBA16_SINT;// MTLPixelFormatRGBA16Sint = 114, + case 115: return nri::Format::RGBA16_SFLOAT;// MTLPixelFormatRGBA16Float = 115, + + case 552: return nri::Format::UNKNOWN; // MTLPixelFormatBGRA10_XR = 552, + case 553: return nri::Format::UNKNOWN; // MTLPixelFormatBGRA10_XR_sRGB = 553, + + + case 123: return nri::Format::RGBA32_UINT; //MTLPixelFormatRGBA32Uint = 123, + case 124: return nri::Format::RGBA32_SINT; //MTLPixelFormatRGBA32Sint = 124, + case 125: return nri::Format::RGBA32_SFLOAT; //MTLPixelFormatRGBA32Float = 125, + + case 130: return nri::Format::BC1_RGBA_UNORM; // MTLPixelFormatBC1_RGBA = 130, + case 131: return nri::Format::BC1_RGBA_SRGB; // MTLPixelFormatBC1_RGBA_sRGB = 131, + case 132: return nri::Format::BC2_RGBA_UNORM; // MTLPixelFormatBC2_RGBA = 132, + case 133: return nri::Format::BC2_RGBA_SRGB; // MTLPixelFormatBC2_RGBA_sRGB = 133, + case 134: return nri::Format::BC3_RGBA_UNORM; //MTLPixelFormatBC3_RGBA = 134, + case 135: return nri::Format::BC3_RGBA_SRGB; // MTLPixelFormatBC3_RGB_sRGB =135, + + + case 140: return nri::Format::BC4_R_UNORM; // MTLPixelFormatBC4_RUnorm = 140, + case 141: return nri::Format::BC4_R_SNORM; // MTLPixelFormatBC4_RSnorm = 141, + case 142: return nri::Format::BC5_RG_UNORM;// MTLPixelFormatBC5_RGUnorm = 142, + case 143: return nri::Format::BC5_RG_SNORM;// MTLPixelFormatBC5_RGSnorm = 143, + + case 150: return nri::Format::BC6H_RGB_SFLOAT; // MTLPixelFormatBC6H_RGBFloat = 150, + case 151: return nri::Format::BC6H_RGB_UFLOAT; // MTLPixelFormatBC6H_RGBUfloat = 151, + case 152: return nri::Format::BC7_RGBA_UNORM; // MTLPixelFormatBC7_RGBAUnorm = 152, + case 153: return nri::Format::BC7_RGBA_SRGB; // MTLPixelFormatBC7_RGBAUnorm_sRGB = 153, + + + + case 255: return nri::Format::D24_UNORM_S8_UINT;// MTLPixelFormatDepth24Unorm_Stencil8 = 255, + case 262: return nri::Format::D32_SFLOAT_S8_UINT_X24;// MTLPixelFormatX24_Stencil8 = 262, + + + } + return nri::Format::UNKNOWN; +} + constexpr std::array MESSAGE_TYPE_NAME = { "INFO", // INFO, "WARNING", // WARNING,