From fa9d10a89424a5c7a5c43646a32de46405efa341 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Sun, 5 Jan 2025 13:20:13 -0800 Subject: [PATCH 1/3] vulkan: Add external-memory-host support Detects the ability to import host pointers directly into the driver. Can avoid the need for staging memory in many cases such as screenshot downloads and memory uploads. --- core/rend/vulkan/vulkan_context.cpp | 49 +++++++++++++++++++++++++++-- core/rend/vulkan/vulkan_context.h | 2 ++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index 557d6bb11b..c9e0629c9d 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -465,9 +465,28 @@ bool VulkanContext::InitDevice() { // Enable VK_EXT_provoking_vertex if available provokingVertexSupported = tryAddDeviceExtension(VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME); + + // Enable VK_EXT_external_memory_host if available + externalMemoryHostSupported = tryAddDeviceExtension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME); } // Get device features + const auto addPointerToChain = [](void* head, const void* ptr) -> void + { + vk::BaseInStructure* prevInStructure = static_cast(head); + while (prevInStructure->pNext) + { + // Structure already in chain + if (prevInStructure->pNext == ptr) + { + return; + } + prevInStructure = const_cast(prevInStructure->pNext); + } + + // Add structure to end + prevInStructure->pNext = static_cast(ptr); + }; vk::PhysicalDeviceFeatures2 featuresChain{}; vk::PhysicalDeviceFeatures& features = featuresChain.features; @@ -475,7 +494,7 @@ bool VulkanContext::InitDevice() vk::PhysicalDeviceProvokingVertexFeaturesEXT provokingVertexFeatures{}; if (provokingVertexSupported) { - featuresChain.pNext = &provokingVertexFeatures; + addPointerToChain(&featuresChain, &provokingVertexFeatures); } // Get the physical device's features @@ -574,7 +593,33 @@ bool VulkanContext::InitDevice() quadRotatePipeline = std::make_unique(true, true); quadRotateDrawer = std::make_unique(); - vk::PhysicalDeviceProperties props = physicalDevice.getProperties(); + + vk::PhysicalDeviceProperties2 properties2; + vk::PhysicalDeviceProperties& props = properties2.properties; + + vk::PhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProperties{}; + if (externalMemoryHostSupported) + { + addPointerToChain(&properties2, &externalMemoryHostProperties); + } + + if (getPhysicalDeviceProperties2Supported && properties2.pNext) + { + physicalDevice.getProperties2(&properties2); + } + else + { + props = physicalDevice.getProperties(); + } + + if (externalMemoryHostSupported) + { + // Only allow usage of VK_EXT_external_memory_host if the imported alignment + // is the same as the system's page size(any pointer can be imported) + externalMemoryHostSupported &= (externalMemoryHostProperties.minImportedHostPointerAlignment == PAGE_SIZE); + } + + driverName = (const char *)props.deviceName; #ifdef __APPLE__ driverVersion = std::to_string(VK_API_VERSION_MAJOR(props.apiVersion)) + "." diff --git a/core/rend/vulkan/vulkan_context.h b/core/rend/vulkan/vulkan_context.h index 4c6a450567..b1ab46c59a 100644 --- a/core/rend/vulkan/vulkan_context.h +++ b/core/rend/vulkan/vulkan_context.h @@ -168,6 +168,7 @@ class VulkanContext : public GraphicsContext, public FlightManager } bool hasPerPixel() override { return fragmentStoresAndAtomics; } bool hasProvokingVertex() { return provokingVertexSupported; } + bool hasExternalMemoryHost() { return externalMemoryHostSupported; } bool recreateSwapChainIfNeeded(); void addToFlight(Deletable *object) override { inFlightObjects[GetCurrentImageIndex()].emplace_back(object); @@ -231,6 +232,7 @@ class VulkanContext : public GraphicsContext, public FlightManager float maxSamplerAnisotropy = 0.f; bool dedicatedAllocationSupported = false; bool provokingVertexSupported = false; + bool externalMemoryHostSupported = false; u32 vendorID = 0; int swapInterval = 1; vk::UniqueDevice device; From 92ed26e4eeabdb02638f6e1ebd92f21a82c97b02 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Sun, 5 Jan 2025 15:19:11 -0800 Subject: [PATCH 2/3] vulkan: Move `addPointerToChain` to `utils.h` --- core/rend/vulkan/utils.h | 17 +++++++++++++++++ core/rend/vulkan/vulkan_context.cpp | 17 ----------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/core/rend/vulkan/utils.h b/core/rend/vulkan/utils.h index 93f9fb66f0..c829fc4580 100644 --- a/core/rend/vulkan/utils.h +++ b/core/rend/vulkan/utils.h @@ -78,6 +78,23 @@ static inline u32 findMemoryType(vk::PhysicalDeviceMemoryProperties const& memor return typeIndex; } +static inline void addPointerToChain(void* head, const void* ptr) +{ + vk::BaseInStructure* prevInStructure = static_cast(head); + while (prevInStructure->pNext) + { + // Structure already in chain + if (prevInStructure->pNext == ptr) + { + return; + } + prevInStructure = const_cast(prevInStructure->pNext); + } + + // Add structure to end + prevInStructure->pNext = static_cast(ptr); +} + static const char GouraudSource[] = R"( #if pp_Gouraud == 0 #define INTERPOLATION flat diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index c9e0629c9d..d21203b14b 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -471,23 +471,6 @@ bool VulkanContext::InitDevice() } // Get device features - const auto addPointerToChain = [](void* head, const void* ptr) -> void - { - vk::BaseInStructure* prevInStructure = static_cast(head); - while (prevInStructure->pNext) - { - // Structure already in chain - if (prevInStructure->pNext == ptr) - { - return; - } - prevInStructure = const_cast(prevInStructure->pNext); - } - - // Add structure to end - prevInStructure->pNext = static_cast(ptr); - }; - vk::PhysicalDeviceFeatures2 featuresChain{}; vk::PhysicalDeviceFeatures& features = featuresChain.features; From 38caf5b37d1dfd7648de1fd1dcf48ae7d7e4e1f8 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Tue, 14 Jan 2025 11:23:57 -0800 Subject: [PATCH 3/3] vulkan: Add missing `stdclass` header for `PAGE_SIZE` --- core/rend/vulkan/vulkan_context.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index d21203b14b..5072bede6a 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -22,6 +22,7 @@ #include "vulkan_renderer.h" #include "imgui.h" #include "imgui_impl_vulkan.h" +#include "stdclass.h" #include "ui/gui.h" #ifdef USE_SDL #include