From 0522a636ad522dbe79068210c7fa3377161a8360 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 15 Aug 2019 13:05:06 +0100 Subject: [PATCH] Add support for VK_KHR_pipeline_executable_properties --- renderdoc/driver/vulkan/vk_common.h | 20 +- renderdoc/driver/vulkan/vk_core.cpp | 4 + renderdoc/driver/vulkan/vk_core.h | 17 ++ renderdoc/driver/vulkan/vk_hookset_defs.h | 20 +- renderdoc/driver/vulkan/vk_next_chains.cpp | 17 +- renderdoc/driver/vulkan/vk_replay.cpp | 237 +++++++++++++++++- renderdoc/driver/vulkan/vk_replay.h | 16 ++ renderdoc/driver/vulkan/vk_serialise.cpp | 148 ++++++++++- renderdoc/driver/vulkan/vk_stringise.cpp | 13 + .../vulkan/wrappers/vk_device_funcs.cpp | 65 +++++ .../driver/vulkan/wrappers/vk_get_funcs.cpp | 31 +++ .../vulkan/wrappers/vk_shader_funcs.cpp | 14 ++ 12 files changed, 574 insertions(+), 28 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index ad14a86fa..1819ae25e 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -793,6 +793,7 @@ DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceMemoryProperties2); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceMultiviewFeatures); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceMultiviewProperties); DECLARE_REFLECTION_STRUCT(VkPhysicalDevicePCIBusInfoPropertiesEXT); +DECLARE_REFLECTION_STRUCT(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR); DECLARE_REFLECTION_STRUCT(VkPhysicalDevicePointClippingProperties); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceProperties2); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceProtectedMemoryFeatures); @@ -829,6 +830,11 @@ DECLARE_REFLECTION_STRUCT(VkPipelineCreationFeedbackCreateInfoEXT); DECLARE_REFLECTION_STRUCT(VkPipelineDepthStencilStateCreateInfo); DECLARE_REFLECTION_STRUCT(VkPipelineDiscardRectangleStateCreateInfoEXT); DECLARE_REFLECTION_STRUCT(VkPipelineDynamicStateCreateInfo); +DECLARE_REFLECTION_STRUCT(VkPipelineExecutableInfoKHR); +DECLARE_REFLECTION_STRUCT(VkPipelineExecutableInternalRepresentationKHR); +DECLARE_REFLECTION_STRUCT(VkPipelineExecutablePropertiesKHR); +DECLARE_REFLECTION_STRUCT(VkPipelineExecutableStatisticKHR); +DECLARE_REFLECTION_STRUCT(VkPipelineInfoKHR); DECLARE_REFLECTION_STRUCT(VkPipelineInputAssemblyStateCreateInfo); DECLARE_REFLECTION_STRUCT(VkPipelineLayoutCreateInfo); DECLARE_REFLECTION_STRUCT(VkPipelineMultisampleStateCreateInfo); @@ -1039,6 +1045,7 @@ DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceMemoryProperties2); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceMultiviewFeatures); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceMultiviewProperties); DECLARE_DESERIALISE_TYPE(VkPhysicalDevicePCIBusInfoPropertiesEXT); +DECLARE_DESERIALISE_TYPE(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR); DECLARE_DESERIALISE_TYPE(VkPhysicalDevicePointClippingProperties); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceProperties2); DECLARE_DESERIALISE_TYPE(VkPhysicalDeviceProtectedMemoryFeatures); @@ -1075,6 +1082,11 @@ DECLARE_DESERIALISE_TYPE(VkPipelineCreationFeedbackCreateInfoEXT); DECLARE_DESERIALISE_TYPE(VkPipelineDepthStencilStateCreateInfo); DECLARE_DESERIALISE_TYPE(VkPipelineDiscardRectangleStateCreateInfoEXT); DECLARE_DESERIALISE_TYPE(VkPipelineDynamicStateCreateInfo); +DECLARE_DESERIALISE_TYPE(VkPipelineExecutableInfoKHR); +DECLARE_DESERIALISE_TYPE(VkPipelineExecutableInternalRepresentationKHR); +DECLARE_DESERIALISE_TYPE(VkPipelineExecutablePropertiesKHR); +DECLARE_DESERIALISE_TYPE(VkPipelineExecutableStatisticKHR); +DECLARE_DESERIALISE_TYPE(VkPipelineInfoKHR); DECLARE_DESERIALISE_TYPE(VkPipelineInputAssemblyStateCreateInfo); DECLARE_DESERIALISE_TYPE(VkPipelineLayoutCreateInfo); DECLARE_DESERIALISE_TYPE(VkPipelineMultisampleStateCreateInfo); @@ -1183,8 +1195,9 @@ DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceLimits); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceMemoryProperties); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceProperties); DECLARE_REFLECTION_STRUCT(VkPhysicalDeviceSparseProperties); -DECLARE_REFLECTION_STRUCT(VkPipelineCreationFeedbackEXT); DECLARE_REFLECTION_STRUCT(VkPipelineColorBlendAttachmentState); +DECLARE_REFLECTION_STRUCT(VkPipelineCreationFeedbackEXT); +DECLARE_REFLECTION_STRUCT(VkPipelineExecutableStatisticValueKHR); DECLARE_REFLECTION_STRUCT(VkPresentRegionKHR); DECLARE_REFLECTION_STRUCT(VkPushConstantRange); DECLARE_REFLECTION_STRUCT(VkQueueFamilyProperties); @@ -1333,6 +1346,8 @@ DECLARE_REFLECTION_ENUM(VkPhysicalDeviceType); DECLARE_REFLECTION_ENUM(VkPipelineBindPoint); DECLARE_REFLECTION_ENUM(VkPipelineCreateFlagBits); DECLARE_REFLECTION_ENUM(VkPipelineCreationFeedbackFlagBitsEXT); +DECLARE_REFLECTION_ENUM(VkPipelineExecutableStatisticFormatKHR); +DECLARE_REFLECTION_ENUM(VkPipelineShaderStageCreateFlagBits); DECLARE_REFLECTION_ENUM(VkPipelineStageFlagBits); DECLARE_REFLECTION_ENUM(VkPointClippingBehavior); DECLARE_REFLECTION_ENUM(VkPolygonMode); @@ -1344,7 +1359,6 @@ DECLARE_REFLECTION_ENUM(VkQueryResultFlagBits); DECLARE_REFLECTION_ENUM(VkQueryType); DECLARE_REFLECTION_ENUM(VkQueueFlagBits); DECLARE_REFLECTION_ENUM(VkQueueGlobalPriorityEXT); -DECLARE_REFLECTION_ENUM(VkPipelineShaderStageCreateFlagBits); DECLARE_REFLECTION_ENUM(VkRenderPassCreateFlagBits); DECLARE_REFLECTION_ENUM(VkResolveModeFlagBitsKHR); DECLARE_REFLECTION_ENUM(VkResult); @@ -1374,8 +1388,8 @@ DECLARE_REFLECTION_ENUM(VkSwapchainCreateFlagBitsKHR); DECLARE_REFLECTION_ENUM(VkTessellationDomainOrigin); DECLARE_REFLECTION_ENUM(VkTimeDomainEXT); DECLARE_REFLECTION_ENUM(VkValidationCheckEXT); -DECLARE_REFLECTION_ENUM(VkValidationFeatureEnableEXT); DECLARE_REFLECTION_ENUM(VkValidationFeatureDisableEXT); +DECLARE_REFLECTION_ENUM(VkValidationFeatureEnableEXT); DECLARE_REFLECTION_ENUM(VkVertexInputRate); // win32 only enums diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index c6f18688a..493e3bd0d 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -936,6 +936,10 @@ static const VkExtensionProperties supportedExtensions[] = { { VK_KHR_MULTIVIEW_EXTENSION_NAME, VK_KHR_MULTIVIEW_SPEC_VERSION, }, + { + VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME, + VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_SPEC_VERSION, + }, { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, VK_KHR_PUSH_DESCRIPTOR_SPEC_VERSION, }, diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 2223914b6..84e0083ae 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -2104,8 +2104,25 @@ public: IMPLEMENT_FUNCTION_SERIALISED(VkResult, vkReleaseFullScreenExclusiveModeEXT, VkDevice device, VkSwapchainKHR swapchain); + // VK_EXT_headless_surface + VkResult vkCreateHeadlessSurfaceEXT(VkInstance instance, const VkHeadlessSurfaceCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface); + + // VK_KHR_pipeline_executable_properties + + VkResult vkGetPipelineExecutablePropertiesKHR(VkDevice device, + const VkPipelineInfoKHR *pPipelineInfo, + uint32_t *pExecutableCount, + VkPipelineExecutablePropertiesKHR *pProperties); + VkResult vkGetPipelineExecutableStatisticsKHR(VkDevice device, + const VkPipelineExecutableInfoKHR *pExecutableInfo, + uint32_t *pStatisticCount, + VkPipelineExecutableStatisticKHR *pStatistics); + VkResult vkGetPipelineExecutableInternalRepresentationsKHR( + VkDevice device, const VkPipelineExecutableInfoKHR *pExecutableInfo, + uint32_t *pInternalRepresentationCount, + VkPipelineExecutableInternalRepresentationKHR *pInternalRepresentations); }; diff --git a/renderdoc/driver/vulkan/vk_hookset_defs.h b/renderdoc/driver/vulkan/vk_hookset_defs.h index e40126f28..b093cbf19 100644 --- a/renderdoc/driver/vulkan/vk_hookset_defs.h +++ b/renderdoc/driver/vulkan/vk_hookset_defs.h @@ -387,7 +387,8 @@ DeclExt(EXT_buffer_device_address); \ DeclExt(EXT_full_screen_exclusive); \ DeclExt(EXT_hdr_metadata); \ - DeclExt(AMD_display_native_hdr); + DeclExt(AMD_display_native_hdr); \ + DeclExt(KHR_pipeline_executable_properties); // for simplicity and since the check itself is platform agnostic, // these aren't protected in platform defines @@ -465,7 +466,8 @@ CheckExt(EXT_host_query_reset, VKXX); \ CheckExt(EXT_buffer_device_address, VKXX); \ CheckExt(EXT_hdr_metadata, VKXX); \ - CheckExt(AMD_display_native_hdr, VKXX); + CheckExt(AMD_display_native_hdr, VKXX); \ + CheckExt(KHR_pipeline_executable_properties, VKXX); #define HookInitVulkanInstanceExts() \ HookInitExtension(KHR_surface, DestroySurfaceKHR); \ @@ -604,6 +606,10 @@ HookInitExtension(EXT_buffer_device_address, GetBufferDeviceAddressEXT); \ HookInitExtension(EXT_hdr_metadata, SetHdrMetadataEXT); \ HookInitExtension(AMD_display_native_hdr, SetLocalDimmingAMD); \ + HookInitExtension(KHR_pipeline_executable_properties, GetPipelineExecutablePropertiesKHR); \ + HookInitExtension(KHR_pipeline_executable_properties, GetPipelineExecutableStatisticsKHR); \ + HookInitExtension(KHR_pipeline_executable_properties, \ + GetPipelineExecutableInternalRepresentationsKHR); \ HookInitDevice_PlatformSpecific() #define DefineHooks() \ @@ -1183,4 +1189,14 @@ HookDefine4(VkResult, vkCreateHeadlessSurfaceEXT, VkInstance, instance, \ const VkHeadlessSurfaceCreateInfoEXT *, pCreateInfo, const VkAllocationCallbacks *, \ pAllocator, VkSurfaceKHR *, pSurface); \ + HookDefine4(VkResult, vkGetPipelineExecutablePropertiesKHR, VkDevice, device, \ + const VkPipelineInfoKHR *, pPipelineInfo, uint32_t *, pExecutableCount, \ + VkPipelineExecutablePropertiesKHR *, pProperties); \ + HookDefine4(VkResult, vkGetPipelineExecutableStatisticsKHR, VkDevice, device, \ + const VkPipelineExecutableInfoKHR *, pExecutableInfo, uint32_t *, pStatisticCount, \ + VkPipelineExecutableStatisticKHR *, pStatistics); \ + HookDefine4(VkResult, vkGetPipelineExecutableInternalRepresentationsKHR, VkDevice, device, \ + const VkPipelineExecutableInfoKHR *, pExecutableInfo, uint32_t *, \ + pInternalRepresentationCount, VkPipelineExecutableInternalRepresentationKHR *, \ + pInternalRepresentations); \ HookDefine_PlatformSpecific() diff --git a/renderdoc/driver/vulkan/vk_next_chains.cpp b/renderdoc/driver/vulkan/vk_next_chains.cpp index 2809e657b..39d95791e 100644 --- a/renderdoc/driver/vulkan/vk_next_chains.cpp +++ b/renderdoc/driver/vulkan/vk_next_chains.cpp @@ -224,6 +224,8 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, VkPhysicalDeviceMultiviewProperties); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT, \ VkPhysicalDevicePCIBusInfoPropertiesEXT); \ + COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR, \ + VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR) \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES, \ VkPhysicalDevicePointClippingProperties); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, VkPhysicalDeviceProperties2); \ @@ -292,6 +294,11 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, VkPipelineDiscardRectangleStateCreateInfoEXT); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, \ VkPipelineDynamicStateCreateInfo); \ + COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR, \ + VkPipelineExecutablePropertiesKHR) \ + COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR, VkPipelineExecutableStatisticKHR) \ + COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR, \ + VkPipelineExecutableInternalRepresentationKHR) \ COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, \ VkPipelineInputAssemblyStateCreateInfo); \ COPY_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, \ @@ -427,6 +434,10 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, UnwrapInPlace(out->memory)); \ UNWRAP_STRUCT(VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, VkMemoryDedicatedAllocateInfo, \ UnwrapInPlace(out->buffer), UnwrapInPlace(out->image)); \ + UNWRAP_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, VkPipelineInfoKHR, \ + UnwrapInPlace(out->pipeline)); \ + UNWRAP_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR, VkPipelineExecutableInfoKHR, \ + UnwrapInPlace(out->pipeline)); \ UNWRAP_STRUCT(VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, VkRenderPassBeginInfo, \ UnwrapInPlace(out->renderPass), UnwrapInPlace(out->framebuffer)); \ UNWRAP_STRUCT(VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, VkSamplerYcbcrConversionInfo, \ @@ -535,7 +546,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_FEATURES_NV: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_NV: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PER_VIEW_ATTRIBUTES_PROPERTIES_NVX: \ - case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_PROPERTIES_NV: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_REPRESENTATIVE_FRAGMENT_TEST_FEATURES_NV: \ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_CORE_PROPERTIES_2_AMD: \ @@ -550,11 +560,6 @@ static void AppendModifiedChainedStruct(byte *&tempMem, VkStruct *outputStruct, case VK_STRUCTURE_TYPE_PIPELINE_COVERAGE_MODULATION_STATE_CREATE_INFO_NV: \ 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_EXECUTABLE_INFO_KHR: \ - case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR: \ - case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR: \ - case VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR: \ - case VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR: \ case VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_LINE_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: \ diff --git a/renderdoc/driver/vulkan/vk_replay.cpp b/renderdoc/driver/vulkan/vk_replay.cpp index 0f84cc460..eb72ba4ad 100644 --- a/renderdoc/driver/vulkan/vk_replay.cpp +++ b/renderdoc/driver/vulkan/vk_replay.cpp @@ -40,7 +40,8 @@ #include "data/glsl/glsl_ubos_cpp.h" static const char *SPIRVDisassemblyTarget = "SPIR-V (RenderDoc)"; -static const char *LiveDriverDisassemblyTarget = "Live driver disassembly"; +static const char *AMDShaderInfoTarget = "AMD_shader_info disassembly"; +static const char *KHRExecutablePropertiesTarget = "KHR_pipeline_executable_properties"; VulkanReplay::VulkanReplay() { @@ -350,11 +351,11 @@ std::vector VulkanReplay::GetDisassemblyTargets() { std::vector ret; - VkDevice dev = m_pDriver->GetDev(); - const VkDevDispatchTable *vt = ObjDisp(dev); + if(m_pDriver->GetExtensions(NULL).ext_AMD_shader_info) + ret.push_back(AMDShaderInfoTarget); - if(vt->GetShaderInfoAMD) - ret.push_back(LiveDriverDisassemblyTarget); + if(m_pDriver->GetExtensions(NULL).ext_KHR_pipeline_executable_properties) + ret.push_back(KHRExecutablePropertiesTarget); // default is always first ret.insert(ret.begin(), SPIRVDisassemblyTarget); @@ -365,6 +366,79 @@ std::vector VulkanReplay::GetDisassemblyTargets() return ret; } +void VulkanReplay::CachePipelineExecutables(ResourceId pipeline) +{ + auto it = m_PipelineExecutables.insert({pipeline, rdcarray()}); + + if(!it.second) + return; + + rdcarray &data = it.first->second; + + VkPipeline pipe = m_pDriver->GetResourceManager()->GetLiveHandle(pipeline); + + VkPipelineInfoKHR pipeInfo = { + VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, NULL, Unwrap(pipe), + }; + + VkDevice dev = m_pDriver->GetDev(); + const VkDevDispatchTable *vt = ObjDisp(dev); + + uint32_t execCount = 0; + vt->GetPipelineExecutablePropertiesKHR(Unwrap(dev), &pipeInfo, &execCount, NULL); + + rdcarray executables; + executables.resize(execCount); + data.resize(execCount); + vt->GetPipelineExecutablePropertiesKHR(Unwrap(dev), &pipeInfo, &execCount, executables.data()); + + for(uint32_t i = 0; i < execCount; i++) + { + const VkPipelineExecutablePropertiesKHR &exec = executables[i]; + PipelineExecutables &out = data[i]; + out.name = exec.name; + out.description = exec.description; + out.stages = exec.stages; + out.subgroupSize = exec.subgroupSize; + rdcarray &stats = out.statistics; + rdcarray &irs = out.representations; + + VkPipelineExecutableInfoKHR pipeExecInfo = { + VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, NULL, Unwrap(pipe), i, + }; + + // enumerate statistics + uint32_t statCount = 0; + vt->GetPipelineExecutableStatisticsKHR(Unwrap(dev), &pipeExecInfo, &statCount, NULL); + + stats.resize(statCount); + for(uint32_t s = 0; s < statCount; s++) + stats[s].sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR; + vt->GetPipelineExecutableStatisticsKHR(Unwrap(dev), &pipeExecInfo, &statCount, stats.data()); + + // enumerate internal representations + uint32_t irCount = 0; + vt->GetPipelineExecutableInternalRepresentationsKHR(Unwrap(dev), &pipeExecInfo, &irCount, NULL); + + irs.resize(irCount); + for(uint32_t ir = 0; ir < irCount; ir++) + irs[ir].sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR; + vt->GetPipelineExecutableInternalRepresentationsKHR(Unwrap(dev), &pipeExecInfo, &irCount, + irs.data()); + + // need to now allocate space, and try again + out.irbytes.resize(irCount); + for(uint32_t ir = 0; ir < irCount; ir++) + { + out.irbytes[ir].resize(irs[ir].dataSize); + irs[ir].pData = out.irbytes[ir].data(); + } + + vt->GetPipelineExecutableInternalRepresentationsKHR(Unwrap(dev), &pipeExecInfo, &irCount, + irs.data()); + } +} + std::string VulkanReplay::DisassembleShader(ResourceId pipeline, const ShaderReflection *refl, const std::string &target) { @@ -387,12 +461,12 @@ std::string VulkanReplay::DisassembleShader(ResourceId pipeline, const ShaderRef VkDevice dev = m_pDriver->GetDev(); const VkDevDispatchTable *vt = ObjDisp(dev); - if(target == LiveDriverDisassemblyTarget && vt->GetShaderInfoAMD) + if(target == AMDShaderInfoTarget && vt->GetShaderInfoAMD) { if(pipeline == ResourceId()) { - return "; No pipeline specified, live driver disassembly is not available\n" - "; Shader must be disassembled with a specific pipeline to get live driver assembly."; + return "; No pipeline specified, VK_AMD_shader_info disassembly is not available\n" + "; Shader must be disassembled with a specific pipeline."; } VkPipeline pipe = m_pDriver->GetResourceManager()->GetLiveHandle(pipeline); @@ -412,6 +486,139 @@ std::string VulkanReplay::DisassembleShader(ResourceId pipeline, const ShaderRef return disasm; } + if(target == KHRExecutablePropertiesTarget && vt->GetPipelineExecutablePropertiesKHR) + { + if(pipeline == ResourceId()) + { + return "; No pipeline specified, VK_KHR_pipeline_executable_properties disassembly is not " + "available\n" + "; Shader must be disassembled with a specific pipeline."; + } + + CachePipelineExecutables(pipeline); + + VkShaderStageFlagBits stageBit = + VkShaderStageFlagBits(1 << it->second.m_Reflections[refl->entryPoint.c_str()].stageIndex); + + const rdcarray &executables = m_PipelineExecutables[pipeline]; + + std::string disasm; + + for(const PipelineExecutables &exec : executables) + { + // if this executable is associated with our stage, definitely include it. If this executable + // is associated with *no* stages, then also include it (since we don't know what it + // corresponds to) + if((exec.stages & stageBit) || exec.stages == 0) + { + disasm += "======== " + exec.name + " ========\n\n"; + disasm += exec.description + "\n\n"; + + // statistics first + disasm += StringFormat::Fmt( + "==== Statistics ====\n\n" + "Subgroup Size: %u" + " // the subgroup size with which this executable is dispatched.\n", + exec.subgroupSize); + + for(const VkPipelineExecutableStatisticKHR &stat : exec.statistics) + { + std::string value; + + switch(stat.format) + { + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR: + value = stat.value.b32 ? "true" : "false"; + break; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR: + value = ToStr(stat.value.i64); + break; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR: + value = ToStr(stat.value.u64); + break; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR: + value = ToStr(stat.value.f64); + break; + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_RANGE_SIZE_KHR: + case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_MAX_ENUM_KHR: value = "???"; break; + } + + disasm += + StringFormat::Fmt("%s: %s // %s\n", stat.name, value.c_str(), stat.description); + } + + // then IRs + + if(!exec.representations.empty()) + disasm += "\n\n==== Internal Representations ====\n\n"; + + for(const VkPipelineExecutableInternalRepresentationKHR &ir : exec.representations) + { + disasm += "---- " + std::string(ir.name) + " ----\n\n"; + disasm += "; " + std::string(ir.description) + "\n\n"; + if(ir.isText) + { + char *str = (char *)ir.pData; + // should already be NULL terminated but let's be sure + str[ir.dataSize - 1] = 0; + disasm += str; + } + else + { + // canonical hexdump display + size_t bytesRemaining = ir.dataSize; + size_t offset = 0; + const byte *src = (const byte *)ir.pData; + while(bytesRemaining > 0) + { + uint8_t row[16]; + const size_t copySize = RDCMIN(sizeof(row), bytesRemaining); + + memcpy(row, src + offset, copySize); + + disasm += StringFormat::Fmt("%08zx ", offset); + for(size_t b = 0; b < 16; b++) + { + if(b < bytesRemaining) + disasm += StringFormat::Fmt("%02hhx ", row[b]); + else + disasm += " "; + + if(b == 7 || b == 15) + disasm += " "; + } + + disasm += "|"; + + for(size_t b = 0; b < 16; b++) + { + if(b < bytesRemaining) + { + char c = (char)row[b]; + if(isprint(c)) + disasm.push_back(c); + else + disasm.push_back('.'); + } + } + + disasm += "|"; + + disasm += "\n"; + + offset += copySize; + bytesRemaining -= copySize; + } + + disasm += StringFormat::Fmt("%08zx", offset); + } + } + } + } + + return disasm; + } + return StringFormat::Fmt("; Invalid disassembly target %s", target.c_str()); } @@ -3633,6 +3840,13 @@ void VulkanReplay::ReplaceResource(ResourceId from, ResourceId to) sh.module = dstShaderModule; } + // if we have pipeline executable properties, capture the data + if(m_pDriver->GetExtensions(NULL).ext_KHR_pipeline_executable_properties) + { + pipeCreateInfo.flags |= (VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR | + VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR); + } + // create the new graphics pipeline VkResult vkr = m_pDriver->vkCreateGraphicsPipelines(dev, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL, &pipe); @@ -3648,6 +3862,13 @@ void VulkanReplay::ReplaceResource(ResourceId from, ResourceId to) RDCASSERT(sh.module == srcShaderModule); sh.module = dstShaderModule; + // if we have pipeline executable properties, capture the data + if(m_pDriver->GetExtensions(NULL).ext_KHR_pipeline_executable_properties) + { + pipeCreateInfo.flags |= (VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR | + VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR); + } + // create the new compute pipeline VkResult vkr = m_pDriver->vkCreateComputePipelines(dev, VK_NULL_HANDLE, 1, &pipeCreateInfo, NULL, &pipe); diff --git a/renderdoc/driver/vulkan/vk_replay.h b/renderdoc/driver/vulkan/vk_replay.h index fe5f399e2..5b8b0272f 100644 --- a/renderdoc/driver/vulkan/vk_replay.h +++ b/renderdoc/driver/vulkan/vk_replay.h @@ -676,6 +676,22 @@ private: DriverInformation m_DriverInfo; + struct PipelineExecutables + { + VkShaderStageFlags stages; + rdcstr name, description; + uint32_t subgroupSize; + rdcarray statistics; + rdcarray representations; + + // internal data, pointed to from representations above + rdcarray irbytes; + }; + + std::map> m_PipelineExecutables; + + void CachePipelineExecutables(ResourceId pipeline); + void CreateTexImageView(VkImage liveIm, const VulkanCreationInfo::Image &iminfo, CompType typeHint, TextureDisplayViews &views); diff --git a/renderdoc/driver/vulkan/vk_serialise.cpp b/renderdoc/driver/vulkan/vk_serialise.cpp index b44cc45ad..d12480829 100644 --- a/renderdoc/driver/vulkan/vk_serialise.cpp +++ b/renderdoc/driver/vulkan/vk_serialise.cpp @@ -809,6 +809,17 @@ SERIALISE_VK_HANDLES(); PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES, \ VkPhysicalDeviceMultiviewProperties) \ \ + /* VK_KHR_pipeline_executable_properties */ \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR, \ + VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR, VkPipelineInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR, \ + VkPipelineExecutablePropertiesKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR, VkPipelineExecutableInfoKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR, VkPipelineExecutableStatisticKHR) \ + PNEXT_STRUCT(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR, \ + VkPipelineExecutableInternalRepresentationKHR) \ + \ /* VK_KHR_push_descriptor */ \ PNEXT_STRUCT(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR, \ VkPhysicalDevicePushDescriptorPropertiesKHR) \ @@ -969,14 +980,6 @@ SERIALISE_VK_HANDLES(); /* VK_INTEL_shader_integer_functions2 */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL) \ \ - /* VK_KHR_pipeline_executable_properties */ \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR) \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR) \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR) \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR) \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR) \ - PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR) \ - \ /* VK_NV_clip_space_w_scaling */ \ PNEXT_UNSUPPORTED(VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_W_SCALING_STATE_CREATE_INFO_NV) \ \ @@ -4202,6 +4205,126 @@ void Deserialise(const VkPhysicalDeviceMultiviewProperties &el) DeserialiseNext(el.pNext); } +template +void DoSerialise(SerialiserType &ser, VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(pipelineExecutableInfo); +} + +template <> +void Deserialise(const VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkPipelineInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(pipeline); +} + +template <> +void Deserialise(const VkPipelineInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkPipelineExecutablePropertiesKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER_VKFLAGS(VkShaderStageFlags, stages); + SERIALISE_MEMBER(name); + SERIALISE_MEMBER(description); + SERIALISE_MEMBER(subgroupSize); +} + +template <> +void Deserialise(const VkPipelineExecutablePropertiesKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkPipelineExecutableInfoKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(pipeline); + SERIALISE_MEMBER(executableIndex); +} + +template <> +void Deserialise(const VkPipelineExecutableInfoKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkPipelineExecutableStatisticValueKHR &el) +{ + SERIALISE_MEMBER(b32); + SERIALISE_MEMBER(i64); + SERIALISE_MEMBER(u64); + SERIALISE_MEMBER(f64); +} + +template +void DoSerialise(SerialiserType &ser, VkPipelineExecutableStatisticKHR &el) +{ + RDCASSERT(ser.IsReading() || el.sType == VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(name); + SERIALISE_MEMBER(description); + SERIALISE_MEMBER(format); + SERIALISE_MEMBER(value); +} + +template <> +void Deserialise(const VkPipelineExecutableStatisticKHR &el) +{ + DeserialiseNext(el.pNext); +} + +template +void DoSerialise(SerialiserType &ser, VkPipelineExecutableInternalRepresentationKHR &el) +{ + RDCASSERT(ser.IsReading() || + el.sType == VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR); + SerialiseNext(ser, el.sType, el.pNext); + + SERIALISE_MEMBER(name); + SERIALISE_MEMBER(description); + SERIALISE_MEMBER(isText); + + // don't serialise size_t, otherwise capture/replay between different bit-ness won't work + { + uint64_t dataSize = el.dataSize; + ser.Serialise("dataSize"_lit, dataSize); + if(ser.IsReading()) + el.dataSize = (size_t)dataSize; + } + + SERIALISE_MEMBER_ARRAY(pData, dataSize); +} + +template <> +void Deserialise(const VkPipelineExecutableInternalRepresentationKHR &el) +{ + DeserialiseNext(el.pNext); +} + template void DoSerialise(SerialiserType &ser, VkPhysicalDevicePushDescriptorPropertiesKHR &el) { @@ -7148,6 +7271,7 @@ INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceMemoryProperties2); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceMultiviewFeatures); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceMultiviewProperties); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDevicePCIBusInfoPropertiesEXT); +INSTANTIATE_SERIALISE_TYPE(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDevicePointClippingProperties); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceProperties2); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceProtectedMemoryFeatures); @@ -7182,6 +7306,11 @@ INSTANTIATE_SERIALISE_TYPE(VkPipelineCreationFeedbackCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkPipelineDepthStencilStateCreateInfo); INSTANTIATE_SERIALISE_TYPE(VkPipelineDiscardRectangleStateCreateInfoEXT); INSTANTIATE_SERIALISE_TYPE(VkPipelineDynamicStateCreateInfo); +INSTANTIATE_SERIALISE_TYPE(VkPipelineExecutableInfoKHR); +INSTANTIATE_SERIALISE_TYPE(VkPipelineExecutableInternalRepresentationKHR); +INSTANTIATE_SERIALISE_TYPE(VkPipelineExecutablePropertiesKHR); +INSTANTIATE_SERIALISE_TYPE(VkPipelineExecutableStatisticKHR); +INSTANTIATE_SERIALISE_TYPE(VkPipelineInfoKHR); INSTANTIATE_SERIALISE_TYPE(VkPipelineInputAssemblyStateCreateInfo); INSTANTIATE_SERIALISE_TYPE(VkPipelineLayoutCreateInfo); INSTANTIATE_SERIALISE_TYPE(VkPipelineMultisampleStateCreateInfo); @@ -7289,8 +7418,9 @@ INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceLimits); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceMemoryProperties); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceProperties); INSTANTIATE_SERIALISE_TYPE(VkPhysicalDeviceSparseProperties); -INSTANTIATE_SERIALISE_TYPE(VkPipelineCreationFeedbackEXT); INSTANTIATE_SERIALISE_TYPE(VkPipelineColorBlendAttachmentState); +INSTANTIATE_SERIALISE_TYPE(VkPipelineCreationFeedbackEXT); +INSTANTIATE_SERIALISE_TYPE(VkPipelineExecutableStatisticValueKHR); INSTANTIATE_SERIALISE_TYPE(VkPresentRegionKHR); INSTANTIATE_SERIALISE_TYPE(VkPushConstantRange); INSTANTIATE_SERIALISE_TYPE(VkQueueFamilyProperties); diff --git a/renderdoc/driver/vulkan/vk_stringise.cpp b/renderdoc/driver/vulkan/vk_stringise.cpp index f2e18f898..9eb8e5e3c 100644 --- a/renderdoc/driver/vulkan/vk_stringise.cpp +++ b/renderdoc/driver/vulkan/vk_stringise.cpp @@ -2572,6 +2572,19 @@ rdcstr DoStringise(const VkShaderFloatControlsIndependenceKHR &el) END_ENUM_STRINGISE(); } +template <> +rdcstr DoStringise(const VkPipelineExecutableStatisticFormatKHR &el) +{ + BEGIN_ENUM_STRINGISE(VkPipelineExecutableStatisticFormatKHR); + { + STRINGISE_ENUM(VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR); + STRINGISE_ENUM(VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR); + STRINGISE_ENUM(VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR); + STRINGISE_ENUM(VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR); + } + END_ENUM_STRINGISE(); +} + template <> rdcstr DoStringise(const VkExtent3D &el) { diff --git a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp index 02a4f9b41..37cfbdc9d 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_device_funcs.cpp @@ -1427,6 +1427,18 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi RDCLOG("Enabling VK_KHR_driver_properties"); } + bool pipeExec = false; + + // enable VK_KHR_pipeline_executable_properties if it's available, to fetch disassembly and + // statistics + if(supportedExtensions.find(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME) != + supportedExtensions.end()) + { + pipeExec = true; + Extensions.push_back(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); + RDCLOG("Enabling VK_KHR_pipeline_executable_properties"); + } + bool xfb = false; // enable VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME if it's available, to fetch mesh output in @@ -2127,6 +2139,14 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi CHECK_PHYS_EXT_FEATURE(computeFullSubgroups); } END_PHYS_EXT_CHECK(); + + BEGIN_PHYS_EXT_CHECK( + VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR); + { + CHECK_PHYS_EXT_FEATURE(pipelineExecutableInfo); + } + END_PHYS_EXT_CHECK(); } if(availFeatures.depthClamp) @@ -2243,6 +2263,51 @@ bool WrappedVulkan::Serialise_vkCreateDevice(SerialiserType &ser, VkPhysicalDevi SAFE_DELETE_ARRAY(exts); + VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR pipeExecFeatures = { + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR, + }; + + if(pipeExec) + { + VkPhysicalDeviceFeatures2 availBase = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2}; + availBase.pNext = &pipeExecFeatures; + ObjDisp(physicalDevice)->GetPhysicalDeviceFeatures2(Unwrap(physicalDevice), &availBase); + + if(pipeExecFeatures.pipelineExecutableInfo) + { + // see if there's an existing struct + VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *existing = + (VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *)FindNextStruct( + &createInfo, + VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR); + + if(existing) + { + // if so, make sure the feature is enabled + existing->pipelineExecutableInfo = VK_TRUE; + } + else + { + // otherwise, add our own, and push it onto the pNext array + pipeExecFeatures.pipelineExecutableInfo = VK_TRUE; + + pipeExecFeatures.pNext = (void *)createInfo.pNext; + createInfo.pNext = &pipeExecFeatures; + } + } + else + { + RDCWARN( + "VK_KHR_pipeline_executable_properties is available, but the physical device feature " + "is not. Disabling"); + + auto it = std::find(Extensions.begin(), Extensions.end(), + VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME); + RDCASSERT(it != Extensions.end()); + Extensions.erase(it); + } + } + VkPhysicalDeviceTransformFeedbackFeaturesEXT xfbFeatures = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT, }; diff --git a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp index 0403da4bb..a55325f68 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_get_funcs.cpp @@ -728,4 +728,35 @@ VkDeviceAddress WrappedVulkan::vkGetBufferDeviceAddressEXT(VkDevice device, VkBufferDeviceAddressInfoEXT unwrappedInfo = *pInfo; unwrappedInfo.buffer = Unwrap(unwrappedInfo.buffer); return ObjDisp(device)->GetBufferDeviceAddressEXT(Unwrap(device), &unwrappedInfo); +} + +VkResult WrappedVulkan::vkGetPipelineExecutablePropertiesKHR( + VkDevice device, const VkPipelineInfoKHR *pPipelineInfo, uint32_t *pExecutableCount, + VkPipelineExecutablePropertiesKHR *pProperties) +{ + VkPipelineInfoKHR unwrappedInfo = *pPipelineInfo; + unwrappedInfo.pipeline = Unwrap(unwrappedInfo.pipeline); + return ObjDisp(device)->GetPipelineExecutablePropertiesKHR(Unwrap(device), &unwrappedInfo, + pExecutableCount, pProperties); +} + +VkResult WrappedVulkan::vkGetPipelineExecutableStatisticsKHR( + VkDevice device, const VkPipelineExecutableInfoKHR *pExecutableInfo, uint32_t *pStatisticCount, + VkPipelineExecutableStatisticKHR *pStatistics) +{ + VkPipelineExecutableInfoKHR unwrappedInfo = *pExecutableInfo; + unwrappedInfo.pipeline = Unwrap(unwrappedInfo.pipeline); + return ObjDisp(device)->GetPipelineExecutableStatisticsKHR(Unwrap(device), &unwrappedInfo, + pStatisticCount, pStatistics); +} + +VkResult WrappedVulkan::vkGetPipelineExecutableInternalRepresentationsKHR( + VkDevice device, const VkPipelineExecutableInfoKHR *pExecutableInfo, + uint32_t *pInternalRepresentationCount, + VkPipelineExecutableInternalRepresentationKHR *pInternalRepresentations) +{ + VkPipelineExecutableInfoKHR unwrappedInfo = *pExecutableInfo; + unwrappedInfo.pipeline = Unwrap(unwrappedInfo.pipeline); + return ObjDisp(device)->GetPipelineExecutableInternalRepresentationsKHR( + Unwrap(device), &unwrappedInfo, pInternalRepresentationCount, pInternalRepresentations); } \ No newline at end of file diff --git a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp index f0fe9d671..541c67f48 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_shader_funcs.cpp @@ -421,6 +421,13 @@ bool WrappedVulkan::Serialise_vkCreateGraphicsPipelines( // don't use pipeline caches on replay pipelineCache = VK_NULL_HANDLE; + // if we have pipeline executable properties, capture the data + if(GetExtensions(NULL).ext_KHR_pipeline_executable_properties) + { + CreateInfo.flags |= (VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR | + VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR); + } + VkGraphicsPipelineCreateInfo *unwrapped = UnwrapInfos(&CreateInfo, 1); VkResult ret = ObjDisp(device)->CreateGraphicsPipelines(Unwrap(device), Unwrap(pipelineCache), 1, unwrapped, NULL, &pipe); @@ -614,6 +621,13 @@ bool WrappedVulkan::Serialise_vkCreateComputePipelines(SerialiserType &ser, VkDe // don't use pipeline caches on replay pipelineCache = VK_NULL_HANDLE; + // if we have pipeline executable properties, capture the data + if(GetExtensions(NULL).ext_KHR_pipeline_executable_properties) + { + CreateInfo.flags |= (VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR | + VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR); + } + VkComputePipelineCreateInfo *unwrapped = UnwrapInfos(&CreateInfo, 1); VkResult ret = ObjDisp(device)->CreateComputePipelines(Unwrap(device), Unwrap(pipelineCache), 1, unwrapped, NULL, &pipe);