diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ec0c254..801ba465 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ option (NRI_STATIC_LIBRARY "Build static library" OFF) # Options: backends 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) @@ -209,8 +210,19 @@ 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_include_directories (NRI_MTL PRIVATE "Include" "Source/Shared" "External") + target_compile_definitions (NRI_MTL PRIVATE ${COMPILE_DEFINITIONS}) +endif() + # VK -if (NRI_ENABLE_VK_SUPPORT) +if (NRI_ENABLE_VK_SUPPORT AND NOT APPLE) message ("NRI adding backend: VK") set (COMPILE_DEFINITIONS ${COMPILE_DEFINITIONS} NRI_USE_VULKAN=1) @@ -315,6 +327,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_NAME}) diff --git a/Include/.DS_Store b/Include/.DS_Store new file mode 100644 index 00000000..dbf90847 Binary files /dev/null and b/Include/.DS_Store differ diff --git a/Include/Extensions/NRIWrapperMTL.h b/Include/Extensions/NRIWrapperMTL.h new file mode 100644 index 00000000..6d62a9bf --- /dev/null +++ b/Include/Extensions/NRIWrapperMTL.h @@ -0,0 +1,24 @@ +// © 2021 NVIDIA Corporation + +#pragma once + +#include "NRIDeviceCreation.h" + +NRI_NAMESPACE_BEGIN + +NRI_STRUCT(DeviceCreationMTLDesc) +{ + bool enableNRIValidation; + id MtlDevice; +} + +NRI_STRUCT(CommandBufferMTLDesc) +{ + +} + + +NRI_API NRI_NAME(Result) NRI_CALL nriCreateDeviceFromMtlDevice(const NRI_NAME_REF(DeviceCreationMTLDesc) deviceDesc, NRI_NAME_REF(Device*) device); + +NRI_NAMESPACE_END + diff --git a/Include/NRIDescs.h b/Include/NRIDescs.h index 5eac31c6..08309171 100644 --- a/Include/NRIDescs.h +++ b/Include/NRIDescs.h @@ -1399,6 +1399,7 @@ NRI_ENUM D3D11, D3D12, VK, + MTL, MAX_NUM ); @@ -1411,6 +1412,7 @@ NRI_ENUM NVIDIA, AMD, INTEL, + APPLE, MAX_NUM ); diff --git a/Source/Creation/Creation.cpp b/Source/Creation/Creation.cpp index 680c88f6..a454c379 100644 --- a/Source/Creation/Creation.cpp +++ b/Source/Creation/Creation.cpp @@ -14,6 +14,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_VULKAN Result CreateDeviceVK(const DeviceCreationDesc& deviceCreationDesc, DeviceBase*& device); Result CreateDeviceVK(const DeviceCreationVKDesc& deviceDesc, DeviceBase*& device); @@ -188,6 +193,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; diff --git a/Source/Metal/BufferMetal.h b/Source/Metal/BufferMetal.h new file mode 100644 index 00000000..6c906e22 --- /dev/null +++ b/Source/Metal/BufferMetal.h @@ -0,0 +1,14 @@ + + +#import + +struct BufferMetal { + +private: + id pBuffer; + //id pIndirectCommandBuffer; + uint64_t mOffset; +}; + + + diff --git a/Source/Metal/BufferMetal.mm b/Source/Metal/BufferMetal.mm new file mode 100644 index 00000000..f01f9abf --- /dev/null +++ b/Source/Metal/BufferMetal.mm @@ -0,0 +1,2 @@ +#include "BufferMetal.h" + diff --git a/Source/Metal/DeviceMetal.h b/Source/Metal/DeviceMetal.h new file mode 100644 index 00000000..b51a1df5 --- /dev/null +++ b/Source/Metal/DeviceMetal.h @@ -0,0 +1,36 @@ +#pragma once + +namespace nri { + +struct DeviceMetal final : public DeviceBase { + BufferMetal(const CallbackInterface& callbacks, const StdAllocator& stdAllocator); + ~BufferMetal(); + + Result FillFunctionTable(CoreInterface& table) const; + Result FillFunctionTable(HelperInterface& table) const; + Result FillFunctionTable(LowLatencyInterface& table) const; + Result FillFunctionTable(MeshShaderInterface& table) const; + Result FillFunctionTable(RayTracingInterface& table) const; + Result FillFunctionTable(StreamerInterface& table) const; + Result FillFunctionTable(SwapChainInterface& table) const; + Result FillFunctionTable(ResourceAllocatorInterface& table) const; + Result FillFunctionTable(WrapperD3D11Interface& table) const; + Result FillFunctionTable(WrapperD3D12Interface& table) const; + Result FillFunctionTable(WrapperVKInterface& table) const; + + //================================================================================================================ + // DeviceBase + //================================================================================================================ + + inline const DeviceDesc& GetDesc() const { + return m_Desc; + } + + Result Create(const DeviceCreationDesc& deviceCreationDesc, const DeviceCreationMTLDesc& deviceCreationVKDesc, bool isWrapper); +private: + DeviceDesc m_Desc = {}; + id m_Device; + DeviceDesc m_Desc = {}; + bool m_OwnsNativeObjects = true; +}; +}; // namespace nri diff --git a/Source/Metal/DeviceMetal.hpp b/Source/Metal/DeviceMetal.hpp new file mode 100644 index 00000000..8a903496 --- /dev/null +++ b/Source/Metal/DeviceMetal.hpp @@ -0,0 +1,17 @@ +Declare_PartiallyFillFunctionTable_Functions(MTL); + +#pragma region[ Core ] + +static const DeviceDesc& NRI_CALL GetDeviceDesc(const Device& device) { + return ((const DeviceMetal&)device).GetDesc(); +} + +#pragma endregion + + +Define_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/DeviceMetal.mm b/Source/Metal/DeviceMetal.mm new file mode 100644 index 00000000..4e7c837d --- /dev/null +++ b/Source/Metal/DeviceMetal.mm @@ -0,0 +1,57 @@ +#include "DeviceMetal.h" + +using namespace nri; + +BufferMetal::BufferMetal(const CallbackInterface& callbacks, const StdAllocator& stdAllocator) + : DeviceBase(callbacks, stdAllocator) { + m_Desc.graphicsAPI = GraphicsAPI::VK; + m_Desc.nriVersionMajor = NRI_VERSION_MAJOR; + m_Desc.nriVersionMinor = NRI_VERSION_MINOR; + +} +BufferMetal::~BufferMetal() { + +} + +Result CreateDeviceMTL(const DeviceCreationDesc& deviceCreationDesc, DeviceBase*& device) { + +} + +Result CreateDeviceMTL(const DeviceCreationMTLDesc& deviceCreationDesc, DeviceBase*& device) { + +} + +Result DeviceMetal::Create(const DeviceCreationDesc& deviceCreationDesc, const DeviceCreationMTLDesc& deviceCreationMTLDesc, bool isWrapper) { + m_OwnsNativeObjects = !isWrapper; + + if(isWrapper) { + m_Device = deviceCreationMTLDesc.MtlDevice; + } + + 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; + } else { + const uint64_t regID = [m_Device registryID]; + if (regID) + { + io_registry_entry_t entry = IOServiceGetMatchingService(kIOMasterPortDefault, IORegistryEntryIDMatching(regID)); + if (entry) + { + // That returned the IOGraphicsAccelerator nub. Its parent, then, is the actual PCI device. + io_registry_entry_t parent; + if (IORegistryEntryGetParentEntry(entry, kIOServicePlane, &parent) == kIOReturnSuccess) + { + m_Desc.adapterDesc.vendor = GetVendorFromID(GetEntryProperty(parent, CFSTR("vendor-id"))); + m_Desc.adapterDesc.deviceId = GetEntryProperty(parent, CFSTR("device-id")); + IOObjectRelease(parent); + } + IOObjectRelease(entry); + } + } + } + + +} diff --git a/Source/Shared/SharedExternal.h b/Source/Shared/SharedExternal.h index c7a6fe40..4f2b5d3f 100644 --- a/Source/Shared/SharedExternal.h +++ b/Source/Shared/SharedExternal.h @@ -159,6 +159,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/VK/DeviceVK.cpp b/Source/VK/DeviceVK.cpp index c6829288..5c4187a3 100644 --- a/Source/VK/DeviceVK.cpp +++ b/Source/VK/DeviceVK.cpp @@ -11,7 +11,7 @@ #include "DescriptorSetVK.h" #include "DescriptorVK.h" #include "FenceVK.h" -#include "HelperDeviceMemoryAllocator.h" +#include "HelperDeviceMemoryAllocator.h"Device #include "MemoryVK.h" #include "PipelineLayoutVK.h" #include "PipelineVK.h" diff --git a/Source/VK/DeviceVK.h b/Source/VK/DeviceVK.h index 97c5ff3e..887f4aa3 100644 --- a/Source/VK/DeviceVK.h +++ b/Source/VK/DeviceVK.h @@ -2,6 +2,7 @@ #pragma once + namespace nri { struct CommandQueueVK; @@ -11,7 +12,7 @@ struct DeviceVK final : public DeviceBase { return m_Device; } - inline operator VkPhysicalDevice() const { + inline operator VkPhysicalDevice() const {DeviceB return m_PhysicalDevice; } diff --git a/Source/Validation/DeviceVal.cpp b/Source/Validation/DeviceVal.cpp index 68d547fa..729ea37a 100644 --- a/Source/Validation/DeviceVal.cpp +++ b/Source/Validation/DeviceVal.cpp @@ -887,6 +887,11 @@ Result DeviceVal::CreateAccelerationStructure(const AccelerationStructureVKDesc& #endif + +#if NRI_USE_METAL + +#endif + #if NRI_USE_D3D11 Result DeviceVal::CreateCommandBuffer(const CommandBufferD3D11Desc& commandBufferDesc, CommandBuffer*& commandBuffer) {