Skip to content

Commit

Permalink
Dynamically fetch instance level vulkan functions
Browse files Browse the repository at this point in the history
  • Loading branch information
EdoardoLuciani committed Apr 16, 2023
1 parent 149cf26 commit 910789e
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 26 deletions.
4 changes: 2 additions & 2 deletions src/VK/UpscaleContext_FSR2_API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ void UpscaleContext_FSR2_API::OnCreateWindowSizeDependentResources(
UpscaleContext::OnCreateWindowSizeDependentResources(input, output, renderWidth, renderHeight, displayWidth, displayHeight, hdr);

// Setup VK interface.
const size_t scratchBufferSize = ffxFsr2GetScratchMemorySizeVK(m_pDevice->GetPhysicalDevice());
const size_t scratchBufferSize = ffxFsr2GetScratchMemorySizeVK(m_pDevice->GetPhysicalDevice(), vkEnumerateDeviceExtensionProperties);
void* scratchBuffer = malloc(scratchBufferSize);
FfxErrorCode errorCode = ffxFsr2GetInterfaceVK(&initializationParameters.callbacks, scratchBuffer, scratchBufferSize, m_pDevice->GetPhysicalDevice(), vkGetDeviceProcAddr);
FfxErrorCode errorCode = ffxFsr2GetInterfaceVK(&initializationParameters.callbacks, scratchBuffer, scratchBufferSize, m_pDevice->GetInstance(), m_pDevice->GetPhysicalDevice(), vkGetInstanceProcAddr);
FFX_ASSERT(errorCode == FFX_OK);

initializationParameters.device = ffxGetDeviceVK(m_pDevice->GetDevice());
Expand Down
67 changes: 45 additions & 22 deletions src/ffx-fsr2-api/vk/ffx_fsr2_vk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,16 @@ typedef struct BackendContext_VK {
} PipelineLayout;

typedef struct VKFunctionTable
{
{
// instance functions
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = 0;
PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties = 0;
PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties = 0;
PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = 0;
PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2 = 0;
PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2 = 0;

// device functions
PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = 0;
PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = 0;
PFN_vkCreateDescriptorPool vkCreateDescriptorPool = 0;
Expand Down Expand Up @@ -132,6 +141,7 @@ typedef struct BackendContext_VK {
PFN_vkCmdClearColorImage vkCmdClearColorImage = 0;
} VkFunctionTable;

VkInstance instance = nullptr;
VkPhysicalDevice physicalDevice = nullptr;
VkDevice device = nullptr;
VkFunctionTable vkFunctionTable = {};
Expand Down Expand Up @@ -170,7 +180,7 @@ typedef struct BackendContext_VK {

} BackendContext_VK;

FFX_API size_t ffxFsr2GetScratchMemorySizeVK(VkPhysicalDevice physicalDevice)
FFX_API size_t ffxFsr2GetScratchMemorySizeVK(VkPhysicalDevice physicalDevice, PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties)
{
uint32_t numExtensions = 0;

Expand All @@ -184,8 +194,9 @@ FfxErrorCode ffxFsr2GetInterfaceVK(
FfxFsr2Interface* outInterface,
void* scratchBuffer,
size_t scratchBufferSize,
VkInstance instance,
VkPhysicalDevice physicalDevice,
PFN_vkGetDeviceProcAddr getDeviceProcAddr)
PFN_vkGetInstanceProcAddr getInstanceProcAddr)
{
FFX_RETURN_ON_ERROR(
outInterface,
Expand All @@ -194,7 +205,7 @@ FfxErrorCode ffxFsr2GetInterfaceVK(
scratchBuffer,
FFX_ERROR_INVALID_POINTER);
FFX_RETURN_ON_ERROR(
scratchBufferSize >= ffxFsr2GetScratchMemorySizeVK(physicalDevice),
scratchBufferSize >= ffxFsr2GetScratchMemorySizeVK(physicalDevice, (PFN_vkEnumerateDeviceExtensionProperties)getInstanceProcAddr(instance, "vkEnumerateDeviceExtensionProperties")),
FFX_ERROR_INSUFFICIENT_MEMORY);

outInterface->fpGetDeviceCapabilities = GetDeviceCapabilitiesVK;
Expand All @@ -214,15 +225,25 @@ FfxErrorCode ffxFsr2GetInterfaceVK(

BackendContext_VK* context = (BackendContext_VK*)scratchBuffer;

context->instance = instance;
context->physicalDevice = physicalDevice;
context->vkFunctionTable.vkGetDeviceProcAddr = getDeviceProcAddr;
context->vkFunctionTable.vkGetInstanceProcAddr = getInstanceProcAddr;

return FFX_OK;
}

void loadVKFunctions(BackendContext_VK* backendContext, PFN_vkGetDeviceProcAddr getDeviceProcAddr)
void loadVKFunctions(BackendContext_VK* backendContext, PFN_vkGetInstanceProcAddr getInstanceProcAddr)
{
FFX_ASSERT(NULL != backendContext);

backendContext->vkFunctionTable.vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)getInstanceProcAddr(backendContext->instance, "vkGetDeviceProcAddr");
backendContext->vkFunctionTable.vkEnumerateDeviceExtensionProperties = (PFN_vkEnumerateDeviceExtensionProperties)getInstanceProcAddr(backendContext->instance, "vkEnumerateDeviceExtensionProperties");
backendContext->vkFunctionTable.vkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties)getInstanceProcAddr(backendContext->instance, "vkGetPhysicalDeviceMemoryProperties");
backendContext->vkFunctionTable.vkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties)getInstanceProcAddr(backendContext->instance, "vkGetPhysicalDeviceProperties");
backendContext->vkFunctionTable.vkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2)getInstanceProcAddr(backendContext->instance, "vkGetPhysicalDeviceProperties2");
backendContext->vkFunctionTable.vkGetPhysicalDeviceFeatures2 = (PFN_vkGetPhysicalDeviceFeatures2)getInstanceProcAddr(backendContext->instance, "vkGetPhysicalDeviceFeatures2");

PFN_vkGetDeviceProcAddr getDeviceProcAddr = backendContext->vkFunctionTable.vkGetDeviceProcAddr;

backendContext->vkFunctionTable.vkSetDebugUtilsObjectNameEXT = (PFN_vkSetDebugUtilsObjectNameEXT)getDeviceProcAddr(backendContext->device, "vkSetDebugUtilsObjectNameEXT");
backendContext->vkFunctionTable.vkFlushMappedMemoryRanges = (PFN_vkFlushMappedMemoryRanges)getDeviceProcAddr(backendContext->device, "vkFlushMappedMemoryRanges");
Expand Down Expand Up @@ -444,13 +465,10 @@ FfxSurfaceFormat ffxGetSurfaceFormatVK(VkFormat fmt)
}
}

uint32_t findMemoryTypeIndex(VkPhysicalDevice physicalDevice, VkMemoryRequirements memRequirements, VkMemoryPropertyFlags requestedProperties, VkMemoryPropertyFlags& outProperties)
uint32_t findMemoryTypeIndex(VkPhysicalDevice physicalDevice, VkMemoryRequirements memRequirements, VkMemoryPropertyFlags requestedProperties, VkMemoryPropertyFlags& outProperties, VkPhysicalDeviceMemoryProperties &memProperties)
{
FFX_ASSERT(NULL != physicalDevice);

VkPhysicalDeviceMemoryProperties memProperties;
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);

uint32_t bestCandidate = UINT32_MAX;

for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
Expand Down Expand Up @@ -736,7 +754,7 @@ FfxErrorCode GetDeviceCapabilitiesVK(FfxFsr2Interface* backendInterface, FfxDevi
VkPhysicalDeviceProperties2 deviceProperties2 = {};
deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
deviceProperties2.pNext = &subgroupSizeControlProperties;
vkGetPhysicalDeviceProperties2(backendContext->physicalDevice, &deviceProperties2);
backendContext->vkFunctionTable.vkGetPhysicalDeviceProperties2(backendContext->physicalDevice, &deviceProperties2);

// NOTE: It's important to check requiredSubgroupSizeStages flags (and it's required by the spec).
// As of August 2022, AMD's Vulkan drivers do not support subgroup size selection through Vulkan API
Expand All @@ -756,8 +774,7 @@ FfxErrorCode GetDeviceCapabilitiesVK(FfxFsr2Interface* backendInterface, FfxDevi
VkPhysicalDeviceFeatures2 physicalDeviceFeatures2 = {};
physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
physicalDeviceFeatures2.pNext = &shaderFloat18Int8Features;

vkGetPhysicalDeviceFeatures2(backendContext->physicalDevice, &physicalDeviceFeatures2);
backendContext->vkFunctionTable.vkGetPhysicalDeviceFeatures2(backendContext->physicalDevice, &physicalDeviceFeatures2);

deviceCapabilities->fp16Supported = (bool)shaderFloat18Int8Features.shaderFloat16;
}
Expand All @@ -770,8 +787,7 @@ FfxErrorCode GetDeviceCapabilitiesVK(FfxFsr2Interface* backendInterface, FfxDevi
VkPhysicalDeviceFeatures2 physicalDeviceFeatures2 = {};
physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
physicalDeviceFeatures2.pNext = &accelerationStructureFeatures;

vkGetPhysicalDeviceFeatures2(backendContext->physicalDevice, &physicalDeviceFeatures2);
backendContext->vkFunctionTable.vkGetPhysicalDeviceFeatures2(backendContext->physicalDevice, &physicalDeviceFeatures2);

deviceCapabilities->raytracingSupported = (bool)accelerationStructureFeatures.accelerationStructure;
}
Expand Down Expand Up @@ -805,12 +821,13 @@ FfxErrorCode CreateBackendContextVK(FfxFsr2Interface* backendInterface, FfxDevic
backendContext->nextDynamicResource = FSR2_MAX_RESOURCE_COUNT - 1;

// load vulkan functions
loadVKFunctions(backendContext, backendContext->vkFunctionTable.vkGetDeviceProcAddr);
loadVKFunctions(backendContext, backendContext->vkFunctionTable.vkGetInstanceProcAddr);

// enumerate all the device extensions
backendContext->numDeviceExtensions = 0;
vkEnumerateDeviceExtensionProperties(backendContext->physicalDevice, nullptr, &backendContext->numDeviceExtensions, nullptr);
vkEnumerateDeviceExtensionProperties(backendContext->physicalDevice, nullptr, &backendContext->numDeviceExtensions, backendContext->extensionProperties);

backendContext->vkFunctionTable.vkEnumerateDeviceExtensionProperties(backendContext->physicalDevice, nullptr, &backendContext->numDeviceExtensions, nullptr);
backendContext->vkFunctionTable.vkEnumerateDeviceExtensionProperties(backendContext->physicalDevice, nullptr, &backendContext->numDeviceExtensions, backendContext->extensionProperties);

// create descriptor pool
VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = {};
Expand Down Expand Up @@ -907,14 +924,17 @@ FfxErrorCode CreateBackendContextVK(FfxFsr2Interface* backendInterface, FfxDevic

VkMemoryPropertyFlags requiredMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

VkPhysicalDeviceMemoryProperties memProperties;
backendContext->vkFunctionTable.vkGetPhysicalDeviceMemoryProperties(backendContext->physicalDevice, &memProperties);

VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = FSR2_UBO_MEMORY_BLOCK_SIZE;
allocInfo.memoryTypeIndex = findMemoryTypeIndex(backendContext->physicalDevice, memRequirements, requiredMemoryProperties, backendContext->uboMemoryProperties);
allocInfo.memoryTypeIndex = findMemoryTypeIndex(backendContext->physicalDevice, memRequirements, requiredMemoryProperties, backendContext->uboMemoryProperties, memProperties);

if (allocInfo.memoryTypeIndex == UINT32_MAX) {
requiredMemoryProperties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
allocInfo.memoryTypeIndex = findMemoryTypeIndex(backendContext->physicalDevice, memRequirements, requiredMemoryProperties, backendContext->uboMemoryProperties);
allocInfo.memoryTypeIndex = findMemoryTypeIndex(backendContext->physicalDevice, memRequirements, requiredMemoryProperties, backendContext->uboMemoryProperties, memProperties);

if (allocInfo.memoryTypeIndex == UINT32_MAX) {
return FFX_ERROR_BACKEND_API_ERROR;
Expand Down Expand Up @@ -1107,10 +1127,13 @@ FfxErrorCode CreateResourceVK(
else
requiredMemoryProperties = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

VkPhysicalDeviceMemoryProperties memProperties;
backendContext->vkFunctionTable.vkGetPhysicalDeviceMemoryProperties(backendContext->physicalDevice, &memProperties);

VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
allocInfo.memoryTypeIndex = findMemoryTypeIndex(backendContext->physicalDevice, memRequirements, requiredMemoryProperties, res->memoryProperties);
allocInfo.memoryTypeIndex = findMemoryTypeIndex(backendContext->physicalDevice, memRequirements, requiredMemoryProperties, res->memoryProperties, memProperties);

if (allocInfo.memoryTypeIndex == UINT32_MAX) {
return FFX_ERROR_BACKEND_API_ERROR;
Expand Down Expand Up @@ -1298,7 +1321,7 @@ FfxErrorCode CreatePipelineVK(FfxFsr2Interface* backendInterface, FfxFsr2Pass pa
if (pass == FFX_FSR2_PASS_ACCUMULATE || pass == FFX_FSR2_PASS_ACCUMULATE_SHARPEN)
{
VkPhysicalDeviceProperties physicalDeviceProperties = {};
vkGetPhysicalDeviceProperties(backendContext->physicalDevice, &physicalDeviceProperties);
backendContext->vkFunctionTable.vkGetPhysicalDeviceProperties(backendContext->physicalDevice, &physicalDeviceProperties);

// Workaround: Disable FP16 path for the accumulate pass on NVIDIA due to reduced occupancy and high VRAM throughput.
if (physicalDeviceProperties.vendorID == 0x10DE)
Expand Down
5 changes: 3 additions & 2 deletions src/ffx-fsr2-api/vk/ffx_fsr2_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ extern "C" {
///
/// @returns
/// The size (in bytes) of the required scratch memory buffer for the VK backend.
FFX_API size_t ffxFsr2GetScratchMemorySizeVK(VkPhysicalDevice physicalDevice);
FFX_API size_t ffxFsr2GetScratchMemorySizeVK(VkPhysicalDevice physicalDevice, PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties);

/// Populate an interface with pointers for the VK backend.
///
Expand All @@ -55,8 +55,9 @@ extern "C" {
FfxFsr2Interface* outInterface,
void* scratchBuffer,
size_t scratchBufferSize,
VkInstance instance,
VkPhysicalDevice physicalDevice,
PFN_vkGetDeviceProcAddr getDeviceProcAddr);
PFN_vkGetInstanceProcAddr getInstanceProcAddr);

/// Create a <c><i>FfxFsr2Device</i></c> from a <c><i>VkDevice</i></c>.
///
Expand Down

0 comments on commit 910789e

Please sign in to comment.