diff --git a/renderdoc/driver/vulkan/official/vk_layer.h b/renderdoc/driver/vulkan/official/vk_layer.h index cf16b2b7b..38222a7d7 100644 --- a/renderdoc/driver/vulkan/official/vk_layer.h +++ b/renderdoc/driver/vulkan/official/vk_layer.h @@ -162,6 +162,7 @@ typedef struct VkLayerDispatchTable_ { PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR; PFN_vkAcquireNextImageKHR AcquireNextImageKHR; PFN_vkQueuePresentKHR QueuePresentKHR; + PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR; } VkLayerDispatchTable; typedef struct VkLayerInstanceDispatchTable_ { diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 93c8cf323..3a43f5885 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -317,6 +317,9 @@ private: vector m_MemIdxMaps; void RemapMemoryIndices(VkPhysicalDeviceMemoryProperties *memProps, uint32_t **memIdxMap); + void WrapAndProcessCreatedSwapchain(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, + VkSwapchainKHR *pSwapChain); + struct { void Reset() @@ -1334,4 +1337,40 @@ public: uint32_t queueFamilyIndex, Display *dpy, VisualID visualID); #endif + + // VK_KHR_display and VK_KHR_display_swapchain. These have no library or include dependencies so + // wecan just compile them in on all platforms to reduce platform-specific code. They are mostly + // only actually used though on *nix. + VkResult vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, + uint32_t *pPropertyCount, + VkDisplayPropertiesKHR *pProperties); + + VkResult vkGetPhysicalDeviceDisplayPlanePropertiesKHR(VkPhysicalDevice physicalDevice, + uint32_t *pPropertyCount, + VkDisplayPlanePropertiesKHR *pProperties); + + VkResult vkGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, uint32_t planeIndex, + uint32_t *pDisplayCount, VkDisplayKHR *pDisplays); + + VkResult vkGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, + uint32_t *pPropertyCount, + VkDisplayModePropertiesKHR *pProperties); + + VkResult vkCreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, + const VkDisplayModeCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkDisplayModeKHR *pMode); + + VkResult vkGetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, VkDisplayModeKHR mode, + uint32_t planeIndex, + VkDisplayPlaneCapabilitiesKHR *pCapabilities); + + VkResult vkCreateDisplayPlaneSurfaceKHR(VkInstance instance, + const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkSurfaceKHR *pSurface); + + VkResult vkCreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount, + const VkSwapchainCreateInfoKHR *pCreateInfos, + const VkAllocationCallbacks *pAllocator, + VkSwapchainKHR *pSwapchains); }; diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index 6b7d60452..2940129d4 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -32,6 +32,8 @@ #undef VK_KHR_android_surface #undef VK_KHR_surface #undef VK_KHR_swapchain +#undef VK_KHR_display +#undef VK_KHR_display_swapchain #undef VK_EXT_debug_report #undef VK_EXT_debug_marker @@ -243,23 +245,37 @@ HookInit(CmdExecuteCommands); \ HookInit(CmdEndRenderPass); +// We can always build in VK_KHR_display and VK_KHR_display_swapchain support +// because they don't need any libraries or headers. +// They're not really used or relevant on win32/android but for platform simplicity +// we just include it always, it does no harm to include. + // for simplicity and since the check itself is platform agnostic, // these aren't protected in platform defines -#define CheckInstanceExts() \ - CheckExt(VK_KHR_xlib_surface) CheckExt(VK_KHR_xcb_surface) CheckExt(VK_KHR_win32_surface) \ - CheckExt(VK_KHR_android_surface) CheckExt(VK_KHR_surface) CheckExt(VK_EXT_debug_report) +#define CheckInstanceExts() \ + CheckExt(VK_KHR_xlib_surface) CheckExt(VK_KHR_xcb_surface) CheckExt(VK_KHR_win32_surface) \ + CheckExt(VK_KHR_android_surface) CheckExt(VK_KHR_surface) CheckExt(VK_EXT_debug_report) \ + CheckExt(VK_KHR_display) -#define CheckDeviceExts() CheckExt(VK_EXT_debug_marker) CheckExt(VK_KHR_swapchain) +#define CheckDeviceExts() \ + CheckExt(VK_EXT_debug_marker) CheckExt(VK_KHR_swapchain) CheckExt(VK_KHR_display_swapchain) -#define HookInitVulkanInstanceExts() \ - HookInitExtension(VK_KHR_surface, DestroySurfaceKHR); \ - HookInitExtension(VK_KHR_surface, GetPhysicalDeviceSurfaceSupportKHR); \ - HookInitExtension(VK_KHR_surface, GetPhysicalDeviceSurfaceCapabilitiesKHR); \ - HookInitExtension(VK_KHR_surface, GetPhysicalDeviceSurfaceFormatsKHR); \ - HookInitExtension(VK_KHR_surface, GetPhysicalDeviceSurfacePresentModesKHR); \ - HookInitExtension(VK_EXT_debug_report, CreateDebugReportCallbackEXT); \ - HookInitExtension(VK_EXT_debug_report, DestroyDebugReportCallbackEXT); \ - HookInitExtension(VK_EXT_debug_report, DebugReportMessageEXT); \ +#define HookInitVulkanInstanceExts() \ + HookInitExtension(VK_KHR_surface, DestroySurfaceKHR); \ + HookInitExtension(VK_KHR_surface, GetPhysicalDeviceSurfaceSupportKHR); \ + HookInitExtension(VK_KHR_surface, GetPhysicalDeviceSurfaceCapabilitiesKHR); \ + HookInitExtension(VK_KHR_surface, GetPhysicalDeviceSurfaceFormatsKHR); \ + HookInitExtension(VK_KHR_surface, GetPhysicalDeviceSurfacePresentModesKHR); \ + HookInitExtension(VK_EXT_debug_report, CreateDebugReportCallbackEXT); \ + HookInitExtension(VK_EXT_debug_report, DestroyDebugReportCallbackEXT); \ + HookInitExtension(VK_EXT_debug_report, DebugReportMessageEXT); \ + HookInitExtension(VK_KHR_display, GetPhysicalDeviceDisplayPropertiesKHR); \ + HookInitExtension(VK_KHR_display, GetPhysicalDeviceDisplayPlanePropertiesKHR); \ + HookInitExtension(VK_KHR_display, GetDisplayPlaneSupportedDisplaysKHR); \ + HookInitExtension(VK_KHR_display, GetDisplayModePropertiesKHR); \ + HookInitExtension(VK_KHR_display, CreateDisplayModeKHR); \ + HookInitExtension(VK_KHR_display, GetDisplayPlaneCapabilitiesKHR); \ + HookInitExtension(VK_KHR_display, CreateDisplayPlaneSurfaceKHR); \ HookInitInstance_PlatformSpecific() #define HookInitVulkanDeviceExts() \ @@ -272,7 +288,8 @@ HookInitExtension(VK_KHR_swapchain, DestroySwapchainKHR); \ HookInitExtension(VK_KHR_swapchain, GetSwapchainImagesKHR); \ HookInitExtension(VK_KHR_swapchain, AcquireNextImageKHR); \ - HookInitExtension(VK_KHR_swapchain, QueuePresentKHR); + HookInitExtension(VK_KHR_swapchain, QueuePresentKHR); \ + HookInitExtension(VK_KHR_display_swapchain, CreateSharedSwapchainsKHR); #define DefineHooks() \ HookDefine3(VkResult, vkEnumeratePhysicalDevices, VkInstance, instance, uint32_t *, \ @@ -597,6 +614,28 @@ HookDefine2(VkResult, vkQueuePresentKHR, VkQueue, queue, VkPresentInfoKHR *, pPresentInfo); \ HookDefine3(void, vkDestroySurfaceKHR, VkInstance, instance, VkSurfaceKHR, surface, \ const VkAllocationCallbacks *, pAllocator); \ + HookDefine3(VkResult, vkGetPhysicalDeviceDisplayPropertiesKHR, VkPhysicalDevice, physicalDevice, \ + uint32_t *, pPropertyCount, VkDisplayPropertiesKHR *, pProperties); \ + HookDefine3(VkResult, vkGetPhysicalDeviceDisplayPlanePropertiesKHR, VkPhysicalDevice, \ + physicalDevice, uint32_t *, pPropertyCount, VkDisplayPlanePropertiesKHR *, \ + pProperties); \ + HookDefine4(VkResult, vkGetDisplayPlaneSupportedDisplaysKHR, VkPhysicalDevice, physicalDevice, \ + uint32_t, planeIndex, uint32_t *, pDisplayCount, VkDisplayKHR *, pDisplays); \ + HookDefine4(VkResult, vkGetDisplayModePropertiesKHR, VkPhysicalDevice, physicalDevice, \ + VkDisplayKHR, display, uint32_t *, pPropertyCount, VkDisplayModePropertiesKHR *, \ + pProperties); \ + HookDefine5(VkResult, vkCreateDisplayModeKHR, VkPhysicalDevice, physicalDevice, VkDisplayKHR, \ + display, const VkDisplayModeCreateInfoKHR *, pCreateInfo, \ + const VkAllocationCallbacks *, pAllocator, VkDisplayModeKHR *, pMode); \ + HookDefine4(VkResult, vkGetDisplayPlaneCapabilitiesKHR, VkPhysicalDevice, physicalDevice, \ + VkDisplayModeKHR, mode, uint32_t, planeIndex, VkDisplayPlaneCapabilitiesKHR *, \ + pCapabilities); \ + HookDefine4(VkResult, vkCreateDisplayPlaneSurfaceKHR, VkInstance, instance, \ + const VkDisplaySurfaceCreateInfoKHR *, pCreateInfo, const VkAllocationCallbacks *, \ + pAllocator, VkSurfaceKHR *, pSurface); \ + HookDefine5(VkResult, vkCreateSharedSwapchainsKHR, VkDevice, device, uint32_t, swapchainCount, \ + const VkSwapchainCreateInfoKHR *, pCreateInfos, const VkAllocationCallbacks *, \ + pAllocator, VkSwapchainKHR *, pSwapchains); \ HookDefine_PlatformSpecific() struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index 18d522b35..e0e5ad85c 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -72,6 +72,9 @@ enum VkResourceType eResSurface }; +// VkDisplayKHR and VkDisplayModeKHR are both UNWRAPPED because there's no need to wrap them. +// The only thing we need to wrap VkSurfaceKHR for is to get back the window from it later. + // dummy standin for a typeless real resource // stored in a uint64_t, with function to cast back // if we know what type it is @@ -544,6 +547,9 @@ struct WrappedVkSurfaceKHR : WrappedVkNonDispRes }; }; +// VkDisplayKHR and VkDisplayModeKHR are both UNWRAPPED because there's no need to wrap them. +// The only thing we need to wrap VkSurfaceKHR for is to get back the window from it later. + // Note: we assume only the following resources can return duplicate handles (and so // on replay we need to handle two distinct ids with the same handle. // Other resources are discounted because they have 'state' or otherwise wouldn't make @@ -630,6 +636,9 @@ UNWRAP_NONDISP_HELPER(VkCommandPool) UNWRAP_NONDISP_HELPER(VkSwapchainKHR) UNWRAP_NONDISP_HELPER(VkSurfaceKHR) +// VkDisplayKHR and VkDisplayModeKHR are both UNWRAPPED because there's no need to wrap them. +// The only thing we need to wrap VkSurfaceKHR for is to get back the window from it later. + #define WRAPPING_DEBUG 0 template diff --git a/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp index 989ffdc37..e2b855303 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_wsi_funcs.cpp @@ -295,6 +295,183 @@ bool WrappedVulkan::Serialise_vkCreateSwapchainKHR(Serialiser *localSerialiser, return true; } +void WrappedVulkan::WrapAndProcessCreatedSwapchain(VkDevice device, + const VkSwapchainCreateInfoKHR *pCreateInfo, + VkSwapchainKHR *pSwapChain) +{ + ResourceId id = GetResourceManager()->WrapResource(Unwrap(device), *pSwapChain); + + if(m_State >= WRITING) + { + Chunk *chunk = NULL; + + { + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CONTEXT(CREATE_SWAP_BUFFER); + Serialise_vkCreateSwapchainKHR(localSerialiser, device, pCreateInfo, NULL, pSwapChain); + + chunk = scope.Get(); + } + + VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pSwapChain); + record->AddChunk(chunk); + + record->swapInfo = new SwapchainInfo(); + SwapchainInfo &swapInfo = *record->swapInfo; + + // sneaky casting of window handle into record + swapInfo.wndHandle = (RENDERDOC_WindowHandle)GetRecord(pCreateInfo->surface); + + { + SCOPED_LOCK(m_SwapLookupLock); + m_SwapLookup[swapInfo.wndHandle] = *pSwapChain; + } + + RenderDoc::Inst().AddFrameCapturer(LayerDisp(m_Instance), swapInfo.wndHandle, this); + + swapInfo.format = pCreateInfo->imageFormat; + swapInfo.extent = pCreateInfo->imageExtent; + swapInfo.arraySize = pCreateInfo->imageArrayLayers; + + VkResult vkr = VK_SUCCESS; + + const VkLayerDispatchTable *vt = ObjDisp(device); + + { + VkAttachmentDescription attDesc = { + 0, + pCreateInfo->imageFormat, + VK_SAMPLE_COUNT_1_BIT, + VK_ATTACHMENT_LOAD_OP_LOAD, + VK_ATTACHMENT_STORE_OP_STORE, + VK_ATTACHMENT_LOAD_OP_DONT_CARE, + VK_ATTACHMENT_STORE_OP_DONT_CARE, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + }; + + VkAttachmentReference attRef = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; + + VkSubpassDescription sub = { + 0, VK_PIPELINE_BIND_POINT_GRAPHICS, + 0, NULL, // inputs + 1, &attRef, // color + NULL, // resolve + NULL, // depth-stencil + 0, NULL, // preserve + }; + + VkRenderPassCreateInfo rpinfo = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, + NULL, + 0, + 1, + &attDesc, + 1, + &sub, + 0, + NULL, // dependencies + }; + + vkr = vt->CreateRenderPass(Unwrap(device), &rpinfo, NULL, &swapInfo.rp); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + + GetResourceManager()->WrapResource(Unwrap(device), swapInfo.rp); + } + + // serialise out the swap chain images + { + uint32_t numSwapImages; + vkr = vt->GetSwapchainImagesKHR(Unwrap(device), Unwrap(*pSwapChain), &numSwapImages, NULL); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + + swapInfo.lastPresent = 0; + swapInfo.images.resize(numSwapImages); + for(uint32_t i = 0; i < numSwapImages; i++) + { + swapInfo.images[i].im = VK_NULL_HANDLE; + swapInfo.images[i].view = VK_NULL_HANDLE; + swapInfo.images[i].fb = VK_NULL_HANDLE; + } + + VkImage *images = new VkImage[numSwapImages]; + + // go through our own function so we assign these images IDs + vkr = vkGetSwapchainImagesKHR(device, *pSwapChain, &numSwapImages, images); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + + for(uint32_t i = 0; i < numSwapImages; i++) + { + SwapchainInfo::SwapImage &swapImInfo = swapInfo.images[i]; + + // memory doesn't exist for genuine WSI created images + swapImInfo.im = images[i]; + + ResourceId imid = GetResID(images[i]); + + VkImageSubresourceRange range; + range.baseMipLevel = range.baseArrayLayer = 0; + range.levelCount = 1; + range.layerCount = pCreateInfo->imageArrayLayers; + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + + // fill out image info so we track resource state barriers + { + SCOPED_LOCK(m_ImageLayoutsLock); + m_ImageLayouts[imid].subresourceStates.clear(); + m_ImageLayouts[imid].subresourceStates.push_back( + ImageRegionState(range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED)); + } + + { + VkImageViewCreateInfo info = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + NULL, + 0, + Unwrap(images[i]), + VK_IMAGE_VIEW_TYPE_2D, + pCreateInfo->imageFormat, + {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, + VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}, + {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, + }; + + vkr = vt->CreateImageView(Unwrap(device), &info, NULL, &swapImInfo.view); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + + GetResourceManager()->WrapResource(Unwrap(device), swapImInfo.view); + + VkFramebufferCreateInfo fbinfo = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, + NULL, + 0, + Unwrap(swapInfo.rp), + 1, + UnwrapPtr(swapImInfo.view), + (uint32_t)pCreateInfo->imageExtent.width, + (uint32_t)pCreateInfo->imageExtent.height, + 1, + }; + + vkr = vt->CreateFramebuffer(Unwrap(device), &fbinfo, NULL, &swapImInfo.fb); + RDCASSERTEQUAL(vkr, VK_SUCCESS); + + GetResourceManager()->WrapResource(Unwrap(device), swapImInfo.fb); + } + } + + SAFE_DELETE_ARRAY(images); + } + + FirstFrame(*pSwapChain); + } + else + { + GetResourceManager()->AddLiveResource(id, *pSwapChain); + } +} + VkResult WrappedVulkan::vkCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, @@ -311,179 +488,7 @@ VkResult WrappedVulkan::vkCreateSwapchainKHR(VkDevice device, ObjDisp(device)->CreateSwapchainKHR(Unwrap(device), &createInfo, pAllocator, pSwapChain); if(ret == VK_SUCCESS) - { - ResourceId id = GetResourceManager()->WrapResource(Unwrap(device), *pSwapChain); - - if(m_State >= WRITING) - { - Chunk *chunk = NULL; - - { - CACHE_THREAD_SERIALISER(); - - SCOPED_SERIALISE_CONTEXT(CREATE_SWAP_BUFFER); - Serialise_vkCreateSwapchainKHR(localSerialiser, device, pCreateInfo, NULL, pSwapChain); - - chunk = scope.Get(); - } - - VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pSwapChain); - record->AddChunk(chunk); - - record->swapInfo = new SwapchainInfo(); - SwapchainInfo &swapInfo = *record->swapInfo; - - // sneaky casting of window handle into record - swapInfo.wndHandle = (RENDERDOC_WindowHandle)GetRecord(pCreateInfo->surface); - - { - SCOPED_LOCK(m_SwapLookupLock); - m_SwapLookup[swapInfo.wndHandle] = *pSwapChain; - } - - RenderDoc::Inst().AddFrameCapturer(LayerDisp(m_Instance), swapInfo.wndHandle, this); - - swapInfo.format = pCreateInfo->imageFormat; - swapInfo.extent = pCreateInfo->imageExtent; - swapInfo.arraySize = pCreateInfo->imageArrayLayers; - - VkResult vkr = VK_SUCCESS; - - const VkLayerDispatchTable *vt = ObjDisp(device); - - { - VkAttachmentDescription attDesc = { - 0, - pCreateInfo->imageFormat, - VK_SAMPLE_COUNT_1_BIT, - VK_ATTACHMENT_LOAD_OP_LOAD, - VK_ATTACHMENT_STORE_OP_STORE, - VK_ATTACHMENT_LOAD_OP_DONT_CARE, - VK_ATTACHMENT_STORE_OP_DONT_CARE, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - }; - - VkAttachmentReference attRef = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - VkSubpassDescription sub = { - 0, VK_PIPELINE_BIND_POINT_GRAPHICS, - 0, NULL, // inputs - 1, &attRef, // color - NULL, // resolve - NULL, // depth-stencil - 0, NULL, // preserve - }; - - VkRenderPassCreateInfo rpinfo = { - VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, - NULL, - 0, - 1, - &attDesc, - 1, - &sub, - 0, - NULL, // dependencies - }; - - vkr = vt->CreateRenderPass(Unwrap(device), &rpinfo, NULL, &swapInfo.rp); - RDCASSERTEQUAL(vkr, VK_SUCCESS); - - GetResourceManager()->WrapResource(Unwrap(device), swapInfo.rp); - } - - // serialise out the swap chain images - { - uint32_t numSwapImages; - vkr = vt->GetSwapchainImagesKHR(Unwrap(device), Unwrap(*pSwapChain), &numSwapImages, NULL); - RDCASSERTEQUAL(vkr, VK_SUCCESS); - - swapInfo.lastPresent = 0; - swapInfo.images.resize(numSwapImages); - for(uint32_t i = 0; i < numSwapImages; i++) - { - swapInfo.images[i].im = VK_NULL_HANDLE; - swapInfo.images[i].view = VK_NULL_HANDLE; - swapInfo.images[i].fb = VK_NULL_HANDLE; - } - - VkImage *images = new VkImage[numSwapImages]; - - // go through our own function so we assign these images IDs - vkr = vkGetSwapchainImagesKHR(device, *pSwapChain, &numSwapImages, images); - RDCASSERTEQUAL(vkr, VK_SUCCESS); - - for(uint32_t i = 0; i < numSwapImages; i++) - { - SwapchainInfo::SwapImage &swapImInfo = swapInfo.images[i]; - - // memory doesn't exist for genuine WSI created images - swapImInfo.im = images[i]; - - ResourceId imid = GetResID(images[i]); - - VkImageSubresourceRange range; - range.baseMipLevel = range.baseArrayLayer = 0; - range.levelCount = 1; - range.layerCount = pCreateInfo->imageArrayLayers; - range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - - // fill out image info so we track resource state barriers - { - SCOPED_LOCK(m_ImageLayoutsLock); - m_ImageLayouts[imid].subresourceStates.clear(); - m_ImageLayouts[imid].subresourceStates.push_back( - ImageRegionState(range, UNKNOWN_PREV_IMG_LAYOUT, VK_IMAGE_LAYOUT_UNDEFINED)); - } - - { - VkImageViewCreateInfo info = { - VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - NULL, - 0, - Unwrap(images[i]), - VK_IMAGE_VIEW_TYPE_2D, - pCreateInfo->imageFormat, - {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}, - {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1}, - }; - - vkr = vt->CreateImageView(Unwrap(device), &info, NULL, &swapImInfo.view); - RDCASSERTEQUAL(vkr, VK_SUCCESS); - - GetResourceManager()->WrapResource(Unwrap(device), swapImInfo.view); - - VkFramebufferCreateInfo fbinfo = { - VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, - NULL, - 0, - Unwrap(swapInfo.rp), - 1, - UnwrapPtr(swapImInfo.view), - (uint32_t)pCreateInfo->imageExtent.width, - (uint32_t)pCreateInfo->imageExtent.height, - 1, - }; - - vkr = vt->CreateFramebuffer(Unwrap(device), &fbinfo, NULL, &swapImInfo.fb); - RDCASSERTEQUAL(vkr, VK_SUCCESS); - - GetResourceManager()->WrapResource(Unwrap(device), swapImInfo.fb); - } - } - - SAFE_DELETE_ARRAY(images); - } - - FirstFrame(*pSwapChain); - } - else - { - GetResourceManager()->AddLiveResource(id, *pSwapChain); - } - } + WrapAndProcessCreatedSwapchain(device, pCreateInfo, pSwapChain); return ret; } @@ -744,7 +749,8 @@ void WrappedVulkan::vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surfac WrappedVkSurfaceKHR *wrapper = GetWrapped(surface); // record pointer has window handle packed in - Keyboard::RemoveInputWindow((void *)wrapper->record); + if(wrapper->record) + Keyboard::RemoveInputWindow((void *)wrapper->record); // now set record pointer back to NULL so no-one tries to delete it wrapper->record = NULL; @@ -754,3 +760,111 @@ void WrappedVulkan::vkDestroySurfaceKHR(VkInstance instance, VkSurfaceKHR surfac GetResourceManager()->ReleaseWrappedResource(surface, true); ObjDisp(instance)->DestroySurfaceKHR(Unwrap(instance), unwrappedObj, pAllocator); } + +// VK_KHR_display and VK_KHR_display_swapchain. These have no library or include dependencies so +// wecan just compile them in on all platforms to reduce platform-specific code. They are mostly +// only actually used though on *nix. + +VkResult WrappedVulkan::vkGetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physicalDevice, + uint32_t *pPropertyCount, + VkDisplayPropertiesKHR *pProperties) +{ + return ObjDisp(physicalDevice) + ->GetPhysicalDeviceDisplayPropertiesKHR(Unwrap(physicalDevice), pPropertyCount, pProperties); +} + +VkResult WrappedVulkan::vkGetPhysicalDeviceDisplayPlanePropertiesKHR( + VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, + VkDisplayPlanePropertiesKHR *pProperties) +{ + return ObjDisp(physicalDevice) + ->GetPhysicalDeviceDisplayPlanePropertiesKHR(Unwrap(physicalDevice), pPropertyCount, + pProperties); +} + +VkResult WrappedVulkan::vkGetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physicalDevice, + uint32_t planeIndex, + uint32_t *pDisplayCount, + VkDisplayKHR *pDisplays) +{ + // we don't wrap the resulting displays since there's no data we need for them + return ObjDisp(physicalDevice) + ->GetDisplayPlaneSupportedDisplaysKHR(Unwrap(physicalDevice), planeIndex, pDisplayCount, + pDisplays); +} + +VkResult WrappedVulkan::vkGetDisplayModePropertiesKHR(VkPhysicalDevice physicalDevice, + VkDisplayKHR display, uint32_t *pPropertyCount, + VkDisplayModePropertiesKHR *pProperties) +{ + // display is not wrapped since we have no need of any data associated with it + return ObjDisp(physicalDevice) + ->GetDisplayModePropertiesKHR(Unwrap(physicalDevice), display, pPropertyCount, pProperties); +} + +VkResult WrappedVulkan::vkCreateDisplayModeKHR(VkPhysicalDevice physicalDevice, VkDisplayKHR display, + const VkDisplayModeCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDisplayModeKHR *pMode) +{ + // we don't wrap the resulting mode since there's no data we need for it + return ObjDisp(physicalDevice) + ->CreateDisplayModeKHR(Unwrap(physicalDevice), display, pCreateInfo, pAllocator, pMode); +} + +VkResult WrappedVulkan::vkGetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physicalDevice, + VkDisplayModeKHR mode, uint32_t planeIndex, + VkDisplayPlaneCapabilitiesKHR *pCapabilities) +{ + // mode is not wrapped since we have no need of any data associated with it + return ObjDisp(physicalDevice) + ->GetDisplayPlaneCapabilitiesKHR(Unwrap(physicalDevice), mode, planeIndex, pCapabilities); +} + +VkResult WrappedVulkan::vkCreateDisplayPlaneSurfaceKHR(VkInstance instance, + const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkSurfaceKHR *pSurface) +{ + // should not come in here at all on replay + RDCASSERT(m_State >= WRITING); + + VkResult ret = ObjDisp(instance)->CreateDisplayPlaneSurfaceKHR(Unwrap(instance), pCreateInfo, + pAllocator, pSurface); + + if(ret == VK_SUCCESS) + { + // we must wrap surfaces to be consistent with the rest of the code and surface handling, + // but there's nothing actually to do here - no meaningful data we care about here. + GetResourceManager()->WrapResource(Unwrap(instance), *pSurface); + } + + return ret; +} + +VkResult WrappedVulkan::vkCreateSharedSwapchainsKHR(VkDevice device, uint32_t swapchainCount, + const VkSwapchainCreateInfoKHR *pCreateInfos, + const VkAllocationCallbacks *pAllocator, + VkSwapchainKHR *pSwapchains) +{ + VkSwapchainCreateInfoKHR *unwrapped = GetTempArray(swapchainCount); + for(uint32_t i = 0; i < swapchainCount; i++) + { + unwrapped[i] = pCreateInfos[i]; + // make sure we can readback to get the screenshot + unwrapped[i].imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + unwrapped[i].surface = Unwrap(unwrapped[i].surface); + unwrapped[i].oldSwapchain = Unwrap(unwrapped[i].oldSwapchain); + } + + VkResult ret = ObjDisp(device)->CreateSharedSwapchainsKHR(Unwrap(device), swapchainCount, + unwrapped, pAllocator, pSwapchains); + + if(ret == VK_SUCCESS) + { + for(uint32_t i = 0; i < swapchainCount; i++) + WrapAndProcessCreatedSwapchain(device, pCreateInfos + i, pSwapchains + i); + } + + return ret; +} \ No newline at end of file