diff --git a/renderdoc/driver/vulkan/extension_support.md b/renderdoc/driver/vulkan/extension_support.md index 0235abddb..5a6826ad1 100644 --- a/renderdoc/driver/vulkan/extension_support.md +++ b/renderdoc/driver/vulkan/extension_support.md @@ -149,6 +149,7 @@ Maintainers can update this file by updating vk.xml in this folder and running ` * `VK_KHR_multiview` * `VK_KHR_performance_query` * `VK_KHR_pipeline_executable_properties` +* `VK_KHR_pipeline_library` * `VK_KHR_present_id` * `VK_KHR_present_wait` * `VK_KHR_push_descriptor` @@ -222,7 +223,6 @@ Ray tracing extensions are now standard and will likely be supported at some poi * `VK_KHR_ray_tracing_pipeline` * `VK_KHR_ray_query` * `VK_KHR_deferred_host_operations` -* `VK_KHR_pipeline_library` ## EXT Extensions diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 826dfd51c..1a016814f 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -1069,6 +1069,7 @@ DECLARE_REFLECTION_STRUCT(VkPipelineFragmentShadingRateStateCreateInfoKHR); DECLARE_REFLECTION_STRUCT(VkPipelineInfoKHR); DECLARE_REFLECTION_STRUCT(VkPipelineInputAssemblyStateCreateInfo); DECLARE_REFLECTION_STRUCT(VkPipelineLayoutCreateInfo); +DECLARE_REFLECTION_STRUCT(VkPipelineLibraryCreateInfoKHR); DECLARE_REFLECTION_STRUCT(VkPipelineMultisampleStateCreateInfo); DECLARE_REFLECTION_STRUCT(VkPipelineRasterizationConservativeStateCreateInfoEXT); DECLARE_REFLECTION_STRUCT(VkPipelineRasterizationDepthClipStateCreateInfoEXT); @@ -1439,6 +1440,7 @@ DECLARE_DESERIALISE_TYPE(VkPipelineFragmentShadingRateStateCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkPipelineInfoKHR); DECLARE_DESERIALISE_TYPE(VkPipelineInputAssemblyStateCreateInfo); DECLARE_DESERIALISE_TYPE(VkPipelineLayoutCreateInfo); +DECLARE_DESERIALISE_TYPE(VkPipelineLibraryCreateInfoKHR); DECLARE_DESERIALISE_TYPE(VkPipelineMultisampleStateCreateInfo); DECLARE_DESERIALISE_TYPE(VkPipelineRasterizationConservativeStateCreateInfoEXT); DECLARE_DESERIALISE_TYPE(VkPipelineRasterizationDepthClipStateCreateInfoEXT); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index fc98c4de2..20b53ccee 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1277,6 +1277,9 @@ static const VkExtensionProperties supportedExtensions[] = { VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME, VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION, }, + { + VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME, VK_KHR_PIPELINE_LIBRARY_SPEC_VERSION, + }, { VK_KHR_PRESENT_ID_EXTENSION_NAME, VK_KHR_PRESENT_ID_SPEC_VERSION, }, diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index bdb63c183..5ab6501ac 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -878,7 +878,7 @@ private: template T UnwrapInfo(const T *info); template - T *UnwrapInfos(const T *infos, uint32_t count); + T *UnwrapInfos(CaptureState state, const T *infos, uint32_t count); void PatchAttachment(VkFramebufferAttachmentImageInfo *att, VkFormat imgFormat, VkSampleCountFlagBits samples); diff --git a/renderdoc/driver/vulkan/vk_next_chains.cpp b/renderdoc/driver/vulkan/vk_next_chains.cpp index 891676529..4414873f4 100644 --- a/renderdoc/driver/vulkan/vk_next_chains.cpp +++ b/renderdoc/driver/vulkan/vk_next_chains.cpp @@ -831,7 +831,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_REDUCTION_STATE_CREATE_INFO_NV: \ case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_TO_COLOR_STATE_CREATE_INFO_NV: \ case VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_ENUM_STATE_CREATE_INFO_NV: \ - case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: \ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT: \ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD: \ case VK_STRUCTURE_TYPE_PIPELINE_REPRESENTATIVE_FRAGMENT_TEST_STATE_CREATE_INFO_NV: \ @@ -1105,6 +1104,14 @@ size_t GetNextPatchSize(const void *pNext) memSize += info->setLayoutCount * sizeof(VkDescriptorSetLayout); break; } + case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: + { + memSize += sizeof(VkPipelineLibraryCreateInfoKHR); + + VkPipelineLibraryCreateInfoKHR *info = (VkPipelineLibraryCreateInfoKHR *)next; + memSize += info->libraryCount * sizeof(VkPipelineLibraryCreateInfoKHR); + break; + } case VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO: { memSize += sizeof(VkPipelineRenderingCreateInfo); @@ -2013,6 +2020,26 @@ void UnwrapNextChain(CaptureState state, const char *structName, byte *&tempMem, break; } + case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: + { + const VkPipelineLibraryCreateInfoKHR *in = (const VkPipelineLibraryCreateInfoKHR *)nextInput; + VkPipelineLibraryCreateInfoKHR *out = (VkPipelineLibraryCreateInfoKHR *)tempMem; + + // append immediately so tempMem is incremented + AppendModifiedChainedStruct(tempMem, out, nextChainTail); + + // allocate unwrapped array + VkPipeline *outLibraries = (VkPipeline *)tempMem; + tempMem += sizeof(VkPipeline) * in->libraryCount; + + *out = *in; + + out->pLibraries = outLibraries; + for(uint32_t i = 0; i < in->libraryCount; i++) + outLibraries[i] = Unwrap(in->pLibraries[i]); + + break; + } case VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO: { const VkPipelineRenderingCreateInfo *in = (const VkPipelineRenderingCreateInfo *)nextInput; @@ -2611,6 +2638,10 @@ void CopyNextChainForPatching(const char *structName, byte *&tempMem, VkBaseInSt case VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO: CopyNextChainedStruct(sizeof(VkPipelineLayoutCreateInfo), tempMem, nextInput, nextChainTail); break; + case VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR: + CopyNextChainedStruct(sizeof(VkPipelineLibraryCreateInfoKHR), tempMem, nextInput, + nextChainTail); + break; case VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO: CopyNextChainedStruct(sizeof(VkPipelineRenderingCreateInfo), tempMem, nextInput, nextChainTail); diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index 58da1c1d9..0be0c6942 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -1122,6 +1122,9 @@ SERIALISE_VK_HANDLES(); PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR, \ VkPipelineExecutableInternalRepresentationKHR) \ \ + /* VK_KHR_pipeline_library */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR, VkPipelineLibraryCreateInfoKHR) \ + \ /* VK_KHR_present_id */ \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_PRESENT_ID_KHR, VkPresentIdKHR) \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRESENT_ID_FEATURES_KHR, \ @@ -1413,9 +1416,6 @@ SERIALISE_VK_HANDLES(); PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR) \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_ACCELERATION_STRUCTURE_KHR) \ \ - /* VK_KHR_pipeline_library */ \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR) \ - \ /* VK_KHR_ray_tracing_pipeline */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR) \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_INTERFACE_CREATE_INFO_KHR) \ @@ -5908,6 +5908,23 @@ void Deserialise(const VkPipelineExecutableInternalRepresentationKHR &el) DeserialiseNext(el.pNext); } +template +void DoSerialise(SerialiserType &ser, VkPipelineLibraryCreateInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(libraryCount); + SERIALISE_MEMBER_ARRAY(pLibraries, libraryCount); +} + +template <> +void Deserialise(const VkPipelineLibraryCreateInfoKHR &el) +{ + DeserialiseNext(el.pNext); + delete[] el.pLibraries; +} + template void DoSerialise(SerialiserType &ser, VkPresentIdKHR &el) { @@ -5922,6 +5939,7 @@ template <> void Deserialise(const VkPresentIdKHR &el) { DeserialiseNext(el.pNext); + delete[] el.pPresentIds; } template @@ -10470,6 +10488,7 @@ INSTANTIATE_SERIALISE_TYPE(VkPipelineFragmentShadingRateStateCreateInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkPipelineInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkPipelineInputAssemblyStateCreateInfo); INSTANTIATE_SERIALISE_TYPE(VkPipelineLayoutCreateInfo); +INSTANTIATE_SERIALISE_TYPE(VkPipelineLibraryCreateInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkPipelineMultisampleStateCreateInfo); INSTANTIATE_SERIALISE_TYPE(VkPipelineRasterizationConservativeStateCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkPipelineRasterizationDepthClipStateCreateInfoEXT); diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index 163713d99..d37ba21e2 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -147,7 +147,8 @@ RDOC_CONFIG(bool, Vulkan_GPUReadbackDeviceLocal, true, // Memory functions template <> -VkBindBufferMemoryInfo *WrappedVulkan::UnwrapInfos(const VkBindBufferMemoryInfo *info, uint32_t count) +VkBindBufferMemoryInfo *WrappedVulkan::UnwrapInfos(CaptureState state, + const VkBindBufferMemoryInfo *info, uint32_t count) { VkBindBufferMemoryInfo *ret = GetTempArray(count); @@ -163,7 +164,8 @@ VkBindBufferMemoryInfo *WrappedVulkan::UnwrapInfos(const VkBindBufferMemoryInfo } template <> -VkBindImageMemoryInfo *WrappedVulkan::UnwrapInfos(const VkBindImageMemoryInfo *info, uint32_t count) +VkBindImageMemoryInfo *WrappedVulkan::UnwrapInfos(CaptureState state, + const VkBindImageMemoryInfo *info, uint32_t count) { size_t memSize = sizeof(VkBindImageMemoryInfo) * count; @@ -2704,7 +2706,7 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory2(SerialiserType &ser, VkDevice return false; } - VkBindBufferMemoryInfo *unwrapped = UnwrapInfos(pBindInfos, bindInfoCount); + VkBindBufferMemoryInfo *unwrapped = UnwrapInfos(m_State, pBindInfos, bindInfoCount); ObjDisp(device)->BindBufferMemory2(Unwrap(device), bindInfoCount, unwrapped); for(uint32_t i = 0; i < bindInfoCount; i++) @@ -2754,7 +2756,7 @@ bool WrappedVulkan::Serialise_vkBindBufferMemory2(SerialiserType &ser, VkDevice VkResult WrappedVulkan::vkBindBufferMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindBufferMemoryInfo *pBindInfos) { - VkBindBufferMemoryInfo *unwrapped = UnwrapInfos(pBindInfos, bindInfoCount); + VkBindBufferMemoryInfo *unwrapped = UnwrapInfos(m_State, pBindInfos, bindInfoCount); VkResult ret; SERIALISE_TIME_CALL( @@ -2875,7 +2877,7 @@ bool WrappedVulkan::Serialise_vkBindImageMemory2(SerialiserType &ser, VkDevice d imgInfo.linear ? VulkanCreationInfo::Memory::Linear : VulkanCreationInfo::Memory::Tiled); } - VkBindImageMemoryInfo *unwrapped = UnwrapInfos(pBindInfos, bindInfoCount); + VkBindImageMemoryInfo *unwrapped = UnwrapInfos(m_State, pBindInfos, bindInfoCount); ObjDisp(device)->BindImageMemory2(Unwrap(device), bindInfoCount, unwrapped); } @@ -2885,7 +2887,7 @@ bool WrappedVulkan::Serialise_vkBindImageMemory2(SerialiserType &ser, VkDevice d VkResult WrappedVulkan::vkBindImageMemory2(VkDevice device, uint32_t bindInfoCount, const VkBindImageMemoryInfo *pBindInfos) { - VkBindImageMemoryInfo *unwrapped = UnwrapInfos(pBindInfos, bindInfoCount); + VkBindImageMemoryInfo *unwrapped = UnwrapInfos(m_State, pBindInfos, bindInfoCount); VkResult ret; SERIALISE_TIME_CALL( ret = ObjDisp(device)->BindImageMemory2(Unwrap(device), bindInfoCount, unwrapped)); diff --git a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp index 3c759db24..2200378eb 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp @@ -26,7 +26,8 @@ #include "driver/shaders/spirv/spirv_reflect.h" template <> -VkComputePipelineCreateInfo *WrappedVulkan::UnwrapInfos(const VkComputePipelineCreateInfo *info, +VkComputePipelineCreateInfo *WrappedVulkan::UnwrapInfos(CaptureState state, + const VkComputePipelineCreateInfo *info, uint32_t count) { VkComputePipelineCreateInfo *unwrapped = GetTempArray(count); @@ -44,23 +45,29 @@ VkComputePipelineCreateInfo *WrappedVulkan::UnwrapInfos(const VkComputePipelineC } template <> -VkGraphicsPipelineCreateInfo *WrappedVulkan::UnwrapInfos(const VkGraphicsPipelineCreateInfo *info, +VkGraphicsPipelineCreateInfo *WrappedVulkan::UnwrapInfos(CaptureState state, + const VkGraphicsPipelineCreateInfo *info, uint32_t count) { // conservatively request memory for 5 stages on each pipeline // (worst case - can't have compute stage). Avoids needing to count - byte *unwrapped = GetTempMemory(sizeof(VkGraphicsPipelineCreateInfo) * count + - sizeof(VkPipelineShaderStageCreateInfo) * count * 5); + size_t memSize = sizeof(VkGraphicsPipelineCreateInfo) * count; + for(uint32_t i = 0; i < count; i++) + { + memSize += sizeof(VkPipelineShaderStageCreateInfo) * info[i].stageCount; + memSize += GetNextPatchSize(info[i].pNext); + } + + byte *tempMem = GetTempMemory(memSize); // keep pipelines first in the memory, then the stages - VkGraphicsPipelineCreateInfo *unwrappedInfos = (VkGraphicsPipelineCreateInfo *)unwrapped; - VkPipelineShaderStageCreateInfo *nextUnwrappedStages = - (VkPipelineShaderStageCreateInfo *)(unwrappedInfos + count); + VkGraphicsPipelineCreateInfo *unwrappedInfos = (VkGraphicsPipelineCreateInfo *)tempMem; + tempMem = (byte *)(unwrappedInfos + count); for(uint32_t i = 0; i < count; i++) { - VkPipelineShaderStageCreateInfo *unwrappedStages = nextUnwrappedStages; - nextUnwrappedStages += info[i].stageCount; + VkPipelineShaderStageCreateInfo *unwrappedStages = (VkPipelineShaderStageCreateInfo *)tempMem; + tempMem = (byte *)(unwrappedStages + info[i].stageCount); for(uint32_t j = 0; j < info[i].stageCount; j++) { unwrappedStages[j] = info[i].pStages[j]; @@ -73,6 +80,9 @@ VkGraphicsPipelineCreateInfo *WrappedVulkan::UnwrapInfos(const VkGraphicsPipelin unwrappedInfos[i].renderPass = Unwrap(unwrappedInfos[i].renderPass); if(unwrappedInfos[i].flags & VK_PIPELINE_CREATE_DERIVATIVE_BIT) unwrappedInfos[i].basePipelineHandle = Unwrap(unwrappedInfos[i].basePipelineHandle); + + UnwrapNextChain(state, "VkGraphicsPipelineCreateInfo", tempMem, + (VkBaseInStructure *)&unwrappedInfos[i]); } return unwrappedInfos; @@ -433,7 +443,7 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines( // valid CreateInfo.flags &= ~VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT; - VkGraphicsPipelineCreateInfo *unwrapped = UnwrapInfos(&CreateInfo, 1); + VkGraphicsPipelineCreateInfo *unwrapped = UnwrapInfos(m_State, &CreateInfo, 1); VkResult ret = ObjDisp(device)->CreateGraphicsPipelines(Unwrap(device), Unwrap(pipelineCache), 1, unwrapped, NULL, &pipe); @@ -474,7 +484,7 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines( m_CreationInfo.m_RenderPass[renderPassID].loadRPs[CreateInfo.subpass]; CreateInfo.subpass = 0; - unwrapped = UnwrapInfos(&CreateInfo, 1); + unwrapped = UnwrapInfos(m_State, &CreateInfo, 1); ret = ObjDisp(device)->CreateGraphicsPipelines(Unwrap(device), Unwrap(pipelineCache), 1, unwrapped, NULL, &pipeInfo.subpass0pipe); RDCASSERTEQUAL(ret, VK_SUCCESS); @@ -514,7 +524,7 @@ VkResult WrappedVulkan::vkCreateGraphicsPipelines(VkDevice device, VkPipelineCac const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) { - VkGraphicsPipelineCreateInfo *unwrapped = UnwrapInfos(pCreateInfos, count); + VkGraphicsPipelineCreateInfo *unwrapped = UnwrapInfos(m_State, pCreateInfos, count); VkResult ret; // to be extra sure just in case the driver doesn't, set pipelines to VK_NULL_HANDLE first. @@ -610,6 +620,18 @@ VkResult WrappedVulkan::vkCreateGraphicsPipelines(VkDevice device, VkPipelineCac VkResourceRecord *modulerecord = GetRecord(pCreateInfos[i].pStages[s].module); record->AddParent(modulerecord); } + + VkPipelineLibraryCreateInfoKHR *libraryInfo = + (VkPipelineLibraryCreateInfoKHR *)FindNextStruct( + &pCreateInfos[i], VK_STRUCTURE_TYPE_PIPELINE_LIBRARY_CREATE_INFO_KHR); + + if(libraryInfo) + { + for(uint32_t l = 0; l < libraryInfo->libraryCount; l++) + { + record->AddParent(GetRecord(libraryInfo->pLibraries[l])); + } + } } else { @@ -656,7 +678,7 @@ bool WrappedVulkan::Serialise_vkCreateComputePipelines(SerialiserType &ser, VkDe VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR); } - VkComputePipelineCreateInfo *unwrapped = UnwrapInfos(&CreateInfo, 1); + VkComputePipelineCreateInfo *unwrapped = UnwrapInfos(m_State, &CreateInfo, 1); VkResult ret = ObjDisp(device)->CreateComputePipelines(Unwrap(device), Unwrap(pipelineCache), 1, unwrapped, NULL, &pipe); @@ -714,7 +736,7 @@ VkResult WrappedVulkan::vkCreateComputePipelines(VkDevice device, VkPipelineCach VkResult ret; SERIALISE_TIME_CALL(ret = ObjDisp(device)->CreateComputePipelines( Unwrap(device), Unwrap(pipelineCache), count, - UnwrapInfos(pCreateInfos, count), pAllocator, pPipelines)); + UnwrapInfos(m_State, pCreateInfos, count), pAllocator, pPipelines)); if(ret == VK_SUCCESS) {