From 730d15d8a779b6111a6abbed4de8357dd794a167 Mon Sep 17 00:00:00 2001 From: Krzysztof Bogacki Date: Sun, 21 May 2023 20:14:25 +0200 Subject: [PATCH] nvapi-d3d12: Use NvapiD3d12Device with its cache for OMM calls --- src/d3d12/nvapi_d3d12_device.cpp | 115 ++++++++++++++++++++++++++++-- src/d3d12/nvapi_d3d12_device.h | 19 ++++- src/nvapi_d3d12.cpp | 117 +++++++++++++------------------ 3 files changed, 175 insertions(+), 76 deletions(-) diff --git a/src/d3d12/nvapi_d3d12_device.cpp b/src/d3d12/nvapi_d3d12_device.cpp index b69fa982..19817c3e 100644 --- a/src/d3d12/nvapi_d3d12_device.cpp +++ b/src/d3d12/nvapi_d3d12_device.cpp @@ -128,6 +128,91 @@ namespace dxvk { return cubinDevice != nullptr; } + bool NvapiD3d12Device::AreOpacityMicromapsSupported(ID3D12Device* device) { + auto ommDevice = GetOmmDevice(device); + return ommDevice != nullptr; + } + + std::optional NvapiD3d12Device::SetCreatePipelineStateOptions(ID3D12Device5* device, const NVAPI_D3D12_SET_CREATE_PIPELINE_STATE_OPTIONS_PARAMS* params) { + auto ommDevice = GetOmmDevice(device); + if (ommDevice == nullptr) + return std::nullopt; + + return static_cast(ommDevice->SetCreatePipelineStateOptions(params)); + } + + std::optional NvapiD3d12Device::CheckDriverMatchingIdentifierEx(ID3D12Device5* device, NVAPI_CHECK_DRIVER_MATCHING_IDENTIFIER_EX_PARAMS* params) { + auto ommDevice = GetOmmDevice(device); + if (ommDevice == nullptr) + return std::nullopt; + + return static_cast(ommDevice->CheckDriverMatchingIdentifierEx(params)); + } + + std::optional NvapiD3d12Device::GetRaytracingAccelerationStructurePrebuildInfoEx(ID3D12Device5* device, NVAPI_GET_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO_EX_PARAMS* params) { + auto ommDevice = GetOmmDevice(device); + if (ommDevice == nullptr) + return std::nullopt; + + return static_cast(ommDevice->GetRaytracingAccelerationStructurePrebuildInfoEx(params)); + } + + std::optional NvapiD3d12Device::GetRaytracingOpacityMicromapArrayPrebuildInfo(ID3D12Device5* device, NVAPI_GET_RAYTRACING_OPACITY_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS* params) { + auto ommDevice = GetOmmDevice(device); + if (ommDevice == nullptr) + return std::nullopt; + + return static_cast(ommDevice->GetRaytracingOpacityMicromapArrayPrebuildInfo(params)); + } + + std::optional NvapiD3d12Device::BuildRaytracingAccelerationStructureEx(ID3D12GraphicsCommandList4* commandList, const NVAPI_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_EX_PARAMS* params) { + auto commandListExt = GetCommandListExt(commandList); + if (!commandListExt.has_value()) + return std::nullopt; + + auto commandListVer = commandListExt.value(); + if (commandListVer.InterfaceVersion < 2) + return std::nullopt; + + return static_cast(commandListVer.CommandListExt->BuildRaytracingAccelerationStructureEx(params)); + } + + std::optional NvapiD3d12Device::BuildRaytracingOpacityMicromapArray(ID3D12GraphicsCommandList4* commandList, NVAPI_BUILD_RAYTRACING_OPACITY_MICROMAP_ARRAY_PARAMS* params) { + auto commandListExt = GetCommandListExt(commandList); + if (!commandListExt.has_value()) + return std::nullopt; + + auto commandListVer = commandListExt.value(); + if (commandListVer.InterfaceVersion < 2) + return std::nullopt; + + return static_cast(commandListVer.CommandListExt->BuildRaytracingOpacityMicromapArray(params)); + } + + std::optional NvapiD3d12Device::RelocateRaytracingOpacityMicromapArray(ID3D12GraphicsCommandList4* commandList, const NVAPI_RELOCATE_RAYTRACING_OPACITY_MICROMAP_ARRAY_PARAMS* params) { + auto commandListExt = GetCommandListExt(commandList); + if (!commandListExt.has_value()) + return std::nullopt; + + auto commandListVer = commandListExt.value(); + if (commandListVer.InterfaceVersion < 2) + return std::nullopt; + + return static_cast(commandListVer.CommandListExt->RelocateRaytracingOpacityMicromapArray(params)); + } + + std::optional NvapiD3d12Device::EmitRaytracingOpacityMicromapArrayPostbuildInfo(ID3D12GraphicsCommandList4* commandList, const NVAPI_EMIT_RAYTRACING_OPACITY_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS* params) { + auto commandListExt = GetCommandListExt(commandList); + if (!commandListExt.has_value()) + return std::nullopt; + + auto commandListVer = commandListExt.value(); + if (commandListVer.InterfaceVersion < 2) + return std::nullopt; + + return static_cast(commandListVer.CommandListExt->EmitRaytracingOpacityMicromapArrayPostbuildInfo(params)); + } + // We are going to have single map for storing devices with extensions D3D12_VK_NVX_BINARY_IMPORT & D3D12_VK_NVX_IMAGE_VIEW_HANDLE. // These are specific to NVIDIA and both of these extensions goes together. Com NvapiD3d12Device::GetCubinDevice(ID3D12Device* device) { @@ -136,15 +221,29 @@ namespace dxvk { if (it != m_cubinDeviceMap.end()) return it->second; - auto cubinDevice = GetDeviceExt(device, D3D12_VK_NVX_BINARY_IMPORT); + auto cubinDevice = GetDeviceExt(device, D3D12_VK_NVX_BINARY_IMPORT); if (cubinDevice != nullptr) m_cubinDeviceMap.emplace(device, cubinDevice.ptr()); return cubinDevice; } - Com NvapiD3d12Device::GetDeviceExt(ID3D12Device* device, D3D12_VK_EXTENSION extension) { - Com deviceExt; + Com NvapiD3d12Device::GetOmmDevice(ID3D12Device* device) { + std::scoped_lock lock(m_ommDeviceMutex); + auto it = m_ommDeviceMap.find(device); + if (it != m_ommDeviceMap.end()) + return it->second; + + auto ommDevice = GetDeviceExt(device, D3D12_VK_EXT_OPACITY_MICROMAP); + if (ommDevice != nullptr) + m_ommDeviceMap.emplace(device, ommDevice.ptr()); + + return ommDevice; + } + + template + Com NvapiD3d12Device::GetDeviceExt(ID3D12Device* device, D3D12_VK_EXTENSION extension) { + Com deviceExt; if (FAILED(device->QueryInterface(IID_PPV_ARGS(&deviceExt)))) return nullptr; @@ -176,15 +275,21 @@ namespace dxvk { if (it != m_commandListMap.end()) return it->second; + Com commandListExt2 = nullptr; + if (SUCCEEDED(commandList->QueryInterface(IID_PPV_ARGS(&commandListExt2)))) { + NvapiD3d12Device::CommandListExtWithVersion cmdListVer{commandListExt2.ptr(), 2}; + return std::make_optional(m_commandListMap.emplace(commandList, cmdListVer).first->second); + } + Com commandListExt1 = nullptr; if (SUCCEEDED(commandList->QueryInterface(IID_PPV_ARGS(&commandListExt1)))) { - NvapiD3d12Device::CommandListExtWithVersion cmdListVer{commandListExt1.ptr(), 1}; + NvapiD3d12Device::CommandListExtWithVersion cmdListVer{reinterpret_cast(commandListExt1.ptr()), 1}; return std::make_optional(m_commandListMap.emplace(commandList, cmdListVer).first->second); } Com commandListExt = nullptr; if (SUCCEEDED(commandList->QueryInterface(IID_PPV_ARGS(&commandListExt)))) { - NvapiD3d12Device::CommandListExtWithVersion cmdListVer{reinterpret_cast(commandListExt.ptr()), 0}; + NvapiD3d12Device::CommandListExtWithVersion cmdListVer{reinterpret_cast(commandListExt.ptr()), 0}; return std::make_optional(m_commandListMap.emplace(commandList, cmdListVer).first->second); } diff --git a/src/d3d12/nvapi_d3d12_device.h b/src/d3d12/nvapi_d3d12_device.h index 386de906..38f725f7 100644 --- a/src/d3d12/nvapi_d3d12_device.h +++ b/src/d3d12/nvapi_d3d12_device.h @@ -9,7 +9,7 @@ namespace dxvk { class NvapiD3d12Device { struct CommandListExtWithVersion { - ID3D12GraphicsCommandListExt1* CommandListExt; + ID3D12GraphicsCommandListExt2* CommandListExt; uint32_t InterfaceVersion; }; @@ -29,9 +29,20 @@ namespace dxvk { static bool CaptureUAVInfo(ID3D12Device* device, NVAPI_UAV_INFO* uavInfo); static bool IsFatbinPTXSupported(ID3D12Device* device); + static bool AreOpacityMicromapsSupported(ID3D12Device* device); + static std::optional SetCreatePipelineStateOptions(ID3D12Device5* device, const NVAPI_D3D12_SET_CREATE_PIPELINE_STATE_OPTIONS_PARAMS* params); + static std::optional CheckDriverMatchingIdentifierEx(ID3D12Device5* device, NVAPI_CHECK_DRIVER_MATCHING_IDENTIFIER_EX_PARAMS* params); + static std::optional GetRaytracingAccelerationStructurePrebuildInfoEx(ID3D12Device5* device, NVAPI_GET_RAYTRACING_ACCELERATION_STRUCTURE_PREBUILD_INFO_EX_PARAMS* params); + static std::optional GetRaytracingOpacityMicromapArrayPrebuildInfo(ID3D12Device5* device, NVAPI_GET_RAYTRACING_OPACITY_MICROMAP_ARRAY_PREBUILD_INFO_PARAMS* params); + static std::optional BuildRaytracingAccelerationStructureEx(ID3D12GraphicsCommandList4* commandList, const NVAPI_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_EX_PARAMS* params); + static std::optional BuildRaytracingOpacityMicromapArray(ID3D12GraphicsCommandList4* commandList, NVAPI_BUILD_RAYTRACING_OPACITY_MICROMAP_ARRAY_PARAMS* params); + static std::optional RelocateRaytracingOpacityMicromapArray(ID3D12GraphicsCommandList4* commandList, const NVAPI_RELOCATE_RAYTRACING_OPACITY_MICROMAP_ARRAY_PARAMS* params); + static std::optional EmitRaytracingOpacityMicromapArrayPostbuildInfo(ID3D12GraphicsCommandList4* commandList, const NVAPI_EMIT_RAYTRACING_OPACITY_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS* params); + static void ClearCacheMaps(); private: + inline static std::unordered_map m_ommDeviceMap; inline static std::unordered_map m_cubinDeviceMap; inline static std::unordered_map m_commandQueueMap; inline static std::unordered_map m_commandListMap; @@ -39,12 +50,16 @@ namespace dxvk { inline static std::mutex m_commandListMutex; inline static std::mutex m_commandQueueMutex; + inline static std::mutex m_ommDeviceMutex; inline static std::mutex m_cubinDeviceMutex; inline static std::mutex m_cubinSmemMutex; + [[nodiscard]] static Com GetOmmDevice(ID3D12Device* device); [[nodiscard]] static Com GetCubinDevice(ID3D12Device* device); - [[nodiscard]] static Com GetDeviceExt(ID3D12Device* device, D3D12_VK_EXTENSION extension); [[nodiscard]] static Com GetCommandQueueExt(ID3D12CommandQueue* commandQueue); [[nodiscard]] static std::optional GetCommandListExt(ID3D12GraphicsCommandList* commandList); + + template + [[nodiscard]] static Com GetDeviceExt(ID3D12Device* device, D3D12_VK_EXTENSION extension); }; } diff --git a/src/nvapi_d3d12.cpp b/src/nvapi_d3d12.cpp index cb3f936b..cffb2793 100644 --- a/src/nvapi_d3d12.cpp +++ b/src/nvapi_d3d12.cpp @@ -275,14 +275,9 @@ extern "C" { if (dataSize != sizeof(NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAPS)) return InvalidArgument(n); - auto ommCaps = reinterpret_cast(pData); - // even though we can check extension support with DeviceExt(0) interface, DeviceExt1 is needed for actual OMM functions - Com deviceExt; - - if (!FAILED(pDevice->QueryInterface(IID_PPV_ARGS(&deviceExt))) && deviceExt->GetExtensionSupport(D3D12_VK_EXT_OPACITY_MICROMAP)) - *ommCaps = NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAP_STANDARD; - else - *ommCaps = NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAP_NONE; + *(NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAPS*)pData = NvapiD3d12Device::AreOpacityMicromapsSupported(pDevice) + ? NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAP_STANDARD + : NVAPI_D3D12_RAYTRACING_OPACITY_MICROMAP_CAP_NONE; break; } @@ -308,19 +303,17 @@ extern "C" { if (pDevice == nullptr || pParams == nullptr) return InvalidArgument(n); - Com pDeviceExt; - if (!FAILED(pDevice->QueryInterface(IID_PPV_ARGS(&pDeviceExt)))) { - auto result = static_cast(pDeviceExt->GetRaytracingOpacityMicromapArrayPrebuildInfo(pParams)); - - if (result == NVAPI_OK) { + if (auto result = NvapiD3d12Device::GetRaytracingOpacityMicromapArrayPrebuildInfo(pDevice, pParams); result.has_value()) { + auto value = result.value(); + if (value == NVAPI_OK) { return Ok(n, alreadyLoggedOk); } else { - log::write(str::format(n, ": ", result)); - return result; + log::write(str::format(n, ": ", value)); + return value; } } - return NoImplementation(n); + return NotSupported(n); } NvAPI_Status __cdecl NvAPI_D3D12_SetCreatePipelineStateOptions(ID3D12Device5* pDevice, const NVAPI_D3D12_SET_CREATE_PIPELINE_STATE_OPTIONS_PARAMS* pState) { @@ -333,19 +326,17 @@ extern "C" { if (pState->version != NVAPI_D3D12_SET_CREATE_PIPELINE_STATE_OPTIONS_PARAMS_VER1) return IncompatibleStructVersion(n); - Com pDeviceExt; - if (!FAILED(pDevice->QueryInterface(IID_PPV_ARGS(&pDeviceExt)))) { - auto result = static_cast(pDeviceExt->SetCreatePipelineStateOptions(pState)); - - if (result == NVAPI_OK) { + if (auto result = NvapiD3d12Device::SetCreatePipelineStateOptions(pDevice, pState); result.has_value()) { + auto value = result.value(); + if (value == NVAPI_OK) { return Ok(str::format(n, "(", pState->flags, ")"), alreadyLoggedOk); } else { - log::write(str::format(n, "(", pState->flags, "): ", result)); - return result; + log::write(str::format(n, "(", pState->flags, "): ", value)); + return value; } } - return NoImplementation(n); + return NotSupported(str::format(n, "(", pState->flags, ")")); } NvAPI_Status __cdecl NvAPI_D3D12_CheckDriverMatchingIdentifierEx(ID3D12Device5* pDevice, NVAPI_CHECK_DRIVER_MATCHING_IDENTIFIER_EX_PARAMS* pParams) { @@ -355,15 +346,13 @@ extern "C" { if (pDevice == nullptr || pParams == nullptr) return InvalidArgument(n); - Com pDeviceExt; - if (!FAILED(pDevice->QueryInterface(IID_PPV_ARGS(&pDeviceExt)))) { - auto result = static_cast(pDeviceExt->CheckDriverMatchingIdentifierEx(pParams)); - - if (result == NVAPI_OK) { + if (auto result = NvapiD3d12Device::CheckDriverMatchingIdentifierEx(pDevice, pParams); result.has_value()) { + auto value = result.value(); + if (value == NVAPI_OK) { return Ok(n, alreadyLoggedOk); } else { - log::write(str::format(n, ": ", result)); - return result; + log::write(str::format(n, ": ", value)); + return value; } } @@ -451,15 +440,13 @@ extern "C" { if (pDevice == nullptr || pParams == nullptr) return InvalidArgument(n); - Com pDeviceExt; - if (!FAILED(pDevice->QueryInterface(IID_PPV_ARGS(&pDeviceExt)))) { - auto result = static_cast(pDeviceExt->GetRaytracingAccelerationStructurePrebuildInfoEx(pParams)); - - if (result == NVAPI_OK) { + if (auto result = NvapiD3d12Device::GetRaytracingAccelerationStructurePrebuildInfoEx(pDevice, pParams); result.has_value()) { + auto value = result.value(); + if (value == NVAPI_OK) { return Ok(n, alreadyLoggedOk); } else { - log::write(str::format(n, ": ", result)); - return result; + log::write(str::format(n, ": ", value)); + return value; } } @@ -487,19 +474,17 @@ extern "C" { if (pCommandList == nullptr || pParams == nullptr) return InvalidArgument(n); - Com pCommandListExt; - if (!FAILED(pCommandList->QueryInterface(IID_PPV_ARGS(&pCommandListExt)))) { - auto result = static_cast(pCommandListExt->BuildRaytracingOpacityMicromapArray(pParams)); - - if (result == NVAPI_OK) { + if (auto result = NvapiD3d12Device::BuildRaytracingOpacityMicromapArray(pCommandList, pParams); result.has_value()) { + auto value = result.value(); + if (value == NVAPI_OK) { return Ok(n, alreadyLoggedOk); } else { - log::write(str::format(n, ": ", result)); - return result; + log::write(str::format(n, ": ", value)); + return value; } } - return NoImplementation(n); + return NotSupported(n); } NvAPI_Status __cdecl NvAPI_D3D12_RelocateRaytracingOpacityMicromapArray(ID3D12GraphicsCommandList4* pCommandList, const NVAPI_RELOCATE_RAYTRACING_OPACITY_MICROMAP_ARRAY_PARAMS* pParams) { @@ -509,19 +494,17 @@ extern "C" { if (pCommandList == nullptr || pParams == nullptr) return InvalidArgument(n); - Com pCommandListExt; - if (!FAILED(pCommandList->QueryInterface(IID_PPV_ARGS(&pCommandListExt)))) { - auto result = static_cast(pCommandListExt->RelocateRaytracingOpacityMicromapArray(pParams)); - - if (result == NVAPI_OK) { + if (auto result = NvapiD3d12Device::RelocateRaytracingOpacityMicromapArray(pCommandList, pParams); result.has_value()) { + auto value = result.value(); + if (value == NVAPI_OK) { return Ok(n, alreadyLoggedOk); } else { - log::write(str::format(n, ": ", result)); - return result; + log::write(str::format(n, ": ", value)); + return value; } } - return NoImplementation(n); + return NotSupported(n); } NvAPI_Status __cdecl NvAPI_D3D12_EmitRaytracingOpacityMicromapArrayPostbuildInfo(ID3D12GraphicsCommandList4* pCommandList, const NVAPI_EMIT_RAYTRACING_OPACITY_MICROMAP_ARRAY_POSTBUILD_INFO_PARAMS* pParams) { @@ -531,19 +514,17 @@ extern "C" { if (pCommandList == nullptr || pParams == nullptr) return InvalidArgument(n); - Com pCommandListExt; - if (!FAILED(pCommandList->QueryInterface(IID_PPV_ARGS(&pCommandListExt)))) { - auto result = static_cast(pCommandListExt->EmitRaytracingOpacityMicromapArrayPostbuildInfo(pParams)); - - if (result == NVAPI_OK) { + if (auto result = NvapiD3d12Device::EmitRaytracingOpacityMicromapArrayPostbuildInfo(pCommandList, pParams); result.has_value()) { + auto value = result.value(); + if (value == NVAPI_OK) { return Ok(n, alreadyLoggedOk); } else { - log::write(str::format(n, ": ", result)); - return result; + log::write(str::format(n, ": ", value)); + return value; } } - return NoImplementation(n); + return NotSupported(n); } NvAPI_Status __cdecl NvAPI_D3D12_BuildRaytracingAccelerationStructureEx(ID3D12GraphicsCommandList4* pCommandList, const NVAPI_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_EX_PARAMS* pParams) { @@ -553,15 +534,13 @@ extern "C" { if (pCommandList == nullptr || pParams == nullptr) return InvalidArgument(n); - Com pCommandListExt; - if (!FAILED(pCommandList->QueryInterface(IID_PPV_ARGS(&pCommandListExt)))) { - auto result = static_cast(pCommandListExt->BuildRaytracingAccelerationStructureEx(pParams)); - - if (result == NVAPI_OK) { + if (auto result = NvapiD3d12Device::BuildRaytracingAccelerationStructureEx(pCommandList, pParams); result.has_value()) { + auto value = result.value(); + if (value == NVAPI_OK) { return Ok(n, alreadyLoggedOk); } else { - log::write(str::format(n, ": ", result)); - return result; + log::write(str::format(n, ": ", value)); + return value; } }