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 557d6bb11b..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 @@ -465,17 +466,19 @@ 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 - vk::PhysicalDeviceFeatures2 featuresChain{}; vk::PhysicalDeviceFeatures& features = featuresChain.features; vk::PhysicalDeviceProvokingVertexFeaturesEXT provokingVertexFeatures{}; if (provokingVertexSupported) { - featuresChain.pNext = &provokingVertexFeatures; + addPointerToChain(&featuresChain, &provokingVertexFeatures); } // Get the physical device's features @@ -574,7 +577,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;