Skip to content

Commit

Permalink
nvapi-d3d12: Use Vulkan to read compute capability
Browse files Browse the repository at this point in the history
This works only for the proprietary driver but should be fine
since this is irrelevant on other drivers.
  • Loading branch information
jp7677 committed Jan 10, 2025
1 parent d719941 commit 7b6cf23
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 56 deletions.
10 changes: 10 additions & 0 deletions src/nvapi/nvapi_adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ namespace dxvk {
deviceProperties2.pNext = &m_vkComputeShaderDerivativesProperties;
}

if (IsVkDeviceExtensionSupported(VK_NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME)) {
m_vkCudaKernelLaunchProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_PROPERTIES_NV;
m_vkCudaKernelLaunchProperties.pNext = deviceProperties2.pNext;
deviceProperties2.pNext = &m_vkCudaKernelLaunchProperties;
}

m_vkIdProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
m_vkIdProperties.pNext = deviceProperties2.pNext;
deviceProperties2.pNext = &m_vkIdProperties;
Expand Down Expand Up @@ -287,6 +293,10 @@ namespace dxvk {
return NV_GPU_ARCHITECTURE_GK100;
}

std::pair<uint32_t, uint32_t> NvapiAdapter::GetComputeCapability() const {
return std::make_pair(m_vkCudaKernelLaunchProperties.computeCapabilityMajor, m_vkCudaKernelLaunchProperties.computeCapabilityMinor);
}

bool NvapiAdapter::IsVkDeviceExtensionSupported(const std::string& name) const {
return m_vkExtensions.find(name) != m_vkExtensions.end();
}
Expand Down
2 changes: 2 additions & 0 deletions src/nvapi/nvapi_adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace dxvk {
[[nodiscard]] uint32_t GetBoardId() const;
[[nodiscard]] std::optional<LUID> GetLuid() const;
[[nodiscard]] NV_GPU_ARCHITECTURE_ID GetArchitectureId() const;
[[nodiscard]] std::pair<uint32_t, uint32_t> GetComputeCapability() const;
[[nodiscard]] bool IsVkDeviceExtensionSupported(const std::string& name) const;
[[nodiscard]] const MemoryInfo& GetMemoryInfo() const;
[[nodiscard]] MemoryBudgetInfo GetCurrentMemoryBudgetInfo() const;
Expand Down Expand Up @@ -68,6 +69,7 @@ namespace dxvk {
VkPhysicalDeviceDriverPropertiesKHR m_vkDriverProperties{};
VkPhysicalDeviceFragmentShadingRatePropertiesKHR m_vkFragmentShadingRateProperties{};
VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR m_vkComputeShaderDerivativesProperties{};
VkPhysicalDeviceCudaKernelLaunchPropertiesNV m_vkCudaKernelLaunchProperties{};
uint32_t m_vkDriverVersion{};
uint32_t m_dxgiVendorId{};
uint32_t m_dxgiDeviceId{};
Expand Down
47 changes: 7 additions & 40 deletions src/nvapi_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,55 +202,22 @@ extern "C" {
if (luid.has_value())
adapter = nvapiAdapterRegistry->FindAdapter(luid.value());

if (adapter == nullptr || (!adapter->HasNvProprietaryDriver() && !adapter->HasNvkDriver()))
if (adapter == nullptr)
return Ok(str::format(n, " (sm_0)"));

// From https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ and https://en.wikipedia.org/wiki/CUDA#GPUs_supported
// Note: One might think that SM here is D3D12 Shader Model, in fact it is the "Streaming Multiprocessor" architecture version
auto computeCapability = adapter->GetComputeCapability();
pGraphicsCaps->majorSMVersion = computeCapability.first;
pGraphicsCaps->minorSMVersion = computeCapability.second;

// Might be related to VK_NV_scissor_exclusive (which isn't used by VKD3D-Proton), but unknown in the context of D3D12
// pGraphicsCaps->bExclusiveScissorRectsSupported = adapter->IsVkDeviceExtensionSupported(VK_NV_SCISSOR_EXCLUSIVE_EXTENSION_NAME);

// Note that adapter->IsVkDeviceExtensionSupported returns the extensions supported by DXVK, not by VKD3D-Proton,
// so we might be wrong here in case of an old VKD3D-Proton version or when VKD3D_DISABLE_EXTENSIONS is in use
pGraphicsCaps->bVariablePixelRateShadingSupported = adapter->IsVkDeviceExtensionSupported(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME);

// From https://arnon.dk/matching-sm-architectures-arch-and-gencode-for-various-nvidia-cards/ and https://en.wikipedia.org/wiki/CUDA#GPUs_supported
// Note: One might think that SM here is D3D12 Shader Model, in fact it is the "Streaming Multiprocessor" architecture name
switch (adapter->GetArchitectureId()) {
case NV_GPU_ARCHITECTURE_GB200:
pGraphicsCaps->majorSMVersion = 10;
pGraphicsCaps->minorSMVersion = 0; // Still unknown
break;
case NV_GPU_ARCHITECTURE_AD100:
pGraphicsCaps->majorSMVersion = 8;
pGraphicsCaps->minorSMVersion = 9;
break;
case NV_GPU_ARCHITECTURE_GA100:
pGraphicsCaps->majorSMVersion = 8;
pGraphicsCaps->minorSMVersion = 6; // Take the risk that no one uses an NVIDIA A100 with this implementation
break;
case NV_GPU_ARCHITECTURE_TU100:
pGraphicsCaps->majorSMVersion = 7;
pGraphicsCaps->minorSMVersion = 5;
break;
case NV_GPU_ARCHITECTURE_GV100:
pGraphicsCaps->majorSMVersion = 7;
pGraphicsCaps->minorSMVersion = 0;
break;
case NV_GPU_ARCHITECTURE_GP100:
pGraphicsCaps->majorSMVersion = 6;
pGraphicsCaps->minorSMVersion = 0;
break;
case NV_GPU_ARCHITECTURE_GM200:
pGraphicsCaps->majorSMVersion = 5;
pGraphicsCaps->minorSMVersion = 2;
break;
case NV_GPU_ARCHITECTURE_GM000:
pGraphicsCaps->majorSMVersion = 5;
pGraphicsCaps->minorSMVersion = 0;
break;
default:
break;
}

return Ok(str::format(n, " (sm_", pGraphicsCaps->majorSMVersion, pGraphicsCaps->minorSMVersion, ")"));
}

Expand Down
26 changes: 11 additions & 15 deletions tests/nvapi_d3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,17 +235,13 @@ TEST_CASE("D3D12 methods succeed", "[.d3d12]") {
bool variablePixelRateShadingSupported;
};
auto args = GENERATE(
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2600, {VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME}, 10, 0, true},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2600, {VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME}, 8, 9, true},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME}, 8, 6, true},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME}, 7, 5, false},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {VK_NVX_IMAGE_VIEW_HANDLE_EXTENSION_NAME}, 7, 0, false},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {VK_NV_CLIP_SPACE_W_SCALING_EXTENSION_NAME}, 6, 0, false},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {VK_NV_VIEWPORT_ARRAY2_EXTENSION_NAME}, 5, 2, false},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {VK_EXT_SHADER_IMAGE_ATOMIC_INT64_EXTENSION_NAME}, 5, 0, false},
Data{VK_DRIVER_ID_MESA_NVK, 0x2600, {VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME}, 8, 9, true},
Data{VK_DRIVER_ID_AMD_OPEN_SOURCE, 0x2000, {VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME}, 0, 0, false},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {"ext"}, 0, 0, false});
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME, VK_NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME}, 8, 6, true},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME}, 0, 0, true},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {}, 0, 0, false},
Data{VK_DRIVER_ID_MESA_NVK, 0x2600, {VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME}, 0, 0, true},
Data{VK_DRIVER_ID_MESA_NVK, 0x2600, {}, 0, 0, false},
Data{VK_DRIVER_ID_AMD_OPEN_SOURCE, 0x2000, {}, 0, 0, false},
Data{VK_DRIVER_ID_NVIDIA_PROPRIETARY, 0x2000, {}, 0, 0, false});

::SetEnvironmentVariableA("DXVK_NVAPI_ALLOW_OTHER_DRIVERS", "1");

Expand All @@ -265,10 +261,10 @@ TEST_CASE("D3D12 methods succeed", "[.d3d12]") {
vkProps.idProps->deviceLUIDValid = VK_TRUE;
vkProps.driverProps->driverID = args.driverId;
vkProps.props->deviceID = args.deviceId;
if (args.extensionNames.contains(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME))
vkProps.fragmentShadingRateProps->primitiveFragmentShadingRateWithMultipleViewports = VK_TRUE;
if (args.extensionNames.contains(VK_KHR_COMPUTE_SHADER_DERIVATIVES_EXTENSION_NAME))
vkProps.computeShaderDerivativesProps->meshAndTaskShaderDerivatives = VK_TRUE;
if (args.extensionNames.contains(VK_NV_CUDA_KERNEL_LAUNCH_EXTENSION_NAME)) {
vkProps.cudaKernelLaunchProperties->computeCapabilityMajor = 8;
vkProps.cudaKernelLaunchProperties->computeCapabilityMinor = 6;
}
}));

SetupResourceFactory(std::move(dxgiFactory), std::move(vk), std::move(nvml), std::move(lfx));
Expand Down
7 changes: 6 additions & 1 deletion tests/resource_factory_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ void ConfigureGetPhysicalDeviceProperties2(
.pciBusInfoProps = nullptr,
.driverProps = nullptr,
.fragmentShadingRateProps = nullptr,
.computeShaderDerivativesProps = nullptr};
.computeShaderDerivativesProps = nullptr,
.cudaKernelLaunchProperties = nullptr};

auto next = reinterpret_cast<VkBaseOutStructure*>(props);
while (next != nullptr) {
Expand All @@ -297,6 +298,10 @@ void ConfigureGetPhysicalDeviceProperties2(
vkProps.computeShaderDerivativesProps = reinterpret_cast<VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR*>(next);
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUDA_KERNEL_LAUNCH_PROPERTIES_NV: {
vkProps.cudaKernelLaunchProperties = reinterpret_cast<VkPhysicalDeviceCudaKernelLaunchPropertiesNV*>(next);
break;
}
default:
break;
}
Expand Down
1 change: 1 addition & 0 deletions tests/resource_factory_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct ConfigureProps {
VkPhysicalDeviceDriverPropertiesKHR* driverProps;
VkPhysicalDeviceFragmentShadingRatePropertiesKHR* fragmentShadingRateProps;
VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR* computeShaderDerivativesProps;
VkPhysicalDeviceCudaKernelLaunchPropertiesNV* cudaKernelLaunchProperties;
};

void ConfigureGetPhysicalDeviceProperties2(
Expand Down

0 comments on commit 7b6cf23

Please sign in to comment.