From bfe021cf73fffe1ddeff62e55bae23deb6254bb2 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 30 Apr 2018 16:41:46 +0100 Subject: [PATCH] Add (mostly disabled) support for VK_KHR_sampler_ycbcr_conversion * We report no support for Ycbcr conversions by snooping the physical device feature query. * Just to be safe, we support pass-through/ignore implementations of most of the functions and pNext structs. --- renderdoc/driver/vulkan/vk_common.h | 27 ++- renderdoc/driver/vulkan/vk_core.cpp | 3 + renderdoc/driver/vulkan/vk_core.h | 10 ++ renderdoc/driver/vulkan/vk_hookset_defs.h | 12 +- renderdoc/driver/vulkan/vk_info.cpp | 6 + renderdoc/driver/vulkan/vk_info.h | 7 + renderdoc/driver/vulkan/vk_resources.cpp | 3 + renderdoc/driver/vulkan/vk_resources.h | 15 ++ renderdoc/driver/vulkan/vk_serialise.cpp | 30 ++++ renderdoc/driver/vulkan/vk_stringise.cpp | 39 ++++- .../driver/vulkan/wrappers/vk_get_funcs.cpp | 13 +- .../driver/vulkan/wrappers/vk_misc_funcs.cpp | 161 +++++++++++++++++- 12 files changed, 320 insertions(+), 6 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index cb3566045..5c12ea681 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -291,6 +291,25 @@ const VkGenericStruct *FindNextStruct(const VkStruct *haystack, VkStructureType return NULL; } +template +VkGenericStruct *FindNextStruct(VkStruct *haystack, VkStructureType needle) +{ + if(!haystack) + return NULL; + + VkGenericStruct *next = (VkGenericStruct *)haystack->pNext; + while(next) + { + if(next->sType == needle) + return next; + + // assume non-const pNext in the original struct + next = (VkGenericStruct *)next->pNext; + } + + return NULL; +} + enum class MemoryScope : uint8_t { InitialContents, @@ -481,6 +500,7 @@ enum class VulkanChunk : uint32_t vkCmdBeginDebugUtilsLabelEXT, vkCmdEndDebugUtilsLabelEXT, vkCmdInsertDebugUtilsLabelEXT, + vkCreateSamplerYcbcrConversionKHR, Max, }; @@ -636,6 +656,7 @@ DECLARE_REFLECTION_STRUCT(VkVertexInputBindingDivisorDescriptionEXT); DECLARE_REFLECTION_STRUCT(VkPipelineVertexInputDivisorStateCreateInfoEXT); DECLARE_REFLECTION_STRUCT(VkSamplerReductionModeCreateInfoEXT); DECLARE_REFLECTION_STRUCT(VkDebugUtilsLabelEXT); +DECLARE_REFLECTION_STRUCT(VkSamplerYcbcrConversionCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkDeviceCreateInfo); DECLARE_DESERIALISE_TYPE(VkBufferCreateInfo); @@ -682,6 +703,7 @@ DECLARE_DESERIALISE_TYPE(VkRenderPassInputAttachmentAspectCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkPipelineVertexInputDivisorStateCreateInfoEXT); DECLARE_DESERIALISE_TYPE(VkSamplerReductionModeCreateInfoEXT); DECLARE_DESERIALISE_TYPE(VkDebugUtilsLabelEXT); +DECLARE_DESERIALISE_TYPE(VkSamplerYcbcrConversionCreateInfoKHR); DECLARE_REFLECTION_ENUM(VkFlagWithNoBits); DECLARE_REFLECTION_ENUM(VkQueueFlagBits); @@ -749,4 +771,7 @@ DECLARE_REFLECTION_ENUM(VkPresentModeKHR); DECLARE_REFLECTION_ENUM(VkDescriptorUpdateTemplateType); DECLARE_REFLECTION_ENUM(VkConservativeRasterizationModeEXT); DECLARE_REFLECTION_ENUM(VkTessellationDomainOriginKHR); -DECLARE_REFLECTION_ENUM(VkSamplerReductionModeEXT); \ No newline at end of file +DECLARE_REFLECTION_ENUM(VkSamplerReductionModeEXT); +DECLARE_REFLECTION_ENUM(VkSamplerYcbcrModelConversionKHR); +DECLARE_REFLECTION_ENUM(VkSamplerYcbcrRangeKHR); +DECLARE_REFLECTION_ENUM(VkChromaLocation); \ No newline at end of file diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 4d9dac88b..136d86bf2 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -680,6 +680,9 @@ static const VkExtensionProperties supportedExtensions[] = { VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION, }, + { + VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, VK_KHR_SAMPLER_YCBCR_CONVERSION_SPEC_VERSION, + }, { VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION, }, diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index e1d0979d3..a0ce77494 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -1736,4 +1736,14 @@ public: VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData); + + // VK_KHR_sampler_ycbcr_conversion + IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkCreateSamplerYcbcrConversionKHR, VkDevice device, + const VkSamplerYcbcrConversionCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkSamplerYcbcrConversionKHR *pYcbcrConversion); + + IMPLEMENT_FUNCTION_SERIALISED(void, vkDestroySamplerYcbcrConversionKHR, VkDevice device, + VkSamplerYcbcrConversionKHR ycbcrConversion, + const VkAllocationCallbacks *pAllocator); }; diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index 36880e406..eb1181f46 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -327,7 +327,8 @@ CheckExt(EXT_global_priority, VKXX); \ CheckExt(AMD_buffer_marker, VKXX); \ CheckExt(EXT_vertex_attribute_divisor, VKXX); \ - CheckExt(EXT_sampler_filter_minmax, VKXX); + CheckExt(EXT_sampler_filter_minmax, VKXX); \ + CheckExt(KHR_sampler_ycbcr_conversion, VK11); #define HookInitVulkanInstanceExts() \ HookInitExtension(KHR_surface, DestroySurfaceKHR); \ @@ -413,6 +414,8 @@ HookInitExtension(EXT_debug_utils, CmdBeginDebugUtilsLabelEXT); \ HookInitExtension(EXT_debug_utils, CmdEndDebugUtilsLabelEXT); \ HookInitExtension(EXT_debug_utils, CmdInsertDebugUtilsLabelEXT); \ + HookInitExtension(KHR_sampler_ycbcr_conversion, CreateSamplerYcbcrConversionKHR); \ + HookInitExtension(KHR_sampler_ycbcr_conversion, DestroySamplerYcbcrConversionKHR); \ HookInitDevice_PlatformSpecific() #define DefineHooks() \ @@ -882,6 +885,13 @@ VkDebugUtilsMessageSeverityFlagBitsEXT, messageSeverity, \ VkDebugUtilsMessageTypeFlagsEXT, messageTypes, \ const VkDebugUtilsMessengerCallbackDataEXT *, pCallbackData); \ + HookDefine4(VkResult, vkCreateSamplerYcbcrConversionKHR, VkDevice, device, \ + const VkSamplerYcbcrConversionCreateInfoKHR *, pCreateInfo, \ + const VkAllocationCallbacks *, pAllocator, VkSamplerYcbcrConversionKHR *, \ + pYcbcrConversion); \ + HookDefine3(void, vkDestroySamplerYcbcrConversionKHR, VkDevice, device, \ + VkSamplerYcbcrConversionKHR, ycbcrConversion, const VkAllocationCallbacks *, \ + pAllocator); \ HookDefine_PlatformSpecific() struct VkLayerInstanceDispatchTableExtended : VkLayerInstanceDispatchTable diff --git a/renderdoc/driver/vulkan/vk_info.cpp b/renderdoc/driver/vulkan/vk_info.cpp index 78173ecfa..fa47b9ca2 100644 --- a/renderdoc/driver/vulkan/vk_info.cpp +++ b/renderdoc/driver/vulkan/vk_info.cpp @@ -644,6 +644,12 @@ void VulkanCreationInfo::Sampler::Init(VulkanResourceManager *resourceMan, Vulka } } +void VulkanCreationInfo::YCbCrSampler::Init(VulkanResourceManager *resourceMan, + VulkanCreationInfo &info, + const VkSamplerYcbcrConversionCreateInfoKHR *pCreateInfo) +{ +} + static TextureSwizzle Convert(VkComponentSwizzle s, int i) { switch(s) diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index 444a3c345..de3204b96 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -376,6 +376,13 @@ struct VulkanCreationInfo }; map m_Sampler; + struct YCbCrSampler + { + void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, + const VkSamplerYcbcrConversionCreateInfoKHR *pCreateInfo); + }; + map m_YCbCrSampler; + struct ImageView { void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info, diff --git a/renderdoc/driver/vulkan/vk_resources.cpp b/renderdoc/driver/vulkan/vk_resources.cpp index fb55ca159..dd3dcb98d 100644 --- a/renderdoc/driver/vulkan/vk_resources.cpp +++ b/renderdoc/driver/vulkan/vk_resources.cpp @@ -53,6 +53,7 @@ WRAPPED_POOL_INST(WrappedVkCommandPool) WRAPPED_POOL_INST(WrappedVkSwapchainKHR) WRAPPED_POOL_INST(WrappedVkSurfaceKHR) WRAPPED_POOL_INST(WrappedVkDescriptorUpdateTemplateKHR) +WRAPPED_POOL_INST(WrappedVkSamplerYcbcrConversionKHR) byte VkResourceRecord::markerValue[32] = { 0xaa, 0xbb, 0xcc, 0xdd, 0x88, 0x77, 0x66, 0x55, 0x01, 0x23, 0x45, 0x67, 0x98, 0x76, 0x54, 0x32, @@ -123,6 +124,8 @@ VkResourceType IdentifyTypeByPtr(WrappedVkRes *ptr) return eResSurface; if(WrappedVkDescriptorUpdateTemplateKHR::IsAlloc(ptr)) return eResDescUpdateTemplate; + if(WrappedVkSamplerYcbcrConversionKHR::IsAlloc(ptr)) + return eResSamplerConversion; RDCERR("Unknown type for ptr 0x%p", ptr); diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index dda6075dd..5ff893e2f 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -70,6 +70,7 @@ enum VkResourceType eResSwapchain, eResSurface, eResDescUpdateTemplate, + eResSamplerConversion, }; DECLARE_REFLECTION_ENUM(VkResourceType); @@ -561,6 +562,19 @@ struct WrappedVkDescriptorUpdateTemplateKHR : WrappedVkNonDispRes TypeEnum = eResDescUpdateTemplate, }; }; +struct WrappedVkSamplerYcbcrConversionKHR : WrappedVkNonDispRes +{ + WrappedVkSamplerYcbcrConversionKHR(VkSamplerYcbcrConversionKHR obj, ResourceId objId) + : WrappedVkNonDispRes(obj, objId) + { + } + typedef VkSamplerYcbcrConversionKHR InnerType; + ALLOCATE_WITH_WRAPPED_POOL(WrappedVkSamplerYcbcrConversionKHR); + enum + { + TypeEnum = eResSamplerConversion, + }; +}; // 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. @@ -659,6 +673,7 @@ UNWRAP_NONDISP_HELPER(VkCommandPool) UNWRAP_NONDISP_HELPER(VkSwapchainKHR) UNWRAP_NONDISP_HELPER(VkSurfaceKHR) UNWRAP_NONDISP_HELPER(VkDescriptorUpdateTemplateKHR) +UNWRAP_NONDISP_HELPER(VkSamplerYcbcrConversionKHR) // 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. diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index e5dcb4447..fd65b6b7a 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -169,6 +169,12 @@ SERIALISE_VK_HANDLES(); /* VK_EXT_global_priority */ \ PNEXT_IGNORE(VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT) \ \ + /* for now we don't support ycbcr and force-disable the feature bit, so no-one should try */ \ + /* to pNext any of these structs anyway, but if they do, we ignore them */ \ + /* VK_KHR_sampler_ycbcr_conversion */ \ + PNEXT_IGNORE(VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO_KHR) \ + PNEXT_IGNORE(VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO) \ + \ /* VK_EXT_conservative_rasterization */ \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT, \ VkPipelineRasterizationConservativeStateCreateInfoEXT) \ @@ -2365,6 +2371,29 @@ void Deserialise(const VkDebugUtilsLabelEXT &el) DeserialiseNext(el.pNext); } +template +void DoSerialise(SerialiserType &ser, VkSamplerYcbcrConversionCreateInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(format); + SERIALISE_MEMBER(ycbcrModel); + SERIALISE_MEMBER(ycbcrRange); + SERIALISE_MEMBER(components); + SERIALISE_MEMBER(xChromaOffset); + SERIALISE_MEMBER(yChromaOffset); + SERIALISE_MEMBER(chromaFilter); + SERIALISE_MEMBER(forceExplicitReconstruction); +} + +template <> +void Deserialise(const VkSamplerYcbcrConversionCreateInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + INSTANTIATE_SERIALISE_TYPE(VkOffset2D); INSTANTIATE_SERIALISE_TYPE(VkExtent2D); INSTANTIATE_SERIALISE_TYPE(VkMemoryType); @@ -2469,6 +2498,7 @@ INSTANTIATE_SERIALISE_TYPE(VkPipelineRasterizationConservativeStateCreateInfoEXT INSTANTIATE_SERIALISE_TYPE(VkPipelineVertexInputDivisorStateCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkSamplerReductionModeCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkDebugUtilsLabelEXT); +INSTANTIATE_SERIALISE_TYPE(VkSamplerYcbcrConversionCreateInfoKHR); INSTANTIATE_SERIALISE_TYPE(DescriptorSetSlot); INSTANTIATE_SERIALISE_TYPE(ImageRegionState); diff --git a/renderdoc/driver/vulkan/vk_stringise.cpp b/renderdoc/driver/vulkan/vk_stringise.cpp index 0dfe98965..11bb19aa8 100644 --- a/renderdoc/driver/vulkan/vk_stringise.cpp +++ b/renderdoc/driver/vulkan/vk_stringise.cpp @@ -28,7 +28,7 @@ template <> std::string DoStringise(const VulkanChunk &el) { - RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1112, "Chunks changed without updating names"); + RDCCOMPILE_ASSERT((uint32_t)VulkanChunk::Max == 1113, "Chunks changed without updating names"); BEGIN_ENUM_STRINGISE(VulkanChunk) { @@ -144,6 +144,7 @@ std::string DoStringise(const VulkanChunk &el) STRINGISE_ENUM_CLASS(vkCmdBeginDebugUtilsLabelEXT); STRINGISE_ENUM_CLASS(vkCmdEndDebugUtilsLabelEXT); STRINGISE_ENUM_CLASS(vkCmdInsertDebugUtilsLabelEXT); + STRINGISE_ENUM_CLASS(vkCreateSamplerYcbcrConversionKHR); STRINGISE_ENUM_CLASS_NAMED(Max, "Max Chunk"); } END_ENUM_STRINGISE() @@ -1731,6 +1732,42 @@ std::string DoStringise(const VkSamplerReductionModeEXT &el) END_ENUM_STRINGISE(); } +template <> +std::string DoStringise(const VkSamplerYcbcrModelConversionKHR &el) +{ + BEGIN_ENUM_STRINGISE(VkSamplerYcbcrModelConversionKHR); + { + STRINGISE_ENUM(VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR) + STRINGISE_ENUM(VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_IDENTITY_KHR) + STRINGISE_ENUM(VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_709_KHR) + STRINGISE_ENUM(VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR) + STRINGISE_ENUM(VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_2020_KHR) + } + END_ENUM_STRINGISE(); +} + +template <> +std::string DoStringise(const VkSamplerYcbcrRangeKHR &el) +{ + BEGIN_ENUM_STRINGISE(VkSamplerYcbcrRangeKHR); + { + STRINGISE_ENUM(VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR) + STRINGISE_ENUM(VK_SAMPLER_YCBCR_RANGE_ITU_NARROW_KHR) + } + END_ENUM_STRINGISE(); +} + +template <> +std::string DoStringise(const VkChromaLocation &el) +{ + BEGIN_ENUM_STRINGISE(VkChromaLocation); + { + STRINGISE_ENUM(VK_CHROMA_LOCATION_COSITED_EVEN_KHR) + STRINGISE_ENUM(VK_CHROMA_LOCATION_MIDPOINT_KHR) + } + END_ENUM_STRINGISE(); +} + template <> std::string DoStringise(const VkExtent3D &el) { diff --git a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp index cc87c4bdf..4d52b4033 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp @@ -428,7 +428,18 @@ void WrappedVulkan::vkGetPhysicalDeviceExternalFencePropertiesKHR( void WrappedVulkan::vkGetPhysicalDeviceFeatures2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures2KHR *pFeatures) { - return ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2KHR(Unwrap(physicalDevice), pFeatures); + ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2KHR(Unwrap(physicalDevice), pFeatures); + + // if the user is requesting ycbcr features, make sure it's reported as NOT supported + VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR *ycbcr = + (VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR *)FindNextStruct( + pFeatures, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR); + + if(ycbcr) + { + RDCWARN("Forcibly disabling support for YCbCr Conversion"); + ycbcr->samplerYcbcrConversion = VK_FALSE; + } } void WrappedVulkan::vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, diff --git a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp index ad0fdff98..b47ebec6f 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp @@ -111,6 +111,7 @@ DESTROY_IMPL(VkQueryPool, DestroyQueryPool) DESTROY_IMPL(VkFramebuffer, DestroyFramebuffer) DESTROY_IMPL(VkRenderPass, DestroyRenderPass) DESTROY_IMPL(VkDescriptorUpdateTemplateKHR, DestroyDescriptorUpdateTemplateKHR) +DESTROY_IMPL(VkSamplerYcbcrConversionKHR, DestroySamplerYcbcrConversionKHR) #undef DESTROY_IMPL @@ -389,6 +390,13 @@ bool WrappedVulkan::ReleaseResource(WrappedVkRes *res) vt->DestroyDescriptorUpdateTemplateKHR(Unwrap(dev), real, NULL); break; } + case eResSamplerConversion: + { + VkSamplerYcbcrConversionKHR real = nondisp->real.As(); + GetResourceManager()->ReleaseWrappedResource(VkSamplerYcbcrConversionKHR(handle)); + vt->DestroySamplerYcbcrConversionKHR(Unwrap(dev), real, NULL); + break; + } } return true; @@ -454,9 +462,59 @@ bool WrappedVulkan::Serialise_vkCreateSampler(SerialiserType &ser, VkDevice devi VkResult WrappedVulkan::vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) { + VkSamplerCreateInfo info = *pCreateInfo; + + size_t memSize = 0; + + // we don't have to unwrap every struct, but unwrapping a struct means we need to copy + // the previous one in the chain locally to modify the pNext pointer. So we just copy + // all of them locally + { + const VkGenericStruct *next = (const VkGenericStruct *)info.pNext; + while(next) + { + // we need to unwrap these structs + if(next->sType == VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR) + memSize += sizeof(VkSamplerYcbcrConversionInfoKHR); + + next = next->pNext; + } + } + + byte *tempMem = GetTempMemory(memSize); + + { + VkGenericStruct *nextChainTail = (VkGenericStruct *)&info; + const VkGenericStruct *nextInput = (const VkGenericStruct *)info.pNext; + while(nextInput) + { + // unwrap and replace the dedicated allocation struct in the chain + if(nextInput->sType == VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO) + { + const VkSamplerYcbcrConversionInfoKHR *ycbcrIn = + (const VkSamplerYcbcrConversionInfoKHR *)nextInput; + VkSamplerYcbcrConversionInfoKHR *ycbcrOut = (VkSamplerYcbcrConversionInfoKHR *)tempMem; + + // copy and unwrap the struct + ycbcrOut->sType = ycbcrIn->sType; + ycbcrOut->conversion = Unwrap(ycbcrIn->conversion); + + AppendModifiedChainedStruct(tempMem, ycbcrOut, nextChainTail); + } + else + { + RDCERR("unrecognised struct %d in vkAllocateMemoryInfo pNext chain", nextInput->sType); + // can't patch this struct, have to just copy it and hope it's the last in the chain + nextChainTail->pNext = nextInput; + } + + nextInput = nextInput->pNext; + } + } + VkResult ret; SERIALISE_TIME_CALL( - ret = ObjDisp(device)->CreateSampler(Unwrap(device), pCreateInfo, pAllocator, pSampler)); + ret = ObjDisp(device)->CreateSampler(Unwrap(device), &info, pAllocator, pSampler)); if(ret == VK_SUCCESS) { @@ -1011,6 +1069,100 @@ VkResult WrappedVulkan::vkGetQueryPoolResults(VkDevice device, VkQueryPool query queryCount, dataSize, pData, stride, flags); } +template +bool WrappedVulkan::Serialise_vkCreateSamplerYcbcrConversionKHR( + SerialiserType &ser, VkDevice device, const VkSamplerYcbcrConversionCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkSamplerYcbcrConversionKHR *pYcbcrConversion) +{ + SERIALISE_ELEMENT(device); + SERIALISE_ELEMENT_LOCAL(CreateInfo, *pCreateInfo); + SERIALISE_ELEMENT_OPT(pAllocator); + SERIALISE_ELEMENT_LOCAL(ycbcrConversion, GetResID(*pYcbcrConversion)) + .TypedAs("VkSamplerYcbcrConversionKHR"); + + SERIALISE_CHECK_READ_ERRORS(); + + if(IsReplayingAndReading()) + { + VkSamplerYcbcrConversionKHR conv = VK_NULL_HANDLE; + + VkResult ret = + ObjDisp(device)->CreateSamplerYcbcrConversionKHR(Unwrap(device), &CreateInfo, NULL, &conv); + + if(ret != VK_SUCCESS) + { + RDCERR("Failed on resource serialise-creation, VkResult: %s", ToStr(ret).c_str()); + return false; + } + else + { + ResourceId live; + + if(GetResourceManager()->HasWrapper(ToTypedHandle(conv))) + { + live = GetResourceManager()->GetNonDispWrapper(conv)->id; + + // destroy this instance of the duplicate, as we must have matching create/destroy + // calls and there won't be a wrapped resource hanging around to destroy this one. + ObjDisp(device)->DestroySamplerYcbcrConversionKHR(Unwrap(device), conv, NULL); + + // whenever the new ID is requested, return the old ID, via replacements. + GetResourceManager()->ReplaceResource(ycbcrConversion, + GetResourceManager()->GetOriginalID(live)); + } + else + { + live = GetResourceManager()->WrapResource(Unwrap(device), conv); + GetResourceManager()->AddLiveResource(ycbcrConversion, conv); + + m_CreationInfo.m_YCbCrSampler[live].Init(GetResourceManager(), m_CreationInfo, &CreateInfo); + } + } + + AddResource(ycbcrConversion, ResourceType::Sampler, "YCbCr Sampler"); + DerivedResource(device, ycbcrConversion); + } + + return true; +} + +VkResult WrappedVulkan::vkCreateSamplerYcbcrConversionKHR( + VkDevice device, const VkSamplerYcbcrConversionCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, VkSamplerYcbcrConversionKHR *pYcbcrConversion) +{ + VkResult ret; + SERIALISE_TIME_CALL(ret = ObjDisp(device)->CreateSamplerYcbcrConversionKHR( + Unwrap(device), pCreateInfo, pAllocator, pYcbcrConversion)); + + if(ret == VK_SUCCESS) + { + ResourceId id = GetResourceManager()->WrapResource(Unwrap(device), *pYcbcrConversion); + + if(IsCaptureMode(m_State)) + { + Chunk *chunk = NULL; + + { + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCreateSamplerYcbcrConversionKHR); + Serialise_vkCreateSamplerYcbcrConversionKHR(ser, device, pCreateInfo, NULL, pYcbcrConversion); + + chunk = scope.Get(); + } + + VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pYcbcrConversion); + record->AddChunk(chunk); + } + else + { + GetResourceManager()->AddLiveResource(id, *pYcbcrConversion); + } + } + + return ret; +} + struct UserDebugReportCallbackData { VkInstance wrappedInstance; @@ -1618,4 +1770,9 @@ INSTANTIATE_FUNCTION_SERIALISED(void, vkDestroyDebugUtilsMessengerEXT, VkInstanc INSTANTIATE_FUNCTION_SERIALISED(void, vkSubmitDebugUtilsMessageEXT, VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, - const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData); \ No newline at end of file + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData); + +INSTANTIATE_FUNCTION_SERIALISED(VkResult, vkCreateSamplerYcbcrConversionKHR, VkDevice device, + const VkSamplerYcbcrConversionCreateInfoKHR *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkSamplerYcbcrConversionKHR *pYcbcrConversion);