diff --git a/android/framework/decode/CMakeLists.txt b/android/framework/decode/CMakeLists.txt index 3c108732cc..d9fdfb00b6 100644 --- a/android/framework/decode/CMakeLists.txt +++ b/android/framework/decode/CMakeLists.txt @@ -93,6 +93,8 @@ target_sources(gfxrecon_decode ${GFXRECON_SOURCE_DIR}/framework/decode/vulkan_replay_dump_resources_draw_calls.cpp ${GFXRECON_SOURCE_DIR}/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.h ${GFXRECON_SOURCE_DIR}/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.cpp + ${GFXRECON_SOURCE_DIR}/framework/decode/vulkan_replay_dump_resources_delegate.h + ${GFXRECON_SOURCE_DIR}/framework/decode/vulkan_replay_dump_resources_delegate.cpp ${GFXRECON_SOURCE_DIR}/framework/decode/vulkan_replay_dump_resources_json.h ${GFXRECON_SOURCE_DIR}/framework/decode/vulkan_replay_dump_resources_json.cpp ${GFXRECON_SOURCE_DIR}/framework/decode/vulkan_resource_allocator.h diff --git a/framework/decode/CMakeLists.txt b/framework/decode/CMakeLists.txt index 6dcfe8de7a..b43e3f45cb 100644 --- a/framework/decode/CMakeLists.txt +++ b/framework/decode/CMakeLists.txt @@ -191,6 +191,8 @@ target_sources(gfxrecon_decode ${CMAKE_CURRENT_LIST_DIR}/vulkan_replay_dump_resources_draw_calls.cpp ${CMAKE_CURRENT_LIST_DIR}/vulkan_replay_dump_resources_compute_ray_tracing.h ${CMAKE_CURRENT_LIST_DIR}/vulkan_replay_dump_resources_compute_ray_tracing.cpp + ${CMAKE_CURRENT_LIST_DIR}/vulkan_replay_dump_resources_delegate.h + ${CMAKE_CURRENT_LIST_DIR}/vulkan_replay_dump_resources_delegate.cpp ${CMAKE_CURRENT_LIST_DIR}/vulkan_replay_dump_resources_json.h ${CMAKE_CURRENT_LIST_DIR}/vulkan_replay_dump_resources_json.cpp ${CMAKE_CURRENT_LIST_DIR}/vulkan_resource_allocator.h diff --git a/framework/decode/dx12_browse_consumer.h b/framework/decode/dx12_browse_consumer.h index d82a107dc8..51dfba6370 100644 --- a/framework/decode/dx12_browse_consumer.h +++ b/framework/decode/dx12_browse_consumer.h @@ -63,7 +63,7 @@ struct TrackRootParameter // The other parameter types have no resources or descriptors info, so no track. }; -enum DumpDrawCallType +enum class DumpDrawCallType { kUnknown, kDraw, diff --git a/framework/decode/vulkan_replay_dump_resources.cpp b/framework/decode/vulkan_replay_dump_resources.cpp index 2d46bb7544..5d403ca64f 100644 --- a/framework/decode/vulkan_replay_dump_resources.cpp +++ b/framework/decode/vulkan_replay_dump_resources.cpp @@ -23,7 +23,7 @@ #include "decode/vulkan_object_info.h" #include "decode/vulkan_replay_dump_resources_compute_ray_tracing.h" #include "decode/vulkan_replay_options.h" -#include "decode/vulkan_replay_dump_resources_json.h" +#include "decode/vulkan_replay_dump_resources_delegate.h" #include "format/format.h" #include "generated/generated_vulkan_enum_to_string.h" #include "generated/generated_vulkan_struct_decoders.h" @@ -48,7 +48,8 @@ VulkanReplayDumpResourcesBase::VulkanReplayDumpResourcesBase(const VulkanReplayO CommonObjectInfoTable* object_info_table) : QueueSubmit_indices_(options.QueueSubmit_Indices), recording_(false), dump_resources_before_(options.dump_resources_before), object_info_table_(object_info_table), - output_json_per_command(options.dump_resources_json_per_command), dump_json_(options) + output_json_per_command(options.dump_resources_json_per_command), user_delegate_(nullptr), + active_delegate_(nullptr), default_delegate_(nullptr) { capture_filename = std::filesystem::path(options.capture_filename).stem().string(); @@ -57,9 +58,20 @@ VulkanReplayDumpResourcesBase::VulkanReplayDumpResourcesBase(const VulkanReplayO return; } + if (user_delegate_ != nullptr) + { + active_delegate_ = user_delegate_; + } + else + { + // Use a default delegate if none was provided. + default_delegate_ = std::make_unique(options, capture_filename); + active_delegate_ = default_delegate_.get(); + } + if (!options.dump_resources_json_per_command) { - dump_json_.Open(options.capture_filename, options.dump_resources_output_dir); + active_delegate_->Open(); } for (size_t i = 0; i < options.BeginCommandBuffer_Indices.size(); ++i) @@ -75,8 +87,7 @@ VulkanReplayDumpResourcesBase::VulkanReplayDumpResourcesBase(const VulkanReplayO options.RenderPass_Indices[i], *object_info_table, options, - dump_json_, - capture_filename)); + *active_delegate_)); } if ((i < options.Dispatch_Indices.size() && options.Dispatch_Indices[i].size()) || @@ -92,8 +103,7 @@ VulkanReplayDumpResourcesBase::VulkanReplayDumpResourcesBase(const VulkanReplayO : std::vector(), *object_info_table_, options, - dump_json_, - capture_filename)); + *active_delegate_)); } } } @@ -105,7 +115,13 @@ VulkanReplayDumpResourcesBase::~VulkanReplayDumpResourcesBase() void VulkanReplayDumpResourcesBase::Release() { - dump_json_.Close(); + // active_delegate_ could be nullptr because constructor could return before creating delegate. + if (active_delegate_) + { + active_delegate_->Close(); + active_delegate_ = nullptr; + default_delegate_ = nullptr; + } draw_call_contexts.clear(); dispatch_ray_contexts.clear(); cmd_buf_begin_map_.clear(); @@ -1847,7 +1863,7 @@ VkResult VulkanReplayDumpResourcesBase::QueueSubmit(const std::vectorDumpStart(); } for (size_t s = 0; s < submit_infos.size(); s++) @@ -1906,7 +1922,7 @@ VkResult VulkanReplayDumpResourcesBase::QueueSubmit(const std::vectorDumpEnd(); } // Looks like we didn't submit anything. Do the submission as it would have been done diff --git a/framework/decode/vulkan_replay_dump_resources.h b/framework/decode/vulkan_replay_dump_resources.h index 546cdf8979..710b530454 100644 --- a/framework/decode/vulkan_replay_dump_resources.h +++ b/framework/decode/vulkan_replay_dump_resources.h @@ -32,7 +32,6 @@ #include "decode/vulkan_replay_dump_resources_draw_calls.h" #include "decode/vulkan_replay_dump_resources_compute_ray_tracing.h" #include "generated/generated_vulkan_dispatch_table.h" -#include "decode/vulkan_replay_dump_resources_json.h" #include "format/format.h" #include "util/defines.h" #include "vulkan/vulkan_core.h" @@ -348,11 +347,14 @@ class VulkanReplayDumpResourcesBase std::unordered_map draw_call_contexts; std::unordered_map dispatch_ray_contexts; - bool recording_; - bool dump_resources_before_; - CommonObjectInfoTable* object_info_table_; - VulkanReplayDumpResourcesJson dump_json_; - bool output_json_per_command; + bool recording_; + bool dump_resources_before_; + CommonObjectInfoTable* object_info_table_; + bool output_json_per_command; + + std::unique_ptr default_delegate_; + VulkanDumpResourcesDelegate* user_delegate_; + VulkanDumpResourcesDelegate* active_delegate_; std::string capture_filename; diff --git a/framework/decode/vulkan_replay_dump_resources_common.h b/framework/decode/vulkan_replay_dump_resources_common.h index 6e30d441d3..236341245d 100644 --- a/framework/decode/vulkan_replay_dump_resources_common.h +++ b/framework/decode/vulkan_replay_dump_resources_common.h @@ -138,6 +138,31 @@ VkResult CreateVkBuffer(VkDeviceSize size, void GetFormatAspects(VkFormat format, std::vector& aspects); +class VulkanDumpResourcesDelegate; +class DefaultVulkanDumpResourcesDelegate; + +enum class DumpResourceType : uint32_t +{ + kUnknown, + kRtv, + kDsv, + kVertex, + kIndex, + kImageDescriptor, + kBufferDescriptor, + kInlineUniformBufferDescriptor, + kDrawCallInfo, + kDispatchInfo, + kTraceRaysIndex, + kDispatchTraceRaysImage, + kDispatchTraceRaysBuffer, + kDispatchTraceRaysImageDescriptor, + kDispatchTraceRaysBufferDescriptor, + kDispatchTraceRaysInlineUniformBufferDescriptor, +}; + +#define DEPTH_ATTACHMENT ~0 + GFXRECON_END_NAMESPACE(gfxrecon) GFXRECON_END_NAMESPACE(decode) diff --git a/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.cpp b/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.cpp index 00d1f2b989..65420acc5e 100644 --- a/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.cpp +++ b/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.cpp @@ -22,7 +22,7 @@ #include "decode/vulkan_object_info.h" #include "decode/vulkan_replay_dump_resources_compute_ray_tracing.h" -#include "decode/vulkan_replay_dump_resources_common.h" +#include "decode/vulkan_replay_dump_resources_delegate.h" #include "format/format.h" #include "generated/generated_vulkan_enum_to_string.h" #include "graphics/vulkan_resources_util.h" @@ -48,24 +48,18 @@ GFXRECON_BEGIN_NAMESPACE(gfxrecon) GFXRECON_BEGIN_NAMESPACE(decode) -DispatchTraceRaysDumpingContext::DispatchTraceRaysDumpingContext(const std::vector& dispatch_indices, - const std::vector& trace_rays_indices, - CommonObjectInfoTable& object_info_table, - const VulkanReplayOptions& options, - VulkanReplayDumpResourcesJson& dump_json, - std::string capture_filename) : +DispatchTraceRaysDumpingContext::DispatchTraceRaysDumpingContext(const std::vector& dispatch_indices, + const std::vector& trace_rays_indices, + CommonObjectInfoTable& object_info_table, + const VulkanReplayOptions& options, + VulkanDumpResourcesDelegate& delegate) : original_command_buffer_info(nullptr), DR_command_buffer(VK_NULL_HANDLE), dispatch_indices(dispatch_indices), trace_rays_indices(trace_rays_indices), bound_pipelines{ nullptr }, - dump_resources_before(options.dump_resources_before), dump_resource_path(options.dump_resources_output_dir), - image_file_format(options.dump_resources_image_format), dump_resources_scale(options.dump_resources_scale), - device_table(nullptr), parent_device(VK_NULL_HANDLE), instance_table(nullptr), object_info_table(object_info_table), - replay_device_phys_mem_props(nullptr), current_dispatch_index(0), current_trace_rays_index(0), dump_json(dump_json), - output_json_per_command(options.dump_resources_json_per_command), - dump_immutable_resources(options.dump_resources_dump_immutable_resources), - dump_all_image_subresources(options.dump_resources_dump_all_image_subresources), capture_filename(capture_filename), - reached_end_command_buffer(false), dump_images_raw(options.dump_resources_dump_raw_images), - dump_images_separate_alpha(options.dump_resources_dump_separate_alpha) + dump_resources_before(options.dump_resources_before), device_table(nullptr), parent_device(VK_NULL_HANDLE), + instance_table(nullptr), object_info_table(object_info_table), replay_device_phys_mem_props(nullptr), + current_dispatch_index(0), current_trace_rays_index(0), delegate_(delegate), + dump_immutable_resources(options.dump_resources_dump_immutable_resources), reached_end_command_buffer(false) {} DispatchTraceRaysDumpingContext::~DispatchTraceRaysDumpingContext() @@ -873,7 +867,22 @@ VkResult DispatchTraceRaysDumpingContext::DumpDispatchTraceRays( } } - GenerateOutputJsonDispatchInfo(qs_index, bcb_index, disp_index, i); + VulkanDumpDrawCallInfo draw_call_info{}; + draw_call_info.type = DumpResourceType::kDispatchInfo; + draw_call_info.instance_table = instance_table; + draw_call_info.device_table = device_table; + draw_call_info.object_info_table = &object_info_table; + draw_call_info.device_info = device_info; + draw_call_info.original_command_buffer_info = original_command_buffer_info; + draw_call_info.bcb_index = bcb_index; + draw_call_info.qs_index = qs_index; + draw_call_info.cmd_index = disp_index; + + const auto& dispatch_param_entry = dispatch_params.find(disp_index); + GFXRECON_ASSERT(dispatch_param_entry != dispatch_params.end()); + draw_call_info.disp_param = &dispatch_param_entry->second; + + delegate_.DumpDrawCallInfo(draw_call_info, i); } for (size_t i = 0; i < trace_rays_indices.size(); ++i) @@ -900,7 +909,22 @@ VkResult DispatchTraceRaysDumpingContext::DumpDispatchTraceRays( } } - GenerateOutputJsonTraceRaysIndex(qs_index, bcb_index, tr_index, i); + VulkanDumpDrawCallInfo draw_call_info{}; + draw_call_info.type = DumpResourceType::kTraceRaysIndex; + draw_call_info.instance_table = instance_table; + draw_call_info.device_table = device_table; + draw_call_info.object_info_table = &object_info_table; + draw_call_info.device_info = device_info; + draw_call_info.original_command_buffer_info = original_command_buffer_info; + draw_call_info.bcb_index = bcb_index; + draw_call_info.qs_index = qs_index; + draw_call_info.cmd_index = tr_index; + + const auto& trace_rays_param_entry = trace_rays_params.find(tr_index); + GFXRECON_ASSERT(trace_rays_param_entry != trace_rays_params.end()); + draw_call_info.tr_param = &trace_rays_param_entry->second; + + delegate_.DumpDrawCallInfo(draw_call_info, i); } // Clean up references to dumped descriptors in case this command buffer is submitted again @@ -916,110 +940,6 @@ VkResult DispatchTraceRaysDumpingContext::DumpDispatchTraceRays( return VK_SUCCESS; } -std::string DispatchTraceRaysDumpingContext::GenerateDispatchTraceRaysImageFilename(VkFormat format, - uint32_t mip, - uint32_t layer, - VkImageAspectFlagBits aspect, - VkImageTiling tiling, - VkImageType type, - bool is_dispatch, - uint64_t qs_index, - uint64_t bcb_index, - uint64_t cmd_index, - uint32_t desc_set, - uint32_t desc_binding, - uint32_t array_index, - VkShaderStageFlagBits stage, - bool before_cmd) const -{ - const VulkanDeviceInfo* device_info = object_info_table.GetVkDeviceInfo(original_command_buffer_info->parent_id); - assert(device_info); - - const DumpedImageFormat output_image_format = GetDumpedImageFormat(device_info, - device_table, - instance_table, - object_info_table, - format, - tiling, - type, - image_file_format, - dump_images_raw); - - const std::string shader_stage_name = ShaderStageToStr(stage); - const std::string aspect_str = ImageAspectToStr(aspect); - - std::stringstream filename; - filename << capture_filename << '_'; - - if (before_cmd) - { - filename << (is_dispatch ? "dispatch_" : "traceRays_") << cmd_index << "_qs_" << qs_index << "_bcb_" - << bcb_index << "_before_stage_" << shader_stage_name << "_set_" << desc_set << "_binding_" - << desc_binding << "_index_" << array_index; - if (output_image_format != KFormatRaw) - { - filename << "_" << util::ToString(format).c_str(); - } - filename << "_aspect_" << aspect_str; - } - else - { - filename << (is_dispatch ? "dispatch_" : "traceRays_") << cmd_index << "_qs_" << qs_index << "_bcb_" - << bcb_index << "_" << (dump_resources_before ? "after_" : "") << "stage_" << shader_stage_name - << "_set_" << desc_set << "_binding_" << desc_binding << "_index_" << array_index; - if (output_image_format != KFormatRaw) - { - filename << "_" << util::ToString(format).c_str(); - } - filename << "_aspect_" << aspect_str; - } - - if (dump_all_image_subresources) - { - filename << "_mip_" << mip << "_layer_" << layer; - } - - filename << ImageFileExtension(output_image_format); - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - return (filedirname / filebasename).string(); -} - -std::string DispatchTraceRaysDumpingContext::GenerateDispatchTraceRaysBufferFilename(bool is_dispatch, - uint64_t qs_index, - uint64_t bcb_index, - uint64_t cmd_index, - uint32_t desc_set, - uint32_t desc_binding, - uint32_t array_index, - VkShaderStageFlagBits stage, - bool before_cmd) const -{ - std::stringstream filename; - - filename << capture_filename << '_'; - - const std::string shader_stage_name = ShaderStageToStr(stage); - - if (before_cmd) - { - filename << (is_dispatch ? "dispatch_" : "traceRays_") << cmd_index << "_qs_" << qs_index << "_bcb_" - << bcb_index << "_before_stage_" << shader_stage_name << "_set_" << desc_set << "_binding_" - << desc_binding << "_index_" << array_index << "_buffer.bin"; - } - else - { - filename << (is_dispatch ? "dispatch_" : "traceRays_") << cmd_index << "_qs_" << qs_index << "_bcb_" - << bcb_index << "_" << (dump_resources_before ? "after_" : "") << "stage_" << shader_stage_name - << "_set_" << desc_set << "_binding_" << desc_binding << "_index_" << array_index << "_buffer.bin"; - } - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - return (filedirname / filebasename).string(); -} - VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_index, uint64_t qs_index, uint64_t cmd_index, @@ -1065,6 +985,15 @@ VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_inde *device_table, *instance_table, *phys_dev_info->replay_device_info->memory_properties); + VulkanDumpResourceInfo res_info_base{}; + res_info_base.device_info = device_info; + res_info_base.device_table = device_table; + res_info_base.instance_table = instance_table; + res_info_base.object_info_table = &object_info_table; + res_info_base.original_command_buffer_info = original_command_buffer_info; + res_info_base.cmd_index = cmd_index; + res_info_base.qs_index = qs_index; + res_info_base.bcb_index = bcb_index; if (dump_resources_before) { @@ -1077,84 +1006,20 @@ VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_inde VulkanImageInfo modified_image_info = *mutable_resources_clones_before.images[i].original_image; modified_image_info.handle = mutable_resources_clones_before.images[i].image; - const uint32_t desc_set = mutable_resources_clones_before.images[i].desc_set; - const uint32_t binding = mutable_resources_clones_before.images[i].desc_binding; - const uint32_t array_index = mutable_resources_clones_before.images[i].array_index; - const VkShaderStageFlagBits stage = mutable_resources_clones_before.images[i].stage; - - std::vector aspects; - GetFormatAspects(modified_image_info.format, aspects); - - const size_t total_files = - dump_all_image_subresources - ? (aspects.size() * modified_image_info.layer_count * modified_image_info.level_count) - : aspects.size(); - - std::vector filenames(total_files); - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < modified_image_info.level_count; ++mip) - { - for (uint32_t layer = 0; layer < modified_image_info.layer_count; ++layer) - { - filenames[f++] = GenerateDispatchTraceRaysImageFilename(modified_image_info.format, - mip, - layer, - aspect, - modified_image_info.tiling, - modified_image_info.type, - is_dispatch, - qs_index, - bcb_index, - cmd_index, - desc_set, - binding, - array_index, - stage, - true); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - - std::vector scaling_supported(filenames.size()); - VkResult res = DumpImageToFile(&modified_image_info, - device_info, - device_table, - instance_table, - object_info_table, - filenames, - dump_resources_scale, - scaling_supported, - image_file_format, - false, - dump_images_raw, - dump_images_separate_alpha, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysImage; + res_info.is_dispatch = is_dispatch; + res_info.before_cmd = true; + res_info.image_info = &modified_image_info; + res_info.set = mutable_resources_clones_before.images[i].desc_set; + res_info.binding = mutable_resources_clones_before.images[i].desc_binding; + res_info.array_index = mutable_resources_clones_before.images[i].array_index; + res_info.stage = mutable_resources_clones_before.images[i].stage; + auto res = delegate_.DumpResource(res_info); if (res != VK_SUCCESS) { - GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) return res; } - - // Keep track of images for which scaling failed - for (size_t i = 0; i < filenames.size(); ++i) - { - if (!scaling_supported[i]) - { - images_failed_scaling.insert(filenames[i]); - } - } } // Dump buffers @@ -1164,27 +1029,30 @@ VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_inde assert(buffer_info != nullptr); assert(mutable_resources_clones_before.buffers[i].buffer != VK_NULL_HANDLE); - std::vector data; - + VulkanDumpResourceInfo res_info = res_info_base; VkResult res = resource_util.ReadFromBufferResource(mutable_resources_clones_before.buffers[i].buffer, buffer_info->size, 0, buffer_info->queue_family_index, - data); + res_info.data); if (res != VK_SUCCESS) { GFXRECON_LOG_ERROR("Reading from buffer resource failed (%s)", util::ToString(res).c_str()) return res; } - const uint32_t desc_set = mutable_resources_clones_before.buffers[i].desc_set; - const uint32_t binding = mutable_resources_clones_before.buffers[i].desc_binding; - const uint32_t array_index = mutable_resources_clones_before.buffers[i].array_index; - const VkShaderStageFlagBits stage = mutable_resources_clones_before.buffers[i].stage; - - std::string filename = GenerateDispatchTraceRaysBufferFilename( - is_dispatch, qs_index, bcb_index, cmd_index, desc_set, binding, array_index, stage, true); - util::bufferwriter::WriteBuffer(filename, data.data(), data.size()); + res_info.type = DumpResourceType::kDispatchTraceRaysBuffer; + res_info.is_dispatch = is_dispatch; + res_info.before_cmd = true; + res_info.set = mutable_resources_clones_before.buffers[i].desc_set; + res_info.binding = mutable_resources_clones_before.buffers[i].desc_binding; + res_info.array_index = mutable_resources_clones_before.buffers[i].array_index; + res_info.stage = mutable_resources_clones_before.buffers[i].stage; + res = delegate_.DumpResource(res_info); + if (res != VK_SUCCESS) + { + return res; + } } } @@ -1196,84 +1064,20 @@ VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_inde VulkanImageInfo modified_image_info = *mutable_resources_clones.images[i].original_image; modified_image_info.handle = mutable_resources_clones.images[i].image; - const uint32_t desc_set = mutable_resources_clones.images[i].desc_set; - const uint32_t binding = mutable_resources_clones.images[i].desc_binding; - const uint32_t array_index = mutable_resources_clones.images[i].array_index; - const VkShaderStageFlagBits stage = mutable_resources_clones.images[i].stage; - - std::vector aspects; - GetFormatAspects(modified_image_info.format, aspects); - - const size_t total_files = - dump_all_image_subresources - ? (aspects.size() * modified_image_info.layer_count * modified_image_info.level_count) - : aspects.size(); - - std::vector filenames(total_files); - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < modified_image_info.level_count; ++mip) - { - for (uint32_t layer = 0; layer < modified_image_info.layer_count; ++layer) - { - filenames[f++] = GenerateDispatchTraceRaysImageFilename(modified_image_info.format, - mip, - layer, - aspect, - modified_image_info.tiling, - modified_image_info.type, - is_dispatch, - qs_index, - bcb_index, - cmd_index, - desc_set, - binding, - array_index, - stage, - false); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - - std::vector scaling_supported(filenames.size()); - VkResult res = DumpImageToFile(&modified_image_info, - device_info, - device_table, - instance_table, - object_info_table, - filenames, - dump_resources_scale, - scaling_supported, - image_file_format, - false, - dump_images_raw, - dump_images_separate_alpha, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysImage; + res_info.is_dispatch = is_dispatch; + res_info.before_cmd = false; + res_info.image_info = &modified_image_info; + res_info.set = mutable_resources_clones.images[i].desc_set; + res_info.binding = mutable_resources_clones.images[i].desc_binding; + res_info.array_index = mutable_resources_clones.images[i].array_index; + res_info.stage = mutable_resources_clones.images[i].stage; + auto res = delegate_.DumpResource(res_info); if (res != VK_SUCCESS) { - GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) return res; } - - // Keep track of images for which scaling failed - for (size_t i = 0; i < filenames.size(); ++i) - { - if (!scaling_supported[i]) - { - images_failed_scaling.insert(filenames[i]); - } - } } // Dump buffers @@ -1282,24 +1086,31 @@ VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_inde assert(mutable_resources_clones.buffers[i].original_buffer != nullptr); assert(mutable_resources_clones.buffers[i].buffer != VK_NULL_HANDLE); const VulkanBufferInfo* buffer_info = mutable_resources_clones.buffers[i].original_buffer; - std::vector data; - VkResult res = resource_util.ReadFromBufferResource( - mutable_resources_clones.buffers[i].buffer, buffer_info->size, 0, buffer_info->queue_family_index, data); + VulkanDumpResourceInfo res_info = res_info_base; + VkResult res = resource_util.ReadFromBufferResource(mutable_resources_clones.buffers[i].buffer, + buffer_info->size, + 0, + buffer_info->queue_family_index, + res_info.data); if (res != VK_SUCCESS) { GFXRECON_LOG_ERROR("Reading from buffer resource failed (%s)", util::ToString(res).c_str()) return res; } - const uint32_t desc_set = mutable_resources_clones.buffers[i].desc_set; - const uint32_t binding = mutable_resources_clones.buffers[i].desc_binding; - const uint32_t array_index = mutable_resources_clones.buffers[i].array_index; - const VkShaderStageFlagBits stage = mutable_resources_clones.buffers[i].stage; - - std::string filename = GenerateDispatchTraceRaysBufferFilename( - is_dispatch, qs_index, bcb_index, cmd_index, desc_set, binding, array_index, stage, false); - util::bufferwriter::WriteBuffer(filename, data.data(), data.size()); + res_info.type = DumpResourceType::kDispatchTraceRaysBuffer; + res_info.is_dispatch = is_dispatch; + res_info.before_cmd = false; + res_info.set = mutable_resources_clones.buffers[i].desc_set; + res_info.binding = mutable_resources_clones.buffers[i].desc_binding; + res_info.array_index = mutable_resources_clones.buffers[i].array_index; + res_info.stage = mutable_resources_clones.buffers[i].stage; + res = delegate_.DumpResource(res_info); + if (res != VK_SUCCESS) + { + return res; + } } return VK_SUCCESS; @@ -1402,90 +1213,6 @@ void DispatchTraceRaysDumpingContext::SnapshotBoundDescriptors(TraceRaysParamete } } -std::string DispatchTraceRaysDumpingContext::GenerateImageDescriptorFilename(VkFormat format, - uint32_t mip, - uint32_t layer, - format::HandleId image_id, - VkImageAspectFlagBits aspect, - VkImageTiling tiling, - VkImageType type, - uint64_t qs_index, - uint64_t bcb_index) const -{ - std::string aspect_str = ImageAspectToStr(aspect); - std::stringstream base_filename; - - base_filename << capture_filename << '_'; - - const VulkanDeviceInfo* device_info = object_info_table.GetVkDeviceInfo(original_command_buffer_info->parent_id); - assert(device_info); - - const DumpedImageFormat output_image_format = GetDumpedImageFormat(device_info, - device_table, - instance_table, - object_info_table, - format, - tiling, - type, - image_file_format, - dump_images_raw); - - if (output_image_format != KFormatRaw) - { - base_filename << "image_" << image_id << "_qs_" << qs_index << "_bcb_" << bcb_index << "_aspect_" << aspect_str; - } - else - { - std::string format_name = FormatToStr(format); - base_filename << "image_" << image_id << "_qs_" << qs_index << "_bcb_" << bcb_index << "_" << format_name - << "_aspect_" << aspect_str; - } - - if (dump_all_image_subresources) - { - std::stringstream sub_resources_str; - sub_resources_str << base_filename.str() << "_mip_" << mip << "_layer_" << layer; - sub_resources_str << ImageFileExtension(output_image_format); - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(sub_resources_str.str()); - return (filedirname / filebasename).string(); - } - else - { - base_filename << ImageFileExtension(output_image_format); - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(base_filename.str()); - return (filedirname / filebasename).string(); - } -} - -std::string DispatchTraceRaysDumpingContext::GenerateBufferDescriptorFilename(uint64_t qs_index, - uint64_t bcb_index, - format::HandleId buffer_id) const -{ - std::stringstream filename; - - filename << capture_filename << "_buffer_" << buffer_id << "_qs_" << qs_index << "_bcb_" << bcb_index << ".bin"; - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - return (filedirname / filebasename).string(); -} - -std::string DispatchTraceRaysDumpingContext::GenerateInlineUniformBufferDescriptorFilename(uint64_t qs_index, - uint64_t bcb_index, - uint32_t set, - uint32_t binding) const -{ - std::stringstream filename; - filename << capture_filename << '_' << "inlineUniformBlock_set_" << set << "_binding_" << binding << "_qs_" - << qs_index << "_bcb_" << bcb_index << ".bin"; - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - return (filedirname / filebasename).string(); -} - VkResult DispatchTraceRaysDumpingContext::DumpImmutableDescriptors(uint64_t qs_index, uint64_t bcb_index, uint64_t cmd_index, @@ -1699,73 +1426,27 @@ VkResult DispatchTraceRaysDumpingContext::DumpImmutableDescriptors(uint64_t qs_i const VulkanDeviceInfo* device_info = object_info_table.GetVkDeviceInfo(original_command_buffer_info->parent_id); assert(device_info); + VulkanDumpResourceInfo res_info_base{}; + res_info_base.device_info = device_info; + res_info_base.device_table = device_table; + res_info_base.instance_table = instance_table; + res_info_base.object_info_table = &object_info_table; + res_info_base.original_command_buffer_info = original_command_buffer_info; + res_info_base.cmd_index = cmd_index; + res_info_base.qs_index = qs_index; + res_info_base.bcb_index = bcb_index; + res_info_base.is_dispatch = is_dispatch; + for (const auto& img_info : image_descriptors) { - std::vector aspects; - GetFormatAspects(img_info->format, aspects); - - const size_t total_files = dump_all_image_subresources - ? (aspects.size() * img_info->layer_count * img_info->level_count) - : aspects.size(); - - std::vector filenames(total_files); - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < img_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) - { - filenames[f++] = GenerateImageDescriptorFilename(img_info->format, - mip, - layer, - img_info->capture_id, - aspect, - img_info->tiling, - img_info->type, - qs_index, - bcb_index); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - - std::vector scaling_supported(filenames.size()); - VkResult res = DumpImageToFile(img_info, - device_info, - device_table, - instance_table, - object_info_table, - filenames, - dump_resources_scale, - scaling_supported, - image_file_format, - dump_all_image_subresources, - dump_images_raw); + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysImageDescriptor; + res_info.image_info = img_info; + auto res = delegate_.DumpResource(res_info); if (res != VK_SUCCESS) { - GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) return res; } - - // Keep track of images for which scaling failed - for (size_t i = 0; i < filenames.size(); ++i) - { - if (!scaling_supported[i]) - { - images_failed_scaling.insert(filenames[i]); - } - } } const VulkanPhysicalDeviceInfo* phys_dev_info = object_info_table.GetVkPhysicalDeviceInfo(device_info->parent_id); @@ -1779,29 +1460,40 @@ VkResult DispatchTraceRaysDumpingContext::DumpImmutableDescriptors(uint64_t qs_i for (const auto& buf : buffer_descriptors) { - const VulkanBufferInfo* buffer_info = buf.first; - const VkDeviceSize offset = buf.second.offset; - const VkDeviceSize range = buf.second.range; - const VkDeviceSize size = range == VK_WHOLE_SIZE ? buffer_info->size - offset : range; + VulkanDumpResourceInfo res_info = res_info_base; + res_info.buffer_info = buf.first; + const VkDeviceSize offset = buf.second.offset; + const VkDeviceSize range = buf.second.range; + const VkDeviceSize size = range == VK_WHOLE_SIZE ? res_info.buffer_info->size - offset : range; - std::vector data; - VkResult res = resource_util.ReadFromBufferResource( - buffer_info->handle, size, offset, buffer_info->queue_family_index, data); + VkResult res = resource_util.ReadFromBufferResource( + res_info.buffer_info->handle, size, offset, res_info.buffer_info->queue_family_index, res_info.data); if (res != VK_SUCCESS) { GFXRECON_LOG_ERROR("Reading from buffer resource failed (%s)", util::ToString(res).c_str()) return res; } - const std::string filename = GenerateBufferDescriptorFilename(qs_index, bcb_index, buffer_info->capture_id); - util::bufferwriter::WriteBuffer(filename, data.data(), data.size()); + res_info.type = DumpResourceType::kDispatchTraceRaysBufferDescriptor; + res = delegate_.DumpResource(res_info); + if (res != VK_SUCCESS) + { + return res; + } } for (const auto& iub : inline_uniform_blocks) { - std::string filename = - GenerateInlineUniformBufferDescriptorFilename(qs_index, bcb_index, iub.second.set, iub.second.binding); - util::bufferwriter::WriteBuffer(filename, iub.second.data->data(), iub.second.data->size()); + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysInlineUniformBufferDescriptor; + res_info.set = iub.second.set; + res_info.binding = iub.second.binding; + res_info.data = *iub.second.data; + auto res = delegate_.DumpResource(res_info); + if (res != VK_SUCCESS) + { + return res; + } } return VK_SUCCESS; @@ -2056,910 +1748,15 @@ VkResult DispatchTraceRaysDumpingContext::FetchIndirectParams() return VK_SUCCESS; } -void DispatchTraceRaysDumpingContext::GenerateOutputJsonDispatchInfo(uint64_t qs_index, - uint64_t bcb_index, - uint64_t disp_index, - uint64_t cmd_index) const -{ - if (dispatch_params.empty()) - { - return; - } - - if (output_json_per_command) - { - std::stringstream filename; - filename << "Dispatch_" << disp_index << "_qs_" << qs_index << "_bcb_" << bcb_index << "_dr.json"; - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - std::string full_filename = (filedirname / filebasename).string(); - - dump_json.Open(full_filename); - dump_json.BlockStart(); - } - - auto& current_block = dump_json.GetCurrentSubEntry(); - auto& dispatch_json_entries = !output_json_per_command ? current_block["dispatchCommands"] : dump_json.GetData(); - auto& dispatch_json_entry = !output_json_per_command ? dispatch_json_entries[cmd_index] : dump_json.GetData(); - - const auto& disp_params = dispatch_params.find(disp_index); - - dispatch_json_entry["dispatchIndex"] = disp_index; - dispatch_json_entry["beginCommandBufferIndex"] = bcb_index; - dispatch_json_entry["queueSubmitIndex"] = qs_index; - - auto& params_json_entries = dispatch_json_entry["parameters"]; - params_json_entries["dispatchType"] = DispatchTypeToStr(disp_params->second.type); - switch (disp_params->second.type) - { - case kDispatch: - { - const DispatchParameters::DispatchParamsUnion::DispatchParams& ds_params = - disp_params->second.dispatch_params_union.dispatch; - - params_json_entries["groupCountX"] = ds_params.groupCountX; - params_json_entries["groupCountY"] = ds_params.groupCountY; - params_json_entries["groupCountZ"] = ds_params.groupCountZ; - } - break; - - case kDispatchIndirect: - { - const DispatchParameters::DispatchParamsUnion::DispatchIndirect& ds_params = - disp_params->second.dispatch_params_union.dispatch_indirect; - - assert(ds_params.dispatch_params != nullptr); - params_json_entries["groupCountX"] = ds_params.dispatch_params->groupCountX; - params_json_entries["groupCountY"] = ds_params.dispatch_params->groupCountY; - params_json_entries["groupCountZ"] = ds_params.dispatch_params->groupCountZ; - } - break; - - case kDispatchBase: - { - const DispatchParameters::DispatchParamsUnion::DispatchBaseParams& ds_params = - disp_params->second.dispatch_params_union.dispatch_base; - - params_json_entries["baseGroupX"] = ds_params.baseGroupX; - params_json_entries["baseGroupY"] = ds_params.baseGroupY; - params_json_entries["baseGroupZ"] = ds_params.baseGroupZ; - params_json_entries["groupCountX"] = ds_params.groupCountX; - params_json_entries["groupCountY"] = ds_params.groupCountY; - params_json_entries["groupCountZ"] = ds_params.groupCountZ; - } - break; - - default: - assert(0); - } - - auto& outputs_json_entries = dispatch_json_entry["outputs"]; - - if (dump_resources_before) - { - const auto& mutable_resource_entry_before = disp_params->second.mutable_resources_clones_before; - if (!mutable_resource_entry_before.images.empty()) - { - auto& before_command_output_image_entries = outputs_json_entries["before"]["images"]; - uint32_t output_image_index = 0; - - for (const auto& image : mutable_resource_entry_before.images) - { - const uint32_t desc_set = image.desc_set; - const uint32_t binding = image.desc_binding; - const uint32_t array_index = image.array_index; - const VkShaderStageFlagBits stage = image.stage; - const VulkanImageInfo* img_info = image.original_image; - assert(img_info != nullptr); - - auto& image_json_entry = before_command_output_image_entries[output_image_index++]; - image_json_entry["type"] = util::ToString(image.desc_type); - image_json_entry["set"] = desc_set; - image_json_entry["binding"] = binding; - image_json_entry["arrayIndex"] = array_index; - auto& image_json_entry_desc = image_json_entry["images"]; - - std::vector aspects; - GetFormatAspects(img_info->format, aspects); - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < img_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) - { - std::string filename = GenerateDispatchTraceRaysImageFilename(img_info->format, - mip, - layer, - aspect, - img_info->tiling, - img_info->type, - true, - qs_index, - bcb_index, - disp_index, - desc_set, - binding, - array_index, - stage, - true); - - const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), - std::max(1u, img_info->extent.height >> mip), - img_info->extent.depth }; - - dump_json.InsertImageInfo(image_json_entry_desc[f++], - img_info->format, - img_info->type, - img_info->capture_id, - extent, - filename, - aspect, - ImageFailedScaling(filename), - mip, - layer, - dump_images_separate_alpha); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - } - } - - if (!mutable_resource_entry_before.buffers.empty()) - { - auto& before_command_output_buffer_entries = outputs_json_entries["before"]["buffers"]; - uint32_t output_buffer_index = 0; - - for (const auto& buffer : mutable_resource_entry_before.buffers) - { - const uint32_t desc_set = buffer.desc_set; - const uint32_t binding = buffer.desc_binding; - const uint32_t array_index = buffer.array_index; - const VkShaderStageFlagBits stage = buffer.stage; - const VulkanBufferInfo* buffer_info = buffer.original_buffer; - assert(buffer_info != nullptr); - - std::string filename = GenerateDispatchTraceRaysBufferFilename( - true, qs_index, bcb_index, disp_index, desc_set, binding, array_index, stage, true); - - auto& buffer_json_entry = before_command_output_buffer_entries[output_buffer_index++]; - buffer_json_entry["type"] = util::ToString(buffer.desc_type); - buffer_json_entry["set"] = desc_set; - buffer_json_entry["binding"] = binding; - buffer_json_entry["arrayIndex"] = array_index; - dump_json.InsertBufferInfo(buffer_json_entry, buffer_info, filename); - } - } - } - - const auto& mutable_resource_entry = disp_params->second.mutable_resources_clones; - if (!mutable_resource_entry.images.empty()) - { - auto& outputs_json_entries_after = dump_resources_before ? outputs_json_entries["after"] : outputs_json_entries; - auto& image_outputs_json_entries = outputs_json_entries_after["images"]; - - uint32_t mutable_images_count = 0; - for (const auto& image : mutable_resource_entry.images) - { - const uint32_t desc_set = image.desc_set; - const uint32_t binding = image.desc_binding; - const uint32_t array_index = image.array_index; - const VkShaderStageFlagBits stage = image.stage; - const VulkanImageInfo* img_info = image.original_image; - assert(img_info != nullptr); - - auto& image_json_entry = image_outputs_json_entries[mutable_images_count++]; - image_json_entry["type"] = util::ToString(image.desc_type); - image_json_entry["set"] = desc_set; - image_json_entry["binding"] = binding; - image_json_entry["arrayIndex"] = array_index; - auto& image_json_entry_desc = image_json_entry["images"]; - - std::vector aspects; - GetFormatAspects(img_info->format, aspects); - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < img_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) - { - std::string filename = GenerateDispatchTraceRaysImageFilename(img_info->format, - mip, - layer, - aspect, - img_info->tiling, - img_info->type, - true, - qs_index, - bcb_index, - disp_index, - desc_set, - binding, - array_index, - stage, - false); - - const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), - std::max(1u, img_info->extent.height >> mip), - img_info->extent.depth }; - - dump_json.InsertImageInfo(image_json_entry_desc[f++], - img_info->format, - img_info->type, - img_info->capture_id, - extent, - filename, - aspect, - ImageFailedScaling(filename), - mip, - layer, - dump_images_separate_alpha); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - } - } - - if (!mutable_resource_entry.buffers.empty()) - { - auto& outputs_json_entries_after = dump_resources_before ? outputs_json_entries["after"] : outputs_json_entries; - auto& buffer_outputs_json_entries = outputs_json_entries_after["buffers"]; - - uint32_t mutable_buffers_count = 0; - for (const auto& buffer : mutable_resource_entry.buffers) - { - const uint32_t desc_set = buffer.desc_set; - const uint32_t binding = buffer.desc_binding; - const uint32_t array_index = buffer.array_index; - const VkShaderStageFlagBits stage = buffer.stage; - const VulkanBufferInfo* buffer_info = buffer.original_buffer; - assert(buffer_info != nullptr); - - std::string filename = GenerateDispatchTraceRaysBufferFilename( - true, qs_index, bcb_index, disp_index, desc_set, binding, array_index, stage, false); - - auto& buffer_json_entry = buffer_outputs_json_entries[mutable_buffers_count++]; - buffer_json_entry["type"] = util::ToString(buffer.desc_type); - buffer_json_entry["set"] = desc_set; - buffer_json_entry["binding"] = binding; - buffer_json_entry["arrayIndex"] = array_index; - dump_json.InsertBufferInfo(buffer_json_entry, buffer_info, filename); - } - } - - if (dump_immutable_resources) - { - uint32_t descriptor_entries_count = 0; - for (const auto& desc_set : disp_params->second.referenced_descriptors) - { - const uint32_t desc_set_index = desc_set.first; - for (const auto& desc_binding : desc_set.second) - { - const uint32_t desc_binding_index = desc_binding.first; - switch (desc_binding.second.desc_type) - { - case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: - case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: - { - for (size_t i = 0; i < desc_binding.second.image_info.size(); ++i) - { - if (desc_binding.second.image_info[i].image_view_info == nullptr) - { - continue; - } - - auto& entry = dispatch_json_entry["descriptors"][descriptor_entries_count++]; - - entry["type"] = util::ToString(desc_binding.second.desc_type); - entry["set"] = desc_set_index; - entry["binding"] = desc_binding_index; - entry["arrayIndex"] = i; - - const VulkanImageInfo* img_info = object_info_table.GetVkImageInfo( - desc_binding.second.image_info[i].image_view_info->image_id); - assert(img_info); - - std::vector aspects; - GetFormatAspects(img_info->format, aspects); - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < img_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) - { - std::string filename = GenerateImageDescriptorFilename(img_info->format, - mip, - layer, - img_info->capture_id, - aspect, - img_info->tiling, - img_info->type, - qs_index, - bcb_index); - - auto& image_descriptor_json_entry = entry["descriptor"]; - const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), - std::max(1u, img_info->extent.height >> mip), - img_info->extent.depth }; - - dump_json.InsertImageInfo(image_descriptor_json_entry[f++], - img_info->format, - img_info->type, - img_info->capture_id, - extent, - filename, - aspect, - ImageFailedScaling(filename), - mip, - layer, - dump_images_separate_alpha); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - } - } - break; - - case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: - { - for (size_t i = 0; i < desc_binding.second.buffer_info.size(); ++i) - { - if (desc_binding.second.buffer_info[i].buffer_info != nullptr) - { - auto& entry = dispatch_json_entry["descriptors"][descriptor_entries_count++]; - - entry["type"] = util::ToString(desc_binding.second.desc_type); - entry["set"] = desc_set_index; - entry["binding"] = desc_binding_index; - entry["arrayIndex"] = i; - - auto& buffer_descriptor_json_entry = entry["descriptor"]; - - const std::string filename = GenerateBufferDescriptorFilename( - qs_index, bcb_index, desc_binding.second.buffer_info[i].buffer_info->capture_id); - dump_json.InsertBufferInfo(buffer_descriptor_json_entry, - desc_binding.second.buffer_info[i].buffer_info, - filename); - } - } - } - break; - - case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: - case VK_DESCRIPTOR_TYPE_SAMPLER: - break; - - case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: - { - auto& entry = dispatch_json_entry["descriptors"][descriptor_entries_count++]; - - entry["type"] = util::ToString(desc_binding.second.desc_type); - entry["set"] = desc_set_index; - entry["binding"] = desc_binding_index; - entry["size"] = desc_binding.second.inline_uniform_block.size(); - - const std::string filename = GenerateInlineUniformBufferDescriptorFilename( - qs_index, bcb_index, desc_set_index, desc_binding_index); - entry["file"] = filename; - } - break; - - default: - GFXRECON_LOG_WARNING_ONCE( - "%s(): Descriptor type (%s) not handled", - __func__, - util::ToString(desc_binding.second.desc_type).c_str()); - break; - } - } - } - } - - if (output_json_per_command) - { - dump_json.BlockEnd(); - dump_json.Close(); - } -} - -void DispatchTraceRaysDumpingContext::GenerateOutputJsonTraceRaysIndex(uint64_t qs_index, - uint64_t bcb_index, - uint64_t tr_index, - uint64_t cmd_index) const -{ - auto& current_block = dump_json.GetCurrentSubEntry(); - - auto& tr_json_entries = (!trace_rays_params.empty() && !output_json_per_command) - ? current_block["traceRaysCommands"] - : dump_json.GetData(); - - if (output_json_per_command) - { - std::stringstream filename; - filename << "TraceRays_" << tr_index << "_qs_" << qs_index << "_bcb_" << bcb_index << "_dr.json"; - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - std::string full_filename = (filedirname / filebasename).string(); - - dump_json.Open(full_filename); - dump_json.BlockStart(); - } - const auto& tr_params = trace_rays_params.find(tr_index); - - auto& tr_entry = !output_json_per_command ? tr_json_entries[cmd_index] : dump_json.GetData(); - - tr_entry["traceRaysIndex"] = tr_index; - tr_entry["beginCommandBufferIndex"] = bcb_index; - tr_entry["queueSubmitIndex"] = qs_index; - - auto& params_json_entries = tr_entry["parameters"]; - params_json_entries["traceRaysType"] = TraceRaysTypeToStr(tr_params->second.type); - - switch (tr_params->second.type) - { - case kTraceRays: - { - const VkTraceRaysIndirectCommandKHR& params = tr_params->second.trace_rays_params_union.trace_rays; - - params_json_entries["width"] = params.width; - params_json_entries["height"] = params.height; - params_json_entries["depth"] = params.depth; - } - break; - - case kTraceRaysIndirect: - { - const TraceRaysParameters::TraceRaysParamsUnion::TraceRaysIndirect& params = - tr_params->second.trace_rays_params_union.trace_rays_indirect; - - params_json_entries["width"] = params.trace_rays_params.width; - params_json_entries["height"] = params.trace_rays_params.height; - params_json_entries["depth"] = params.trace_rays_params.depth; - } - break; - - case kTraceRaysIndirect2: - { - const TraceRaysParameters::TraceRaysParamsUnion::TraceRaysIndirect2& params = - tr_params->second.trace_rays_params_union.trace_rays_indirect2; - - params_json_entries["width"] = params.trace_rays_params.width; - params_json_entries["height"] = params.trace_rays_params.height; - params_json_entries["depth"] = params.trace_rays_params.depth; - } - break; - - default: - assert(0); - } - - auto& outputs_json_entries = tr_entry["outputs"]; - - if (dump_resources_before) - { - const auto& mutable_resource_entry_before = tr_params->second.mutable_resources_clones_before; - if (!mutable_resource_entry_before.images.empty()) - { - auto& before_command_output_image_entries = outputs_json_entries["before"]["images"]; - uint32_t output_image_index = 0; - - for (const auto& image : mutable_resource_entry_before.images) - { - const uint32_t desc_set = image.desc_set; - const uint32_t binding = image.desc_binding; - const uint32_t array_index = image.array_index; - const VkShaderStageFlagBits stage = image.stage; - const VulkanImageInfo* img_info = image.original_image; - assert(img_info != nullptr); - - std::vector aspects; - GetFormatAspects(img_info->format, aspects); - - auto& image_json_entry = before_command_output_image_entries[output_image_index++]; - image_json_entry["type"] = util::ToString(image.desc_type); - image_json_entry["set"] = desc_set; - image_json_entry["binding"] = binding; - image_json_entry["arrayIndex"] = array_index; - auto& image_json_entry_desc = image_json_entry["images"]; - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < img_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) - { - std::string filename = GenerateDispatchTraceRaysImageFilename(img_info->format, - mip, - layer, - aspect, - img_info->tiling, - img_info->type, - false, - qs_index, - bcb_index, - tr_index, - desc_set, - binding, - array_index, - stage, - true); - - const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), - std::max(1u, img_info->extent.height >> mip), - img_info->extent.depth }; - - dump_json.InsertImageInfo(image_json_entry_desc[f++], - img_info->format, - img_info->type, - img_info->capture_id, - extent, - filename, - aspect, - ImageFailedScaling(filename), - mip, - layer, - dump_images_separate_alpha); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - } - } - - if (!mutable_resource_entry_before.buffers.empty()) - { - auto& before_command_output_buffer_entries = outputs_json_entries["before"]["buffers"]; - uint32_t output_buffer_index = 0; - - for (const auto& buffer : mutable_resource_entry_before.buffers) - { - const uint32_t desc_set = buffer.desc_set; - const uint32_t binding = buffer.desc_binding; - const uint32_t array_index = buffer.array_index; - const VkShaderStageFlagBits stage = buffer.stage; - const VulkanBufferInfo* buffer_info = buffer.original_buffer; - assert(buffer_info != nullptr); - - std::string filename = GenerateDispatchTraceRaysBufferFilename( - false, qs_index, bcb_index, tr_index, desc_set, binding, array_index, stage, true); - - auto& buffer_json_entry = before_command_output_buffer_entries[output_buffer_index++]; - buffer_json_entry["type"] = util::ToString(buffer.desc_type); - buffer_json_entry["set"] = desc_set; - buffer_json_entry["binding"] = binding; - buffer_json_entry["arrayIndex"] = array_index; - dump_json.InsertBufferInfo(buffer_json_entry, buffer_info, filename); - } - } - } - - const auto& mutable_resource_entry = tr_params->second.mutable_resources_clones; - auto& outputs_json_entries_after = dump_resources_before ? outputs_json_entries["after"] : outputs_json_entries; - - if (!mutable_resource_entry.images.empty()) - { - uint32_t mutable_images_count = 0; - for (const auto& image : mutable_resource_entry.images) - { - const uint32_t desc_set = image.desc_set; - const uint32_t binding = image.desc_binding; - const uint32_t array_index = image.array_index; - const VkShaderStageFlagBits stage = image.stage; - const VulkanImageInfo* img_info = image.original_image; - assert(img_info != nullptr); - - auto& image_json_entry = outputs_json_entries_after["images"][mutable_images_count++]; - image_json_entry["type"] = util::ToString(image.desc_type); - image_json_entry["set"] = desc_set; - image_json_entry["binding"] = binding; - image_json_entry["arrayIndex"] = array_index; - auto& image_json_entry_desc = image_json_entry["image"]; - - std::vector aspects; - GetFormatAspects(img_info->format, aspects); - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < img_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) - { - std::string filename = GenerateDispatchTraceRaysImageFilename(img_info->format, - mip, - layer, - aspect, - img_info->tiling, - img_info->type, - false, - qs_index, - bcb_index, - tr_index, - desc_set, - binding, - array_index, - stage, - false); - - const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), - std::max(1u, img_info->extent.height >> mip), - img_info->extent.depth }; - - dump_json.InsertImageInfo(image_json_entry_desc[f++], - img_info->format, - img_info->type, - img_info->capture_id, - extent, - filename, - aspect, - ImageFailedScaling(filename), - mip, - layer, - dump_images_separate_alpha); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - } - } - - if (!mutable_resource_entry.buffers.empty()) - { - uint32_t mutable_buffers_count = 0; - for (const auto& buffer : mutable_resource_entry.buffers) - { - const uint32_t desc_set = buffer.desc_set; - const uint32_t binding = buffer.desc_binding; - const uint32_t array_index = buffer.array_index; - const VkShaderStageFlagBits stage = buffer.stage; - const VulkanBufferInfo* buffer_info = buffer.original_buffer; - assert(buffer_info != nullptr); - - std::string filename = GenerateDispatchTraceRaysBufferFilename( - false, qs_index, bcb_index, tr_index, desc_set, binding, array_index, stage, false); - - auto& buffer_json_entry = outputs_json_entries_after["buffers"][mutable_buffers_count++]; - buffer_json_entry["type"] = util::ToString(buffer.desc_type); - buffer_json_entry["set"] = desc_set; - buffer_json_entry["binding"] = binding; - buffer_json_entry["arrayIndex"] = array_index; - dump_json.InsertBufferInfo(buffer_json_entry, buffer_info, filename); - } - } - - if (dump_immutable_resources) - { - for (const auto& shader_stage : tr_params->second.referenced_descriptors) - { - uint32_t stage_entry_index = 0; - const std::string shader_stage_name = ShaderStageToStr(shader_stage.first); - for (const auto& desc_set : shader_stage.second) - { - const uint32_t desc_set_index = desc_set.first; - - for (const auto& desc_binding : desc_set.second) - { - const uint32_t desc_binding_index = desc_binding.first; - - switch (desc_binding.second.desc_type) - { - case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: - case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: - { - for (size_t img = 0; img < desc_binding.second.image_info.size(); ++img) - { - if (desc_binding.second.image_info[img].image_view_info == nullptr) - { - continue; - } - - auto& entry = tr_entry["descriptors"][shader_stage_name][stage_entry_index++]; - - const VulkanImageInfo* img_info = object_info_table.GetVkImageInfo( - desc_binding.second.image_info[img].image_view_info->image_id); - assert(img_info); - - entry["type"] = util::ToString(desc_binding.second.desc_type); - entry["set"] = desc_set_index; - entry["binding"] = desc_binding_index; - entry["arrayIndex"] = img; - - std::vector aspects; - GetFormatAspects(img_info->format, aspects); - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < img_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) - { - std::string filename = GenerateImageDescriptorFilename(img_info->format, - mip, - layer, - img_info->capture_id, - aspect, - img_info->tiling, - img_info->type, - qs_index, - bcb_index); - - const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), - std::max(1u, img_info->extent.height >> mip), - img_info->extent.depth }; - - auto& image_descriptor_json_entry = entry["descriptor"]; - - dump_json.InsertImageInfo(image_descriptor_json_entry[f++], - img_info->format, - img_info->type, - img_info->capture_id, - extent, - filename, - aspect, - ImageFailedScaling(filename), - mip, - layer, - dump_images_separate_alpha); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - } - } - break; - - case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: - { - for (size_t i = 0; i < desc_binding.second.buffer_info.size(); ++i) - { - if (desc_binding.second.buffer_info[i].buffer_info != nullptr) - { - auto& entry = tr_entry["descriptors"][shader_stage_name][stage_entry_index++]; - - entry["type"] = util::ToString(desc_binding.second.desc_type); - entry["set"] = desc_set_index; - entry["binding"] = desc_binding_index; - entry["arrayIndex"] = i; - - const std::string filename = GenerateBufferDescriptorFilename( - qs_index, - bcb_index, - desc_binding.second.buffer_info[i].buffer_info->capture_id); - auto& buffer_descriptor_json_entry = entry["descriptor"]; - dump_json.InsertBufferInfo(buffer_descriptor_json_entry, - desc_binding.second.buffer_info[i].buffer_info, - filename); - } - } - } - break; - - case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: - { - auto& desc_json_entry = tr_entry["descriptors"][shader_stage_name][stage_entry_index++]; - - const std::string filename = GenerateInlineUniformBufferDescriptorFilename( - qs_index, bcb_index, desc_set_index, desc_binding_index); - - desc_json_entry["type"] = util::ToString(desc_binding.second.desc_type); - desc_json_entry["set"] = desc_set_index; - desc_json_entry["binding"] = desc_binding_index; - desc_json_entry["size"] = desc_binding.second.inline_uniform_block.size(); - desc_json_entry["file"] = filename; - } - break; - - case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: - case VK_DESCRIPTOR_TYPE_SAMPLER: - break; - - default: - GFXRECON_LOG_WARNING_ONCE( - "%s(): Descriptor type (%s) not handled", - __func__, - util::ToString(desc_binding.second.desc_type).c_str()); - break; - } - } - } - } - } - - if (output_json_per_command) - { - dump_json.BlockEnd(); - dump_json.Close(); - } -} - void DispatchTraceRaysDumpingContext::InsertNewDispatchParameters(uint64_t index, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) { - auto new_entry = dispatch_params.emplace( - std::piecewise_construct, - std::forward_as_tuple(index), - std::forward_as_tuple( - DispatchTraceRaysDumpingContext::DispatchTypes::kDispatch, groupCountX, groupCountY, groupCountZ)); + auto new_entry = + dispatch_params.emplace(std::piecewise_construct, + std::forward_as_tuple(index), + std::forward_as_tuple(DispatchTypes::kDispatch, groupCountX, groupCountY, groupCountZ)); assert(new_entry.second); } @@ -2967,10 +1764,10 @@ void DispatchTraceRaysDumpingContext::InsertNewDispatchParameters(uint64_t const VulkanBufferInfo* buffer_info, VkDeviceSize offset) { - auto new_entry = dispatch_params.emplace( - std::piecewise_construct, - std::forward_as_tuple(index), - std::forward_as_tuple(DispatchTraceRaysDumpingContext::DispatchTypes::kDispatchIndirect, buffer_info, offset)); + auto new_entry = + dispatch_params.emplace(std::piecewise_construct, + std::forward_as_tuple(index), + std::forward_as_tuple(DispatchTypes::kDispatchIndirect, buffer_info, offset)); assert(new_entry.second); } @@ -2984,10 +1781,9 @@ void DispatchTraceRaysDumpingContext::InsertNewTraceRaysParameters( uint32_t height, uint32_t depth) { - auto new_entry = trace_rays_params.emplace( - std::piecewise_construct, - std::forward_as_tuple(index), - std::forward_as_tuple(DispatchTraceRaysDumpingContext::TraceRaysTypes::kTraceRays, width, height, depth)); + auto new_entry = trace_rays_params.emplace(std::piecewise_construct, + std::forward_as_tuple(index), + std::forward_as_tuple(TraceRaysTypes::kTraceRays, width, height, depth)); assert(new_entry.second); } @@ -2999,22 +1795,20 @@ void DispatchTraceRaysDumpingContext::InsertNewTraceRaysIndirectParameters( const VkStridedDeviceAddressRegionKHR* pCallableShaderBindingTable, VkDeviceAddress indirectDeviceAddress) { - auto new_entry = trace_rays_params.emplace( - std::piecewise_construct, - std::forward_as_tuple(index), - std::forward_as_tuple(DispatchTraceRaysDumpingContext::TraceRaysTypes::kTraceRaysIndirect, - indirectDeviceAddress)); + auto new_entry = + trace_rays_params.emplace(std::piecewise_construct, + std::forward_as_tuple(index), + std::forward_as_tuple(TraceRaysTypes::kTraceRaysIndirect, indirectDeviceAddress)); assert(new_entry.second); } void DispatchTraceRaysDumpingContext::InsertNewTraceRaysIndirect2Parameters(uint64_t index, VkDeviceAddress indirectDeviceAddress) { - auto new_entry = trace_rays_params.emplace( - std::piecewise_construct, - std::forward_as_tuple(index), - std::forward_as_tuple(DispatchTraceRaysDumpingContext::TraceRaysTypes::kTraceRaysIndirect2, - indirectDeviceAddress)); + auto new_entry = + trace_rays_params.emplace(std::piecewise_construct, + std::forward_as_tuple(index), + std::forward_as_tuple(TraceRaysTypes::kTraceRaysIndirect2, indirectDeviceAddress)); assert(new_entry.second); } diff --git a/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.h b/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.h index 0310c69a75..f252f4226a 100644 --- a/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.h +++ b/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.h @@ -28,7 +28,6 @@ #include "decode/vulkan_object_info.h" #include "decode/vulkan_replay_options.h" #include "generated/generated_vulkan_dispatch_table.h" -#include "decode/vulkan_replay_dump_resources_json.h" #include "format/format.h" #include "util/defines.h" #include "vulkan/vulkan_core.h" @@ -46,12 +45,11 @@ GFXRECON_BEGIN_NAMESPACE(decode) class DispatchTraceRaysDumpingContext { public: - DispatchTraceRaysDumpingContext(const std::vector& dispatch_indices, - const std::vector& trace_rays_indices, - CommonObjectInfoTable& object_info_table, - const VulkanReplayOptions& options, - VulkanReplayDumpResourcesJson& dump_json, - std::string capture_filename); + DispatchTraceRaysDumpingContext(const std::vector& dispatch_indices, + const std::vector& trace_rays_indices, + CommonObjectInfoTable& object_info_table, + const VulkanReplayOptions& options, + VulkanDumpResourcesDelegate& delegate); ~DispatchTraceRaysDumpingContext(); @@ -121,50 +119,6 @@ class DispatchTraceRaysDumpingContext void Release(); private: - std::string GenerateDispatchTraceRaysImageFilename(VkFormat format, - uint32_t mip, - uint32_t layer, - VkImageAspectFlagBits aspect, - VkImageTiling tiling, - VkImageType type, - bool is_dispatch, - uint64_t qs_index, - uint64_t bcb_index, - uint64_t cmd_index, - uint32_t desc_set, - uint32_t desc_binding, - uint32_t array_index, - VkShaderStageFlagBits stage, - bool before_cmd) const; - - std::string GenerateDispatchTraceRaysBufferFilename(bool is_dispatch, - uint64_t qs_index, - uint64_t bcb_index, - uint64_t cmd_index, - uint32_t desc_set, - uint32_t desc_binding, - uint32_t array_index, - VkShaderStageFlagBits stage, - bool before_cmd) const; - - std::string GenerateImageDescriptorFilename(VkFormat format, - uint32_t mip, - uint32_t layer, - format::HandleId image_id, - VkImageAspectFlagBits aspect, - VkImageTiling tiling, - VkImageType type, - uint64_t bcb_index, - uint64_t cmd_index) const; - - std::string - GenerateBufferDescriptorFilename(uint64_t bcb_index, uint64_t cmd_index, format::HandleId buffer_id) const; - - std::string GenerateInlineUniformBufferDescriptorFilename(uint64_t bcb_index, - uint64_t cmd_index, - uint32_t set, - uint32_t binding) const; - void CopyImageResource(const VulkanImageInfo* src_image_info, VkImage dst_image); void CopyBufferResource(const VulkanBufferInfo* src_buffer_info, @@ -180,36 +134,20 @@ class DispatchTraceRaysDumpingContext VkResult DumpImmutableDescriptors(uint64_t qs_index, uint64_t bcb_index, uint64_t cmd_index, bool is_dispatch); - void GenerateOutputJsonDispatchInfo(uint64_t qs_index, - uint64_t bcb_index, - uint64_t disp_index, - uint64_t cmd_index) const; - - void GenerateOutputJsonTraceRaysIndex(uint64_t qs_index, - uint64_t bcb_index, - uint64_t tr_index, - uint64_t cmd_index) const; - const VulkanCommandBufferInfo* original_command_buffer_info; VkCommandBuffer DR_command_buffer; std::vector dispatch_indices; std::vector trace_rays_indices; const VulkanPipelineInfo* bound_pipelines[kBindPoint_count]; bool dump_resources_before; - const std::string& dump_resource_path; - util::ScreenshotFormat image_file_format; - float dump_resources_scale; - VulkanReplayDumpResourcesJson& dump_json; - bool output_json_per_command; + VulkanDumpResourcesDelegate& delegate_; bool dump_immutable_resources; - bool dump_all_image_subresources; - bool dump_images_raw; - bool dump_images_separate_alpha; // One entry per descriptor set for each compute and ray tracing binding points std::unordered_map bound_descriptor_sets_compute; std::unordered_map bound_descriptor_sets_ray_tracing; + public: // For each Dispatch/TraceRays that we dump we create a clone of all mutable resources used in the // shaders/pipeline and the content of the original resources are copied into the clones struct MutableResourcesBackupContext @@ -453,6 +391,7 @@ class DispatchTraceRaysDumpingContext MutableResourcesBackupContext mutable_resources_clones_before; }; + private: VkResult CloneMutableResources(MutableResourcesBackupContext& backup_context, bool is_dispatch); void SnapshotBoundDescriptors(DispatchParameters& disp_params); @@ -491,7 +430,6 @@ class DispatchTraceRaysDumpingContext const VkPhysicalDeviceMemoryProperties* replay_device_phys_mem_props; size_t current_dispatch_index; size_t current_trace_rays_index; - std::string capture_filename; bool reached_end_command_buffer; }; diff --git a/framework/decode/vulkan_replay_dump_resources_delegate.cpp b/framework/decode/vulkan_replay_dump_resources_delegate.cpp new file mode 100644 index 0000000000..9c32250fb7 --- /dev/null +++ b/framework/decode/vulkan_replay_dump_resources_delegate.cpp @@ -0,0 +1,2179 @@ +/* +** Copyright (c) 2025 LunarG, Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and associated documentation files (the "Software"), +** to deal in the Software without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Software, and to permit persons to whom the +** Software is furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +*/ + +#include "decode/vulkan_replay_dump_resources_delegate.h" +#include "generated/generated_vulkan_enum_to_string.h" +#include "util/buffer_writer.h" + +GFXRECON_BEGIN_NAMESPACE(gfxrecon) +GFXRECON_BEGIN_NAMESPACE(decode) + +void DefaultVulkanDumpResourcesDelegate::DumpDrawCallInfo(const VulkanDumpDrawCallInfo& draw_call_info, size_t index) +{ + switch (draw_call_info.type) + { + case DumpResourceType::kDrawCallInfo: + GenerateOutputJsonDrawCallInfo(draw_call_info, index); + break; + case DumpResourceType::kDispatchInfo: + GenerateOutputJsonDispatchInfo(draw_call_info, index); + break; + case DumpResourceType::kTraceRaysIndex: + GenerateOutputJsonTraceRaysIndex(draw_call_info, index); + break; + default: + break; + } +} + +VkResult DefaultVulkanDumpResourcesDelegate::DumpResource(const VulkanDumpResourceInfo& resource_info) +{ + switch (resource_info.type) + { + case DumpResourceType::kRtv: + case DumpResourceType::kDsv: + return DumpRenderTargetImage(resource_info); + break; + case DumpResourceType::kImageDescriptor: + return DumpImageDescriptor(resource_info); + break; + case DumpResourceType::kBufferDescriptor: + return DumpBufferDescriptor(resource_info); + break; + case DumpResourceType::kInlineUniformBufferDescriptor: + return DumpInlineUniformBufferDescriptor(resource_info); + break; + case DumpResourceType::kVertex: + return DumpVertexBuffer(resource_info); + break; + case DumpResourceType::kIndex: + return DumpIndexBuffer(resource_info); + break; + case DumpResourceType::kDispatchTraceRaysImage: + return DumpeDispatchTraceRaysImage(resource_info); + break; + case DumpResourceType::kDispatchTraceRaysBuffer: + return DumpeDispatchTraceRaysBuffer(resource_info); + break; + case DumpResourceType::kDispatchTraceRaysImageDescriptor: + return DumpDispatchTraceRaysImageDescriptor(resource_info); + break; + case DumpResourceType::kDispatchTraceRaysBufferDescriptor: + return DumpDispatchTraceRaysBufferDescriptor(resource_info); + break; + case DumpResourceType::kDispatchTraceRaysInlineUniformBufferDescriptor: + return DumpDispatchTraceRaysInlineUniformBufferDescriptor(resource_info); + break; + default: + break; + } + return VK_ERROR_UNKNOWN; +} + +VkResult DefaultVulkanDumpResourcesDelegate::DumpRenderTargetImage(const VulkanDumpResourceInfo& resource_info) +{ + const VulkanImageInfo* image_info = resource_info.image_info; + + std::vector aspects; + GetFormatAspects(image_info->format, aspects); + + const size_t total_files = options_.dump_resources_dump_all_image_subresources + ? (aspects.size() * image_info->layer_count * image_info->level_count) + : aspects.size(); + + std::vector filenames(total_files); + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < image_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) + { + filenames[f++] = GenerateRenderTargetImageFilename(resource_info, aspect, mip, layer); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + + std::vector scaling_supported(filenames.size()); + VkResult res = DumpImageToFile(image_info, + resource_info.device_info, + resource_info.device_table, + resource_info.instance_table, + *resource_info.object_info_table, + filenames, + options_.dump_resources_scale, + scaling_supported, + options_.dump_resources_image_format, + options_.dump_resources_dump_all_image_subresources, + options_.dump_resources_dump_raw_images, + options_.dump_resources_dump_separate_alpha, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + &resource_info.image_extent); + + if (res != VK_SUCCESS) + { + GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) + return res; + } + + // Keep track of images for which scaling failed + for (size_t i = 0; i < filenames.size(); ++i) + { + if (!scaling_supported[i]) + { + images_failed_scaling_.insert(filenames[i]); + } + } + return res; +} + +std::string DefaultVulkanDumpResourcesDelegate::GenerateRenderTargetImageFilename( + const VulkanDumpResourceInfo& resource_info, VkImageAspectFlagBits aspect, uint32_t mip_level, uint32_t layer) const +{ + const VulkanImageInfo* image_info = resource_info.image_info; + std::string aspect_str = ImageAspectToStr(aspect); + std::string attachment_str = resource_info.attachment_index != DEPTH_ATTACHMENT + ? "_att_" + std::to_string(resource_info.attachment_index) + : "_depth_att"; + + std::stringstream filename; + filename << capture_filename_ << "_"; + + const DumpedImageFormat output_image_format = GetDumpedImageFormat(resource_info.device_info, + resource_info.device_table, + resource_info.instance_table, + *resource_info.object_info_table, + image_info->format, + image_info->tiling, + image_info->type, + options_.dump_resources_image_format, + options_.dump_resources_dump_raw_images); + + if (output_image_format != KFormatRaw) + { + if (options_.dump_resources_before) + { + filename << "draw_" << ((!resource_info.before_cmd) ? "after_" : "before_") << resource_info.cmd_index + << "_qs_" << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << attachment_str + << "_aspect_" << aspect_str; + } + else + { + filename << "draw_" << resource_info.cmd_index << "_qs_" << resource_info.qs_index << "_bcb_" + << resource_info.bcb_index << attachment_str << "_aspect_" << aspect_str; + } + } + else + { + if (options_.dump_resources_before) + { + filename << "draw_" << ((!resource_info.before_cmd) ? "after_" : "before_") << resource_info.cmd_index + << "_qs_" << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << "_" + << resource_info.qs_index << "_" << resource_info.bcb_index << attachment_str << "_" + << util::ToString(image_info->format) << "_aspect_" << aspect_str; + } + else + { + filename << "draw_" << resource_info.cmd_index << "_qs_" << resource_info.qs_index << "_bcb_" + << resource_info.bcb_index << attachment_str << "_" << util::ToString(image_info->format) + << "_aspect_" << aspect_str; + } + } + + if (options_.dump_resources_dump_all_image_subresources) + { + std::stringstream subresource_sting; + subresource_sting << "_mip_" << mip_level << "_layer_" << layer; + subresource_sting << ImageFileExtension(output_image_format); + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str() + subresource_sting.str()); + return (filedirname / filebasename).string(); + } + else + { + filename << ImageFileExtension(output_image_format); + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + return (filedirname / filebasename).string(); + } +} + +VkResult DefaultVulkanDumpResourcesDelegate::DumpImageDescriptor(const VulkanDumpResourceInfo& resource_info) +{ + const VulkanImageInfo* image_info = resource_info.image_info; + + std::vector aspects; + GetFormatAspects(image_info->format, aspects); + + const size_t total_files = options_.dump_resources_dump_all_image_subresources + ? (aspects.size() * image_info->layer_count * image_info->level_count) + : aspects.size(); + + std::vector filenames(total_files); + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < image_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) + { + filenames[f++] = GenerateImageDescriptorFilename(resource_info, aspect, mip, layer); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + + std::vector scaling_supported(total_files); + VkResult res = DumpImageToFile(image_info, + resource_info.device_info, + resource_info.device_table, + resource_info.instance_table, + *resource_info.object_info_table, + filenames, + options_.dump_resources_scale, + scaling_supported, + options_.dump_resources_image_format, + options_.dump_resources_dump_all_image_subresources, + options_.dump_resources_dump_raw_images, + options_.dump_resources_dump_separate_alpha); + if (res != VK_SUCCESS) + { + GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) + return res; + } + + // Keep track of images for which scaling failed + for (size_t i = 0; i < filenames.size(); ++i) + { + if (!scaling_supported[i]) + { + images_failed_scaling_.insert(filenames[i]); + } + } + return res; +} + +std::string DefaultVulkanDumpResourcesDelegate::GenerateImageDescriptorFilename( + const VulkanDumpResourceInfo& resource_info, VkImageAspectFlagBits aspect, uint32_t mip_level, uint32_t layer) const +{ + const VulkanImageInfo* image_info = resource_info.image_info; + std::string aspect_str = ImageAspectToStr(aspect); + std::stringstream base_filename; + base_filename << capture_filename_ << "_"; + + const DumpedImageFormat output_image_format = GetDumpedImageFormat(resource_info.device_info, + resource_info.device_table, + resource_info.instance_table, + *resource_info.object_info_table, + image_info->format, + image_info->tiling, + image_info->type, + options_.dump_resources_image_format, + options_.dump_resources_dump_raw_images); + + if (output_image_format != KFormatRaw) + { + base_filename << "image_" << image_info->capture_id << "_qs_" << resource_info.qs_index << "_bcb_" + << resource_info.bcb_index << "_rp_" << resource_info.rp << "_aspect_" << aspect_str; + } + else + { + std::string whole_format_name = util::ToString(image_info->format); + std::string format_name(whole_format_name.begin() + 10, whole_format_name.end()); + + base_filename << "image_" << image_info->capture_id << "_qs_" << resource_info.qs_index << "_bcb_" + << resource_info.bcb_index << "_rp_" << resource_info.rp << "_" << format_name << "_aspect_" + << aspect_str; + } + + if (options_.dump_resources_dump_all_image_subresources) + { + std::stringstream sub_resources_str; + sub_resources_str << base_filename.str() << "_mip_" << mip_level << "_layer_" << layer; + sub_resources_str << ImageFileExtension(output_image_format); + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(sub_resources_str.str()); + return (filedirname / filebasename).string(); + } + else + { + base_filename << ImageFileExtension(output_image_format); + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(base_filename.str()); + return (filedirname / filebasename).string(); + } +} + +VkResult DefaultVulkanDumpResourcesDelegate::DumpBufferDescriptor(const VulkanDumpResourceInfo& resource_info) +{ + const std::string filename = GenerateBufferDescriptorFilename(resource_info); + return util::bufferwriter::WriteBuffer(filename, resource_info.data.data(), resource_info.data.size()) + ? VK_SUCCESS + : VK_ERROR_UNKNOWN; +} + +std::string +DefaultVulkanDumpResourcesDelegate::GenerateBufferDescriptorFilename(const VulkanDumpResourceInfo& resource_info) const +{ + std::stringstream filename; + + filename << capture_filename_ << "_" + << "buffer_" << resource_info.buffer_info->capture_id << "_qs_" << resource_info.qs_index << "_bcb_" + << resource_info.bcb_index << "_rp_" << resource_info.rp << ".bin"; + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + return (filedirname / filebasename).string(); +} + +VkResult +DefaultVulkanDumpResourcesDelegate::DumpInlineUniformBufferDescriptor(const VulkanDumpResourceInfo& resource_info) +{ + std::string filename = GenerateInlineUniformBufferDescriptorFilename(resource_info); + return util::bufferwriter::WriteBuffer(filename, resource_info.data.data(), resource_info.data.size()) + ? VK_SUCCESS + : VK_ERROR_UNKNOWN; +} + +std::string DefaultVulkanDumpResourcesDelegate::GenerateInlineUniformBufferDescriptorFilename( + const VulkanDumpResourceInfo& resource_info) const +{ + std::stringstream filename; + filename << capture_filename_ << "_" + << "inlineUniformBlock_set_" << resource_info.set << "_binding_" << resource_info.binding << "_qs_" + << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << ".bin"; + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + return (filedirname / filebasename).string(); +} + +VkResult DefaultVulkanDumpResourcesDelegate::DumpVertexBuffer(const VulkanDumpResourceInfo& resource_info) +{ + std::string filename = GenerateVertexBufferFilename(resource_info); + return util::bufferwriter::WriteBuffer(filename, resource_info.data.data(), resource_info.data.size()) + ? VK_SUCCESS + : VK_ERROR_UNKNOWN; +} + +std::string +DefaultVulkanDumpResourcesDelegate::GenerateVertexBufferFilename(const VulkanDumpResourceInfo& resource_info) const +{ + std::stringstream filename; + filename << capture_filename_ << "_" + << "vertexBuffers_" + << "qs_" << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << "_dc_" + << resource_info.cmd_index << "_binding_" << resource_info.binding << ".bin"; + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + return (filedirname / filebasename).string(); +} + +VkResult DefaultVulkanDumpResourcesDelegate::DumpIndexBuffer(const VulkanDumpResourceInfo& resource_info) +{ + std::string filename = GenerateIndexBufferFilename(resource_info); + return util::bufferwriter::WriteBuffer(filename, resource_info.data.data(), resource_info.data.size()) + ? VK_SUCCESS + : VK_ERROR_UNKNOWN; +} + +std::string +DefaultVulkanDumpResourcesDelegate::GenerateIndexBufferFilename(const VulkanDumpResourceInfo& resource_info) const +{ + std::stringstream filename; + filename << capture_filename_ << "_"; + std::string index_type_name = IndexTypeToStr(resource_info.index_type); + filename << "indexBuffer_" + << "qs_" << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << "_dc_" + << resource_info.cmd_index << index_type_name << ".bin"; + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + return (filedirname / filebasename).string(); +} + +void DefaultVulkanDumpResourcesDelegate::GenerateOutputJsonDrawCallInfo(const VulkanDumpDrawCallInfo& draw_call_info, + size_t index) +{ + if (options_.dump_resources_json_per_command) + { + std::stringstream filename; + filename << capture_filename_ << "_"; + filename << "DrawCall_" << draw_call_info.cmd_index << "_qs_" << draw_call_info.qs_index << "_bcb_" + << draw_call_info.bcb_index << "_dr.json"; + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + std::string full_filename = (filedirname / filebasename).string(); + + dump_json_.Open(full_filename); + dump_json_.BlockStart(); + } + + auto& current_block = dump_json_.GetCurrentSubEntry(); + auto& drawcall_json_entries = + !options_.dump_resources_json_per_command ? current_block["drawCallCommands"] : current_block; + auto& draw_call_entry = + !options_.dump_resources_json_per_command ? drawcall_json_entries[index] : drawcall_json_entries; + + draw_call_entry["drawIndex"] = draw_call_info.cmd_index; + draw_call_entry["beginCommandBufferIndex"] = draw_call_info.bcb_index; + draw_call_entry["queueSubmitIndex"] = draw_call_info.qs_index; + + // Write draw call params + auto& dc_params_json_entry = draw_call_entry["parameters"]; + dc_params_json_entry["drawCallType"] = DrawCallsDumpingContext::DrawCallTypeToStr(draw_call_info.dc_param->type); + switch (draw_call_info.dc_param->type) + { + case DrawCallsDumpingContext::DrawCallTypes::kDraw: + { + const VkDrawIndirectCommand& dc_params = draw_call_info.dc_param->dc_params_union.draw; + + dc_params_json_entry["vertexCount"] = dc_params.vertexCount; + dc_params_json_entry["instanceCount"] = dc_params.instanceCount; + dc_params_json_entry["firstVertex"] = dc_params.firstVertex; + dc_params_json_entry["firstInstance"] = dc_params.firstInstance; + } + break; + + case DrawCallsDumpingContext::DrawCallTypes::kDrawIndexed: + { + const VkDrawIndexedIndirectCommand& dc_params = draw_call_info.dc_param->dc_params_union.draw_indexed; + + dc_params_json_entry["indexCount"] = dc_params.indexCount; + dc_params_json_entry["instanceCount"] = dc_params.instanceCount; + dc_params_json_entry["firstIndex"] = dc_params.firstIndex; + dc_params_json_entry["vertexOffset"] = dc_params.vertexOffset; + dc_params_json_entry["firstInstance"] = dc_params.firstInstance; + } + break; + + case DrawCallsDumpingContext::DrawCallTypes::kDrawIndirect: + { + const auto& dc_params = draw_call_info.dc_param->dc_params_union.draw_indirect; + + assert((dc_params.draw_count && dc_params.draw_params != nullptr) || !dc_params.draw_count); + + dc_params_json_entry["drawCount"] = dc_params.draw_count; + auto& indirect_param_entries = dc_params_json_entry["indirectParams"]; + for (uint32_t di = 0; di < dc_params.draw_count; ++di) + { + indirect_param_entries[di]["vertexCount"] = dc_params.draw_params[di].vertexCount; + indirect_param_entries[di]["instanceCount"] = dc_params.draw_params[di].instanceCount; + indirect_param_entries[di]["firstVertex"] = dc_params.draw_params[di].firstVertex; + indirect_param_entries[di]["firstInstance"] = dc_params.draw_params[di].firstInstance; + } + } + break; + + case DrawCallsDumpingContext::DrawCallTypes::kDrawIndexedIndirect: + { + const auto& dc_params = draw_call_info.dc_param->dc_params_union.draw_indirect; + + assert((dc_params.draw_count && dc_params.draw_indexed_params != nullptr) || !dc_params.draw_count); + + dc_params_json_entry["drawCount"] = dc_params.draw_count; + auto& indirect_param_entries = dc_params_json_entry["indirectParams"]; + for (uint32_t di = 0; di < dc_params.draw_count; ++di) + { + indirect_param_entries[di]["indexCount"] = dc_params.draw_indexed_params[di].indexCount; + indirect_param_entries[di]["instanceCount"] = dc_params.draw_indexed_params[di].instanceCount; + indirect_param_entries[di]["firstIndex"] = dc_params.draw_indexed_params[di].firstIndex; + indirect_param_entries[di]["vertexOffset"] = dc_params.draw_indexed_params[di].vertexOffset; + indirect_param_entries[di]["firstInstance"] = dc_params.draw_indexed_params[di].firstInstance; + } + } + break; + + case DrawCallsDumpingContext::DrawCallTypes::kDrawIndirectCount: + case DrawCallsDumpingContext::DrawCallTypes::kDrawIndirectCountKHR: + { + const auto& dc_params = draw_call_info.dc_param->dc_params_union.draw_indirect_count; + + dc_params_json_entry["maxDrawCount"] = dc_params.max_draw_count; + dc_params_json_entry["actualDrawCount"] = dc_params.actual_draw_count; + + auto& indirect_param_entries = dc_params_json_entry["indirectParams"]; + for (uint32_t di = 0; di < dc_params.actual_draw_count; ++di) + { + indirect_param_entries[di]["vertexCount"] = dc_params.draw_params[di].vertexCount; + indirect_param_entries[di]["instanceCount"] = dc_params.draw_params[di].instanceCount; + indirect_param_entries[di]["firstVertex"] = dc_params.draw_params[di].firstVertex; + indirect_param_entries[di]["firstInstance"] = dc_params.draw_params[di].firstInstance; + } + } + break; + + case DrawCallsDumpingContext::DrawCallTypes::kDrawIndexedIndirectCount: + case DrawCallsDumpingContext::DrawCallTypes::kDrawIndexedIndirectCountKHR: + { + const auto& dc_params = draw_call_info.dc_param->dc_params_union.draw_indirect_count; + + dc_params_json_entry["maxDrawCount"] = dc_params.max_draw_count; + dc_params_json_entry["actualDrawCount"] = dc_params.actual_draw_count; + + auto& indirect_param_entries = dc_params_json_entry["indirectParams"]; + for (uint32_t di = 0; di < dc_params.actual_draw_count; ++di) + { + indirect_param_entries[di]["indexCount"] = dc_params.draw_indexed_params[di].indexCount; + indirect_param_entries[di]["instanceCount"] = dc_params.draw_indexed_params[di].instanceCount; + indirect_param_entries[di]["firstIndex"] = dc_params.draw_indexed_params[di].firstIndex; + indirect_param_entries[di]["vertexOffset"] = dc_params.draw_indexed_params[di].vertexOffset; + indirect_param_entries[di]["firstInstance"] = dc_params.draw_indexed_params[di].firstInstance; + } + } + break; + + default: + assert(0); + } + + VulkanDumpResourceInfo res_info_base{}; + res_info_base = draw_call_info; + + // Write color attachment info + if (draw_call_info.render_targets != nullptr && !draw_call_info.render_targets->color_att_imgs.empty()) + { + auto& rt_entries = draw_call_entry["colorAttachments"]; + + size_t f = 0; + for (size_t i = 0; i < draw_call_info.render_targets->color_att_imgs.size(); ++i) + { + if (options_.dump_resources_color_attachment_index != kUnspecifiedColorAttachment && + static_cast(options_.dump_resources_color_attachment_index) != i) + { + continue; + } + + const VulkanImageInfo* image_info = draw_call_info.render_targets->color_att_imgs[i]; + assert(image_info != nullptr); + + std::vector aspects; + GetFormatAspects(image_info->format, aspects); + + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < image_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) + { + std::string filenameBefore; + if (options_.dump_resources_before) + { + VulkanDumpResourceInfo res_info_before = res_info_base; + res_info_before.type = DumpResourceType::kRtv; + res_info_before.image_info = image_info; + res_info_before.attachment_index = i; + res_info_before.before_cmd = true; + filenameBefore = GenerateRenderTargetImageFilename(res_info_before, aspect, mip, layer); + } + + VulkanDumpResourceInfo res_info_after = res_info_base; + res_info_after.type = DumpResourceType::kRtv; + res_info_after.image_info = image_info; + res_info_after.attachment_index = i; + res_info_after.before_cmd = false; + std::string filenameAfter = + GenerateRenderTargetImageFilename(res_info_after, aspect, mip, layer); + + const VkExtent3D extent = { std::max(1u, image_info->extent.width >> mip), + std::max(1u, image_info->extent.height >> mip), + image_info->extent.depth }; + + dump_json_.InsertImageInfo(rt_entries[f++], + image_info->format, + image_info->type, + image_info->capture_id, + extent, + filenameAfter, + aspect, + ImageFailedScaling(filenameAfter), + mip, + layer, + options_.dump_resources_dump_separate_alpha, + options_.dump_resources_before ? &filenameBefore : nullptr); + + // Skip rest of layers + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + // Skip rest of mip map levels + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + } + } + + // Write depth attachment info + if (options_.dump_resources_dump_depth && draw_call_info.render_targets != nullptr && + draw_call_info.render_targets->depth_att_img != nullptr) + { + auto& depth_entries = draw_call_entry["depthAttachments"]; + + const VulkanImageInfo* image_info = draw_call_info.render_targets->depth_att_img; + + std::vector aspects; + GetFormatAspects(image_info->format, aspects); + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < image_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) + { + std::string filenameBefore; + if (options_.dump_resources_before) + { + VulkanDumpResourceInfo res_info_before = res_info_base; + res_info_before.type = DumpResourceType::kDsv; + res_info_before.image_info = image_info; + res_info_before.attachment_index = DEPTH_ATTACHMENT; + res_info_before.before_cmd = true; + filenameBefore = GenerateRenderTargetImageFilename(res_info_before, aspect, mip, layer); + } + + VulkanDumpResourceInfo res_info_after = res_info_base; + res_info_after.type = DumpResourceType::kDsv; + res_info_after.image_info = image_info; + res_info_after.attachment_index = DEPTH_ATTACHMENT; + res_info_after.before_cmd = false; + std::string filenameAfter = GenerateRenderTargetImageFilename(res_info_after, aspect, mip, layer); + + const VkExtent3D extent = { std::max(1u, image_info->extent.width >> mip), + std::max(1u, image_info->extent.height >> mip), + image_info->extent.depth }; + + dump_json_.InsertImageInfo(depth_entries[f++], + image_info->format, + image_info->type, + image_info->capture_id, + extent, + filenameAfter, + aspect, + ImageFailedScaling(filenameAfter), + mip, + layer, + options_.dump_resources_dump_separate_alpha, + options_.dump_resources_before ? &filenameBefore : nullptr); + + // Skip rest of layers + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + // Skip rest of mip map levels + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + } + + // Emit in json output the references to vertex and index buffers dumped files + if (options_.dump_resources_dump_vertex_index_buffer) + { + if (DrawCallsDumpingContext::IsDrawCallIndexed(draw_call_info.dc_param->type)) + { + if (draw_call_info.dc_param->referenced_index_buffer.buffer_info != nullptr) + { + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kIndex; + res_info.index_type = draw_call_info.dc_param->referenced_index_buffer.index_type; + const std::string index_buffer_filename = GenerateIndexBufferFilename(res_info); + + auto& json_entry = draw_call_entry["indexBuffer"]; + + dump_json_.InsertBufferInfo( + json_entry, draw_call_info.dc_param->referenced_index_buffer.buffer_info, index_buffer_filename); + } + } + + if (!draw_call_info.dc_param->referenced_vertex_buffers.bound_vertex_buffer_per_binding.empty() && + !draw_call_info.dc_param->vertex_input_state.vertex_input_binding_map.empty()) + { + auto& json_entry = draw_call_entry["vertexBuffers"]; + + uint32_t i = 0; + for (const auto& vb_binding : draw_call_info.dc_param->vertex_input_state.vertex_input_binding_map) + { + const auto& vb_binding_buffer = + draw_call_info.dc_param->referenced_vertex_buffers.bound_vertex_buffer_per_binding.find( + vb_binding.first); + assert(vb_binding_buffer != + draw_call_info.dc_param->referenced_vertex_buffers.bound_vertex_buffer_per_binding.end()); + + if (vb_binding_buffer->second.buffer_info != nullptr) + { + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kVertex; + res_info.binding = vb_binding.first; + const std::string vb_filename = GenerateVertexBufferFilename(res_info); + + json_entry[i]["bufferId"] = vb_binding_buffer->second.buffer_info->capture_id; + json_entry[i]["vertexBufferBinding"] = vb_binding.first; + json_entry[i]["file"] = vb_filename; + ++i; + } + } + } + } + + // Emit in json output the references to dumped immutable descriptors + if (options_.dump_resources_dump_immutable_resources) + { + for (const auto& shader_stage : draw_call_info.dc_param->referenced_descriptors) + { + uint32_t stage_entry_index = 0; + for (const auto& desc_set : shader_stage.second) + { + const uint32_t desc_set_index = desc_set.first; + for (const auto& desc_binding : desc_set.second) + { + const uint32_t desc_set_binding_index = desc_binding.first; + switch (desc_binding.second.desc_type) + { + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + { + for (size_t img = 0; img < desc_binding.second.image_info.size(); ++img) + { + if (desc_binding.second.image_info[img].image_view_info == nullptr) + { + continue; + } + + auto& desc_shader_stage_json_entry = + draw_call_entry["descriptors"][ShaderStageToStr(shader_stage.first)]; + auto& desc_shader_binding_json_entry = + desc_shader_stage_json_entry[stage_entry_index++]; + + desc_shader_binding_json_entry["type"] = + util::ToString(desc_binding.second.desc_type); + desc_shader_binding_json_entry["set"] = desc_set_index; + desc_shader_binding_json_entry["binding"] = desc_set_binding_index; + desc_shader_binding_json_entry["arrayIndex"] = img; + + const VulkanImageInfo* image_info = draw_call_info.object_info_table->GetVkImageInfo( + desc_binding.second.image_info[img].image_view_info->image_id); + assert(image_info != nullptr); + + std::vector aspects; + GetFormatAspects(image_info->format, aspects); + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kImageDescriptor; + res_info.image_info = image_info; + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < image_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) + { + std::string filename = + GenerateImageDescriptorFilename(res_info, aspect, mip, layer); + const VkExtent3D extent = { std::max(1u, image_info->extent.width >> mip), + std::max(1u, image_info->extent.height >> mip), + image_info->extent.depth }; + + auto& image_descriptor_json_entry = + desc_shader_binding_json_entry["descriptor"]; + dump_json_.InsertImageInfo(image_descriptor_json_entry[f++], + image_info->format, + image_info->type, + image_info->capture_id, + extent, + filename, + aspect, + ImageFailedScaling(filename), + mip, + layer, + options_.dump_resources_dump_separate_alpha); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + } + } + break; + + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + { + for (size_t buf = 0; buf < desc_binding.second.buffer_info.size(); ++buf) + { + const VulkanBufferInfo* buf_info = desc_binding.second.buffer_info[buf].buffer_info; + if (buf_info != nullptr) + { + auto& desc_shader_stage_json_entry = + draw_call_entry["descriptors"][ShaderStageToStr(shader_stage.first)]; + auto& desc_shader_binding_json_entry = + desc_shader_stage_json_entry[stage_entry_index++]; + + desc_shader_binding_json_entry["type"] = + util::ToString(desc_binding.second.desc_type); + desc_shader_binding_json_entry["set"] = desc_set_index; + desc_shader_binding_json_entry["binding"] = desc_set_binding_index; + desc_shader_binding_json_entry["arrayIndex"] = buf; + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kBufferDescriptor; + res_info.buffer_info = buf_info; + + const std::string filename = GenerateBufferDescriptorFilename(res_info); + auto& buffer_descriptor_json_entry = desc_shader_binding_json_entry["descriptor"]; + dump_json_.InsertBufferInfo(buffer_descriptor_json_entry, buf_info, filename); + } + } + } + break; + + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: + { + auto& desc_shader_stage_json_entry = + draw_call_entry["descriptors"][ShaderStageToStr(shader_stage.first)]; + auto& desc_shader_binding_json_entry = desc_shader_stage_json_entry[stage_entry_index++]; + + desc_shader_binding_json_entry["type"] = + util::ToString(desc_binding.second.desc_type); + desc_shader_binding_json_entry["set"] = desc_set_index; + desc_shader_binding_json_entry["binding"] = desc_set_binding_index; + desc_shader_binding_json_entry["size"] = desc_binding.second.inline_uniform_block.size(); + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kInlineUniformBufferDescriptor; + res_info.set = desc_set_index; + res_info.binding = desc_set_binding_index; + desc_shader_binding_json_entry["file"] = + GenerateInlineUniformBufferDescriptorFilename(res_info); + } + break; + + default: + break; + } + } + } + } + } + + if (options_.dump_resources_json_per_command) + { + dump_json_.BlockEnd(); + dump_json_.Close(); + } +} + +VkResult DefaultVulkanDumpResourcesDelegate::DumpeDispatchTraceRaysImage(const VulkanDumpResourceInfo& resource_info) +{ + const VulkanImageInfo* image_info = resource_info.image_info; + + std::vector aspects; + GetFormatAspects(image_info->format, aspects); + + const size_t total_files = options_.dump_resources_dump_all_image_subresources + ? (aspects.size() * image_info->layer_count * image_info->level_count) + : aspects.size(); + + std::vector filenames(total_files); + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < image_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) + { + filenames[f++] = GenerateDispatchTraceRaysImageFilename(resource_info, mip, layer, aspect); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + + std::vector scaling_supported(filenames.size()); + VkResult res = DumpImageToFile(image_info, + resource_info.device_info, + resource_info.device_table, + resource_info.instance_table, + *resource_info.object_info_table, + filenames, + options_.dump_resources_scale, + scaling_supported, + options_.dump_resources_image_format, + false, + options_.dump_resources_dump_raw_images, + options_.dump_resources_dump_separate_alpha, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + if (res != VK_SUCCESS) + { + GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) + return res; + } + + // Keep track of images for which scaling failed + for (size_t i = 0; i < filenames.size(); ++i) + { + if (!scaling_supported[i]) + { + images_failed_scaling_.insert(filenames[i]); + } + } + return res; +} + +std::string DefaultVulkanDumpResourcesDelegate::GenerateDispatchTraceRaysImageFilename( + const VulkanDumpResourceInfo& resource_info, uint32_t mip_level, uint32_t layer, VkImageAspectFlagBits aspect) const +{ + const VulkanImageInfo* image_info = resource_info.image_info; + const DumpedImageFormat output_image_format = GetDumpedImageFormat(resource_info.device_info, + resource_info.device_table, + resource_info.instance_table, + *resource_info.object_info_table, + image_info->format, + image_info->tiling, + image_info->type, + options_.dump_resources_image_format, + options_.dump_resources_dump_raw_images); + + const std::string shader_stage_name = ShaderStageToStr(resource_info.stage); + const std::string aspect_str = ImageAspectToStr(aspect); + + std::stringstream filename; + filename << capture_filename_ << '_'; + + if (resource_info.before_cmd) + { + filename << (resource_info.is_dispatch ? "dispatch_" : "traceRays_") << resource_info.cmd_index << "_qs_" + << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << "_before_stage_" + << shader_stage_name << "_set_" << resource_info.set << "_binding_" << resource_info.binding + << "_index_" << resource_info.array_index; + if (output_image_format != KFormatRaw) + { + filename << "_" << util::ToString(image_info->format).c_str(); + } + filename << "_aspect_" << aspect_str; + } + else + { + filename << (resource_info.is_dispatch ? "dispatch_" : "traceRays_") << resource_info.cmd_index << "_qs_" + << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << "_" + << (options_.dump_resources_before ? "after_" : "") << "stage_" << shader_stage_name << "_set_" + << resource_info.set << "_binding_" << resource_info.binding << "_index_" << resource_info.array_index; + if (output_image_format != KFormatRaw) + { + filename << "_" << util::ToString(image_info->format).c_str(); + } + filename << "_aspect_" << aspect_str; + } + + if (options_.dump_resources_dump_all_image_subresources) + { + filename << "_mip_" << mip_level << "_layer_" << layer; + } + + filename << ImageFileExtension(output_image_format); + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + return (filedirname / filebasename).string(); +} + +VkResult DefaultVulkanDumpResourcesDelegate::DumpeDispatchTraceRaysBuffer(const VulkanDumpResourceInfo& resource_info) +{ + std::string filename = GenerateDispatchTraceRaysBufferFilename(resource_info); + return util::bufferwriter::WriteBuffer(filename, resource_info.data.data(), resource_info.data.size()) + ? VK_SUCCESS + : VK_ERROR_UNKNOWN; +} + +std::string DefaultVulkanDumpResourcesDelegate::GenerateDispatchTraceRaysBufferFilename( + const VulkanDumpResourceInfo& resource_info) const +{ + std::stringstream filename; + + filename << capture_filename_ << '_'; + + const std::string shader_stage_name = ShaderStageToStr(resource_info.stage); + + if (resource_info.before_cmd) + { + filename << (resource_info.is_dispatch ? "dispatch_" : "traceRays_") << resource_info.cmd_index << "_qs_" + << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << "_before_stage_" + << shader_stage_name << "_set_" << resource_info.set << "_binding_" << resource_info.binding + << "_index_" << resource_info.array_index << "_buffer.bin"; + } + else + { + filename << (resource_info.is_dispatch ? "dispatch_" : "traceRays_") << resource_info.cmd_index << "_qs_" + << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << "_" + << (options_.dump_resources_before ? "after_" : "") << "stage_" << shader_stage_name << "_set_" + << resource_info.set << "_binding_" << resource_info.binding << "_index_" << resource_info.array_index + << "_buffer.bin"; + } + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + return (filedirname / filebasename).string(); +} + +VkResult +DefaultVulkanDumpResourcesDelegate::DumpDispatchTraceRaysImageDescriptor(const VulkanDumpResourceInfo& resource_info) +{ + const VulkanImageInfo* image_info = resource_info.image_info; + + std::vector aspects; + GetFormatAspects(image_info->format, aspects); + + const size_t total_files = options_.dump_resources_dump_all_image_subresources + ? (aspects.size() * image_info->layer_count * image_info->level_count) + : aspects.size(); + + std::vector filenames(total_files); + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < image_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) + { + filenames[f++] = GenerateDispatchTraceRaysImageDescriptorFilename(resource_info, mip, layer, aspect); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + + std::vector scaling_supported(filenames.size()); + VkResult res = DumpImageToFile(image_info, + resource_info.device_info, + resource_info.device_table, + resource_info.instance_table, + *resource_info.object_info_table, + filenames, + options_.dump_resources_scale, + scaling_supported, + options_.dump_resources_image_format, + options_.dump_resources_dump_all_image_subresources, + options_.dump_resources_dump_raw_images); + if (res != VK_SUCCESS) + { + GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) + return res; + } + + // Keep track of images for which scaling failed + for (size_t i = 0; i < filenames.size(); ++i) + { + if (!scaling_supported[i]) + { + images_failed_scaling_.insert(filenames[i]); + } + } + return res; +} + +std::string DefaultVulkanDumpResourcesDelegate::GenerateDispatchTraceRaysImageDescriptorFilename( + const VulkanDumpResourceInfo& resource_info, uint32_t mip_level, uint32_t layer, VkImageAspectFlagBits aspect) const +{ + const VulkanImageInfo* image_info = resource_info.image_info; + std::string aspect_str = ImageAspectToStr(aspect); + std::stringstream base_filename; + + base_filename << capture_filename_ << '_'; + + const DumpedImageFormat output_image_format = GetDumpedImageFormat(resource_info.device_info, + resource_info.device_table, + resource_info.instance_table, + *resource_info.object_info_table, + image_info->format, + image_info->tiling, + image_info->type, + options_.dump_resources_image_format, + options_.dump_resources_dump_raw_images); + + if (output_image_format != KFormatRaw) + { + base_filename << "image_" << image_info->capture_id << "_qs_" << resource_info.qs_index << "_bcb_" + << resource_info.bcb_index << "_aspect_" << aspect_str; + } + else + { + std::string format_name = FormatToStr(image_info->format); + base_filename << "image_" << image_info->capture_id << "_qs_" << resource_info.qs_index << "_bcb_" + << resource_info.bcb_index << "_" << format_name << "_aspect_" << aspect_str; + } + + if (options_.dump_resources_dump_all_image_subresources) + { + std::stringstream sub_resources_str; + sub_resources_str << base_filename.str() << "_mip_" << mip_level << "_layer_" << layer; + sub_resources_str << ImageFileExtension(output_image_format); + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(sub_resources_str.str()); + return (filedirname / filebasename).string(); + } + else + { + base_filename << ImageFileExtension(output_image_format); + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(base_filename.str()); + return (filedirname / filebasename).string(); + } +} + +VkResult +DefaultVulkanDumpResourcesDelegate::DumpDispatchTraceRaysBufferDescriptor(const VulkanDumpResourceInfo& resource_info) +{ + const std::string filename = GenerateDispatchTraceRaysBufferDescriptorFilename(resource_info); + return util::bufferwriter::WriteBuffer(filename, resource_info.data.data(), resource_info.data.size()) + ? VK_SUCCESS + : VK_ERROR_UNKNOWN; +} + +std::string DefaultVulkanDumpResourcesDelegate::GenerateDispatchTraceRaysBufferDescriptorFilename( + const VulkanDumpResourceInfo& resource_info) const +{ + std::stringstream filename; + + filename << capture_filename_ << "_buffer_" << resource_info.buffer_info->capture_id << "_qs_" + << resource_info.qs_index << "_bcb_" << resource_info.bcb_index << ".bin"; + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + return (filedirname / filebasename).string(); +} + +VkResult DefaultVulkanDumpResourcesDelegate::DumpDispatchTraceRaysInlineUniformBufferDescriptor( + const VulkanDumpResourceInfo& resource_info) +{ + std::string filename = GenerateDispatchTraceRaysInlineUniformBufferDescriptorFilename(resource_info); + return util::bufferwriter::WriteBuffer(filename, resource_info.data.data(), resource_info.data.size()) + ? VK_SUCCESS + : VK_ERROR_UNKNOWN; +} + +std::string DefaultVulkanDumpResourcesDelegate::GenerateDispatchTraceRaysInlineUniformBufferDescriptorFilename( + const VulkanDumpResourceInfo& resource_info) const +{ + std::stringstream filename; + filename << capture_filename_ << '_' << "inlineUniformBlock_set_" << resource_info.set << "_binding_" + << resource_info.binding << "_qs_" << resource_info.qs_index << "_bcb_" << resource_info.bcb_index + << ".bin"; + + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + return (filedirname / filebasename).string(); +} + +void DefaultVulkanDumpResourcesDelegate::GenerateOutputJsonDispatchInfo(const VulkanDumpDrawCallInfo& draw_call_info, + size_t index) +{ + if (draw_call_info.disp_param == nullptr) + { + return; + } + + if (options_.dump_resources_json_per_command) + { + std::stringstream filename; + filename << "Dispatch_" << draw_call_info.cmd_index << "_qs_" << draw_call_info.qs_index << "_bcb_" + << draw_call_info.bcb_index << "_dr.json"; + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + std::string full_filename = (filedirname / filebasename).string(); + + dump_json_.Open(full_filename); + dump_json_.BlockStart(); + } + + auto& current_block = dump_json_.GetCurrentSubEntry(); + auto& dispatch_json_entries = + !options_.dump_resources_json_per_command ? current_block["dispatchCommands"] : dump_json_.GetData(); + auto& dispatch_json_entry = + !options_.dump_resources_json_per_command ? dispatch_json_entries[index] : dump_json_.GetData(); + + dispatch_json_entry["dispatchIndex"] = draw_call_info.cmd_index; + dispatch_json_entry["beginCommandBufferIndex"] = draw_call_info.bcb_index; + dispatch_json_entry["queueSubmitIndex"] = draw_call_info.qs_index; + + auto& params_json_entries = dispatch_json_entry["parameters"]; + params_json_entries["dispatchType"] = + DispatchTraceRaysDumpingContext::DispatchTypeToStr(draw_call_info.disp_param->type); + switch (draw_call_info.disp_param->type) + { + case DispatchTraceRaysDumpingContext::DispatchTypes::kDispatch: + { + const auto& ds_params = draw_call_info.disp_param->dispatch_params_union.dispatch; + + params_json_entries["groupCountX"] = ds_params.groupCountX; + params_json_entries["groupCountY"] = ds_params.groupCountY; + params_json_entries["groupCountZ"] = ds_params.groupCountZ; + } + break; + + case DispatchTraceRaysDumpingContext::DispatchTypes::kDispatchIndirect: + { + const auto& ds_params = draw_call_info.disp_param->dispatch_params_union.dispatch_indirect; + + assert(ds_params.dispatch_params != nullptr); + params_json_entries["groupCountX"] = ds_params.dispatch_params->groupCountX; + params_json_entries["groupCountY"] = ds_params.dispatch_params->groupCountY; + params_json_entries["groupCountZ"] = ds_params.dispatch_params->groupCountZ; + } + break; + + case DispatchTraceRaysDumpingContext::DispatchTypes::kDispatchBase: + { + const auto& ds_params = draw_call_info.disp_param->dispatch_params_union.dispatch_base; + + params_json_entries["baseGroupX"] = ds_params.baseGroupX; + params_json_entries["baseGroupY"] = ds_params.baseGroupY; + params_json_entries["baseGroupZ"] = ds_params.baseGroupZ; + params_json_entries["groupCountX"] = ds_params.groupCountX; + params_json_entries["groupCountY"] = ds_params.groupCountY; + params_json_entries["groupCountZ"] = ds_params.groupCountZ; + } + break; + + default: + assert(0); + } + + auto& outputs_json_entries = dispatch_json_entry["outputs"]; + + VulkanDumpResourceInfo res_info_base{}; + res_info_base = draw_call_info; + + if (options_.dump_resources_before) + { + const auto& mutable_resource_entry_before = draw_call_info.disp_param->mutable_resources_clones_before; + if (!mutable_resource_entry_before.images.empty()) + { + auto& before_command_output_image_entries = outputs_json_entries["before"]["images"]; + uint32_t output_image_index = 0; + + for (const auto& image : mutable_resource_entry_before.images) + { + const uint32_t desc_set = image.desc_set; + const uint32_t binding = image.desc_binding; + const uint32_t array_index = image.array_index; + const VkShaderStageFlagBits stage = image.stage; + const VulkanImageInfo* img_info = image.original_image; + assert(img_info != nullptr); + + auto& image_json_entry = before_command_output_image_entries[output_image_index++]; + image_json_entry["type"] = util::ToString(image.desc_type); + image_json_entry["set"] = desc_set; + image_json_entry["binding"] = binding; + image_json_entry["arrayIndex"] = array_index; + auto& image_json_entry_desc = image_json_entry["images"]; + + std::vector aspects; + GetFormatAspects(img_info->format, aspects); + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < img_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) + { + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysImage; + res_info.is_dispatch = true; + res_info.before_cmd = true; + res_info.image_info = img_info; + res_info.set = desc_set; + res_info.binding = binding; + res_info.array_index = array_index; + res_info.stage = stage; + + std::string filename = GenerateDispatchTraceRaysImageFilename(res_info, mip, layer, aspect); + + const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), + std::max(1u, img_info->extent.height >> mip), + img_info->extent.depth }; + + dump_json_.InsertImageInfo(image_json_entry_desc[f++], + img_info->format, + img_info->type, + img_info->capture_id, + extent, + filename, + aspect, + ImageFailedScaling(filename), + mip, + layer, + options_.dump_resources_dump_separate_alpha); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + } + } + + if (!mutable_resource_entry_before.buffers.empty()) + { + auto& before_command_output_buffer_entries = outputs_json_entries["before"]["buffers"]; + uint32_t output_buffer_index = 0; + + for (const auto& buffer : mutable_resource_entry_before.buffers) + { + const uint32_t desc_set = buffer.desc_set; + const uint32_t binding = buffer.desc_binding; + const uint32_t array_index = buffer.array_index; + const VkShaderStageFlagBits stage = buffer.stage; + const VulkanBufferInfo* buffer_info = buffer.original_buffer; + assert(buffer_info != nullptr); + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysBuffer; + res_info.is_dispatch = true; + res_info.before_cmd = true; + res_info.set = desc_set; + res_info.binding = binding; + res_info.array_index = array_index; + res_info.stage = stage; + + std::string filename = GenerateDispatchTraceRaysBufferFilename(res_info); + + auto& buffer_json_entry = before_command_output_buffer_entries[output_buffer_index++]; + buffer_json_entry["type"] = util::ToString(buffer.desc_type); + buffer_json_entry["set"] = desc_set; + buffer_json_entry["binding"] = binding; + buffer_json_entry["arrayIndex"] = array_index; + dump_json_.InsertBufferInfo(buffer_json_entry, buffer_info, filename); + } + } + } + + const auto& mutable_resource_entry = draw_call_info.disp_param->mutable_resources_clones; + if (!mutable_resource_entry.images.empty()) + { + auto& outputs_json_entries_after = + options_.dump_resources_before ? outputs_json_entries["after"] : outputs_json_entries; + auto& image_outputs_json_entries = outputs_json_entries_after["images"]; + + uint32_t mutable_images_count = 0; + for (const auto& image : mutable_resource_entry.images) + { + const uint32_t desc_set = image.desc_set; + const uint32_t binding = image.desc_binding; + const uint32_t array_index = image.array_index; + const VkShaderStageFlagBits stage = image.stage; + const VulkanImageInfo* img_info = image.original_image; + assert(img_info != nullptr); + + auto& image_json_entry = image_outputs_json_entries[mutable_images_count++]; + image_json_entry["type"] = util::ToString(image.desc_type); + image_json_entry["set"] = desc_set; + image_json_entry["binding"] = binding; + image_json_entry["arrayIndex"] = array_index; + auto& image_json_entry_desc = image_json_entry["images"]; + + std::vector aspects; + GetFormatAspects(img_info->format, aspects); + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < img_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) + { + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysImage; + res_info.is_dispatch = true; + res_info.before_cmd = false; + res_info.image_info = img_info; + res_info.set = desc_set; + res_info.binding = binding; + res_info.array_index = array_index; + res_info.stage = stage; + + std::string filename = GenerateDispatchTraceRaysImageFilename(res_info, mip, layer, aspect); + + const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), + std::max(1u, img_info->extent.height >> mip), + img_info->extent.depth }; + + dump_json_.InsertImageInfo(image_json_entry_desc[f++], + img_info->format, + img_info->type, + img_info->capture_id, + extent, + filename, + aspect, + ImageFailedScaling(filename), + mip, + layer, + options_.dump_resources_dump_separate_alpha); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + } + } + + if (!mutable_resource_entry.buffers.empty()) + { + auto& outputs_json_entries_after = + options_.dump_resources_before ? outputs_json_entries["after"] : outputs_json_entries; + auto& buffer_outputs_json_entries = outputs_json_entries_after["buffers"]; + + uint32_t mutable_buffers_count = 0; + for (const auto& buffer : mutable_resource_entry.buffers) + { + const uint32_t desc_set = buffer.desc_set; + const uint32_t binding = buffer.desc_binding; + const uint32_t array_index = buffer.array_index; + const VkShaderStageFlagBits stage = buffer.stage; + const VulkanBufferInfo* buffer_info = buffer.original_buffer; + assert(buffer_info != nullptr); + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysBuffer; + res_info.is_dispatch = true; + res_info.before_cmd = false; + res_info.set = desc_set; + res_info.binding = binding; + res_info.array_index = array_index; + res_info.stage = stage; + + std::string filename = GenerateDispatchTraceRaysBufferFilename(res_info); + + auto& buffer_json_entry = buffer_outputs_json_entries[mutable_buffers_count++]; + buffer_json_entry["type"] = util::ToString(buffer.desc_type); + buffer_json_entry["set"] = desc_set; + buffer_json_entry["binding"] = binding; + buffer_json_entry["arrayIndex"] = array_index; + dump_json_.InsertBufferInfo(buffer_json_entry, buffer_info, filename); + } + } + + if (options_.dump_resources_dump_immutable_resources) + { + uint32_t descriptor_entries_count = 0; + for (const auto& desc_set : draw_call_info.disp_param->referenced_descriptors) + { + const uint32_t desc_set_index = desc_set.first; + for (const auto& desc_binding : desc_set.second) + { + const uint32_t desc_binding_index = desc_binding.first; + switch (desc_binding.second.desc_type) + { + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + { + for (size_t i = 0; i < desc_binding.second.image_info.size(); ++i) + { + if (desc_binding.second.image_info[i].image_view_info == nullptr) + { + continue; + } + + auto& entry = dispatch_json_entry["descriptors"][descriptor_entries_count++]; + + entry["type"] = util::ToString(desc_binding.second.desc_type); + entry["set"] = desc_set_index; + entry["binding"] = desc_binding_index; + entry["arrayIndex"] = i; + + const VulkanImageInfo* img_info = draw_call_info.object_info_table->GetVkImageInfo( + desc_binding.second.image_info[i].image_view_info->image_id); + assert(img_info); + + std::vector aspects; + GetFormatAspects(img_info->format, aspects); + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < img_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) + { + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysImageDescriptor; + res_info.image_info = img_info; + + std::string filename = GenerateDispatchTraceRaysImageDescriptorFilename( + res_info, mip, layer, aspect); + + auto& image_descriptor_json_entry = entry["descriptor"]; + const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), + std::max(1u, img_info->extent.height >> mip), + img_info->extent.depth }; + + dump_json_.InsertImageInfo(image_descriptor_json_entry[f++], + img_info->format, + img_info->type, + img_info->capture_id, + extent, + filename, + aspect, + ImageFailedScaling(filename), + mip, + layer, + options_.dump_resources_dump_separate_alpha); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + } + } + break; + + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + { + for (size_t i = 0; i < desc_binding.second.buffer_info.size(); ++i) + { + if (desc_binding.second.buffer_info[i].buffer_info != nullptr) + { + auto& entry = dispatch_json_entry["descriptors"][descriptor_entries_count++]; + + entry["type"] = util::ToString(desc_binding.second.desc_type); + entry["set"] = desc_set_index; + entry["binding"] = desc_binding_index; + entry["arrayIndex"] = i; + + auto& buffer_descriptor_json_entry = entry["descriptor"]; + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysBufferDescriptor; + res_info.buffer_info = desc_binding.second.buffer_info[i].buffer_info; + + const std::string filename = + GenerateDispatchTraceRaysBufferDescriptorFilename(res_info); + dump_json_.InsertBufferInfo(buffer_descriptor_json_entry, + desc_binding.second.buffer_info[i].buffer_info, + filename); + } + } + } + break; + + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + case VK_DESCRIPTOR_TYPE_SAMPLER: + break; + + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: + { + auto& entry = dispatch_json_entry["descriptors"][descriptor_entries_count++]; + + entry["type"] = util::ToString(desc_binding.second.desc_type); + entry["set"] = desc_set_index; + entry["binding"] = desc_binding_index; + entry["size"] = desc_binding.second.inline_uniform_block.size(); + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysInlineUniformBufferDescriptor; + res_info.set = desc_set_index; + res_info.binding = desc_binding_index; + + const std::string filename = + GenerateDispatchTraceRaysInlineUniformBufferDescriptorFilename(res_info); + entry["file"] = filename; + } + break; + + default: + GFXRECON_LOG_WARNING_ONCE( + "%s(): Descriptor type (%s) not handled", + __func__, + util::ToString(desc_binding.second.desc_type).c_str()); + break; + } + } + } + } + + if (options_.dump_resources_json_per_command) + { + dump_json_.BlockEnd(); + dump_json_.Close(); + } +} + +void DefaultVulkanDumpResourcesDelegate::GenerateOutputJsonTraceRaysIndex(const VulkanDumpDrawCallInfo& draw_call_info, + size_t index) +{ + if (draw_call_info.tr_param == nullptr) + { + return; + } + auto& current_block = dump_json_.GetCurrentSubEntry(); + + auto& tr_json_entries = + (!options_.dump_resources_json_per_command) ? current_block["traceRaysCommands"] : dump_json_.GetData(); + + if (options_.dump_resources_json_per_command) + { + std::stringstream filename; + filename << "TraceRays_" << draw_call_info.cmd_index << "_qs_" << draw_call_info.qs_index << "_bcb_" + << draw_call_info.bcb_index << "_dr.json"; + std::filesystem::path filedirname(options_.dump_resources_output_dir); + std::filesystem::path filebasename(filename.str()); + std::string full_filename = (filedirname / filebasename).string(); + + dump_json_.Open(full_filename); + dump_json_.BlockStart(); + } + auto& tr_entry = !options_.dump_resources_json_per_command ? tr_json_entries[index] : dump_json_.GetData(); + + tr_entry["traceRaysIndex"] = draw_call_info.cmd_index; + tr_entry["beginCommandBufferIndex"] = draw_call_info.bcb_index; + tr_entry["queueSubmitIndex"] = draw_call_info.qs_index; + + auto& params_json_entries = tr_entry["parameters"]; + params_json_entries["traceRaysType"] = + DispatchTraceRaysDumpingContext::TraceRaysTypeToStr(draw_call_info.tr_param->type); + + switch (draw_call_info.tr_param->type) + { + case DispatchTraceRaysDumpingContext::TraceRaysTypes::kTraceRays: + { + const auto& params = draw_call_info.tr_param->trace_rays_params_union.trace_rays; + + params_json_entries["width"] = params.width; + params_json_entries["height"] = params.height; + params_json_entries["depth"] = params.depth; + } + break; + + case DispatchTraceRaysDumpingContext::TraceRaysTypes::kTraceRaysIndirect: + { + const auto& params = draw_call_info.tr_param->trace_rays_params_union.trace_rays_indirect; + + params_json_entries["width"] = params.trace_rays_params.width; + params_json_entries["height"] = params.trace_rays_params.height; + params_json_entries["depth"] = params.trace_rays_params.depth; + } + break; + + case DispatchTraceRaysDumpingContext::TraceRaysTypes::kTraceRaysIndirect2: + { + const auto& params = draw_call_info.tr_param->trace_rays_params_union.trace_rays_indirect2; + + params_json_entries["width"] = params.trace_rays_params.width; + params_json_entries["height"] = params.trace_rays_params.height; + params_json_entries["depth"] = params.trace_rays_params.depth; + } + break; + + default: + assert(0); + } + + auto& outputs_json_entries = tr_entry["outputs"]; + + VulkanDumpResourceInfo res_info_base{}; + res_info_base = draw_call_info; + + if (options_.dump_resources_before) + { + const auto& mutable_resource_entry_before = draw_call_info.tr_param->mutable_resources_clones_before; + if (!mutable_resource_entry_before.images.empty()) + { + auto& before_command_output_image_entries = outputs_json_entries["before"]["images"]; + uint32_t output_image_index = 0; + + for (const auto& image : mutable_resource_entry_before.images) + { + const uint32_t desc_set = image.desc_set; + const uint32_t binding = image.desc_binding; + const uint32_t array_index = image.array_index; + const VkShaderStageFlagBits stage = image.stage; + const VulkanImageInfo* img_info = image.original_image; + assert(img_info != nullptr); + + std::vector aspects; + GetFormatAspects(img_info->format, aspects); + + auto& image_json_entry = before_command_output_image_entries[output_image_index++]; + image_json_entry["type"] = util::ToString(image.desc_type); + image_json_entry["set"] = desc_set; + image_json_entry["binding"] = binding; + image_json_entry["arrayIndex"] = array_index; + auto& image_json_entry_desc = image_json_entry["images"]; + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < img_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) + { + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysImage; + res_info.is_dispatch = false; + res_info.before_cmd = true; + res_info.image_info = img_info; + res_info.set = desc_set; + res_info.binding = binding; + res_info.array_index = array_index; + res_info.stage = stage; + + std::string filename = GenerateDispatchTraceRaysImageFilename(res_info, mip, layer, aspect); + + const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), + std::max(1u, img_info->extent.height >> mip), + img_info->extent.depth }; + + dump_json_.InsertImageInfo(image_json_entry_desc[f++], + img_info->format, + img_info->type, + img_info->capture_id, + extent, + filename, + aspect, + ImageFailedScaling(filename), + mip, + layer, + options_.dump_resources_dump_separate_alpha); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + } + } + + if (!mutable_resource_entry_before.buffers.empty()) + { + auto& before_command_output_buffer_entries = outputs_json_entries["before"]["buffers"]; + uint32_t output_buffer_index = 0; + + for (const auto& buffer : mutable_resource_entry_before.buffers) + { + const uint32_t desc_set = buffer.desc_set; + const uint32_t binding = buffer.desc_binding; + const uint32_t array_index = buffer.array_index; + const VkShaderStageFlagBits stage = buffer.stage; + const VulkanBufferInfo* buffer_info = buffer.original_buffer; + assert(buffer_info != nullptr); + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysBuffer; + res_info.is_dispatch = false; + res_info.before_cmd = true; + res_info.set = desc_set; + res_info.binding = binding; + res_info.array_index = array_index; + res_info.stage = stage; + + std::string filename = GenerateDispatchTraceRaysBufferFilename(res_info); + + auto& buffer_json_entry = before_command_output_buffer_entries[output_buffer_index++]; + buffer_json_entry["type"] = util::ToString(buffer.desc_type); + buffer_json_entry["set"] = desc_set; + buffer_json_entry["binding"] = binding; + buffer_json_entry["arrayIndex"] = array_index; + dump_json_.InsertBufferInfo(buffer_json_entry, buffer_info, filename); + } + } + } + + const auto& mutable_resource_entry = draw_call_info.tr_param->mutable_resources_clones; + auto& outputs_json_entries_after = + options_.dump_resources_before ? outputs_json_entries["after"] : outputs_json_entries; + + if (!mutable_resource_entry.images.empty()) + { + uint32_t mutable_images_count = 0; + for (const auto& image : mutable_resource_entry.images) + { + const uint32_t desc_set = image.desc_set; + const uint32_t binding = image.desc_binding; + const uint32_t array_index = image.array_index; + const VkShaderStageFlagBits stage = image.stage; + const VulkanImageInfo* img_info = image.original_image; + assert(img_info != nullptr); + + auto& image_json_entry = outputs_json_entries_after["images"][mutable_images_count++]; + image_json_entry["type"] = util::ToString(image.desc_type); + image_json_entry["set"] = desc_set; + image_json_entry["binding"] = binding; + image_json_entry["arrayIndex"] = array_index; + auto& image_json_entry_desc = image_json_entry["image"]; + + std::vector aspects; + GetFormatAspects(img_info->format, aspects); + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < img_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) + { + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysImage; + res_info.is_dispatch = false; + res_info.before_cmd = false; + res_info.image_info = img_info; + res_info.set = desc_set; + res_info.binding = binding; + res_info.array_index = array_index; + res_info.stage = stage; + + std::string filename = GenerateDispatchTraceRaysImageFilename(res_info, mip, layer, aspect); + + const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), + std::max(1u, img_info->extent.height >> mip), + img_info->extent.depth }; + + dump_json_.InsertImageInfo(image_json_entry_desc[f++], + img_info->format, + img_info->type, + img_info->capture_id, + extent, + filename, + aspect, + ImageFailedScaling(filename), + mip, + layer, + options_.dump_resources_dump_separate_alpha); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + } + } + + if (!mutable_resource_entry.buffers.empty()) + { + uint32_t mutable_buffers_count = 0; + for (const auto& buffer : mutable_resource_entry.buffers) + { + const uint32_t desc_set = buffer.desc_set; + const uint32_t binding = buffer.desc_binding; + const uint32_t array_index = buffer.array_index; + const VkShaderStageFlagBits stage = buffer.stage; + const VulkanBufferInfo* buffer_info = buffer.original_buffer; + assert(buffer_info != nullptr); + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysBuffer; + res_info.is_dispatch = false; + res_info.before_cmd = false; + res_info.set = desc_set; + res_info.binding = binding; + res_info.array_index = array_index; + res_info.stage = stage; + + std::string filename = GenerateDispatchTraceRaysBufferFilename(res_info); + + auto& buffer_json_entry = outputs_json_entries_after["buffers"][mutable_buffers_count++]; + buffer_json_entry["type"] = util::ToString(buffer.desc_type); + buffer_json_entry["set"] = desc_set; + buffer_json_entry["binding"] = binding; + buffer_json_entry["arrayIndex"] = array_index; + dump_json_.InsertBufferInfo(buffer_json_entry, buffer_info, filename); + } + } + + if (options_.dump_resources_dump_immutable_resources) + { + for (const auto& shader_stage : draw_call_info.tr_param->referenced_descriptors) + { + uint32_t stage_entry_index = 0; + const std::string shader_stage_name = ShaderStageToStr(shader_stage.first); + for (const auto& desc_set : shader_stage.second) + { + const uint32_t desc_set_index = desc_set.first; + + for (const auto& desc_binding : desc_set.second) + { + const uint32_t desc_binding_index = desc_binding.first; + + switch (desc_binding.second.desc_type) + { + case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: + case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: + case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: + case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: + { + for (size_t img = 0; img < desc_binding.second.image_info.size(); ++img) + { + if (desc_binding.second.image_info[img].image_view_info == nullptr) + { + continue; + } + + auto& entry = tr_entry["descriptors"][shader_stage_name][stage_entry_index++]; + + const VulkanImageInfo* img_info = draw_call_info.object_info_table->GetVkImageInfo( + desc_binding.second.image_info[img].image_view_info->image_id); + assert(img_info); + + entry["type"] = util::ToString(desc_binding.second.desc_type); + entry["set"] = desc_set_index; + entry["binding"] = desc_binding_index; + entry["arrayIndex"] = img; + + std::vector aspects; + GetFormatAspects(img_info->format, aspects); + + size_t f = 0; + for (auto aspect : aspects) + { + for (uint32_t mip = 0; mip < img_info->level_count; ++mip) + { + for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) + { + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysImageDescriptor; + res_info.image_info = img_info; + + std::string filename = GenerateDispatchTraceRaysImageDescriptorFilename( + res_info, mip, layer, aspect); + + const VkExtent3D extent = { std::max(1u, img_info->extent.width >> mip), + std::max(1u, img_info->extent.height >> mip), + img_info->extent.depth }; + + auto& image_descriptor_json_entry = entry["descriptor"]; + + dump_json_.InsertImageInfo(image_descriptor_json_entry[f++], + img_info->format, + img_info->type, + img_info->capture_id, + extent, + filename, + aspect, + ImageFailedScaling(filename), + mip, + layer, + options_.dump_resources_dump_separate_alpha); + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + + if (!options_.dump_resources_dump_all_image_subresources) + { + break; + } + } + } + } + } + break; + + case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + { + for (size_t i = 0; i < desc_binding.second.buffer_info.size(); ++i) + { + if (desc_binding.second.buffer_info[i].buffer_info != nullptr) + { + auto& entry = tr_entry["descriptors"][shader_stage_name][stage_entry_index++]; + + entry["type"] = util::ToString(desc_binding.second.desc_type); + entry["set"] = desc_set_index; + entry["binding"] = desc_binding_index; + entry["arrayIndex"] = i; + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysBufferDescriptor; + res_info.buffer_info = desc_binding.second.buffer_info[i].buffer_info; + + const std::string filename = + GenerateDispatchTraceRaysBufferDescriptorFilename(res_info); + auto& buffer_descriptor_json_entry = entry["descriptor"]; + dump_json_.InsertBufferInfo(buffer_descriptor_json_entry, + desc_binding.second.buffer_info[i].buffer_info, + filename); + } + } + } + break; + + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: + { + auto& desc_json_entry = tr_entry["descriptors"][shader_stage_name][stage_entry_index++]; + + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDispatchTraceRaysInlineUniformBufferDescriptor; + res_info.set = desc_set_index; + res_info.binding = desc_binding_index; + + const std::string filename = + GenerateDispatchTraceRaysInlineUniformBufferDescriptorFilename(res_info); + + desc_json_entry["type"] = util::ToString(desc_binding.second.desc_type); + desc_json_entry["set"] = desc_set_index; + desc_json_entry["binding"] = desc_binding_index; + desc_json_entry["size"] = desc_binding.second.inline_uniform_block.size(); + desc_json_entry["file"] = filename; + } + break; + + case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR: + case VK_DESCRIPTOR_TYPE_SAMPLER: + break; + + default: + GFXRECON_LOG_WARNING_ONCE( + "%s(): Descriptor type (%s) not handled", + __func__, + util::ToString(desc_binding.second.desc_type).c_str()); + break; + } + } + } + } + } + + if (options_.dump_resources_json_per_command) + { + dump_json_.BlockEnd(); + dump_json_.Close(); + } +} + +GFXRECON_END_NAMESPACE(gfxrecon) +GFXRECON_END_NAMESPACE(decode) diff --git a/framework/decode/vulkan_replay_dump_resources_delegate.h b/framework/decode/vulkan_replay_dump_resources_delegate.h new file mode 100644 index 0000000000..52324dd115 --- /dev/null +++ b/framework/decode/vulkan_replay_dump_resources_delegate.h @@ -0,0 +1,223 @@ +/* +** Copyright (c) 2025 LunarG, Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and associated documentation files (the "Software"), +** to deal in the Software without restriction, including without limitation +** the rights to use, copy, modify, merge, publish, distribute, sublicense, +** and/or sell copies of the Software, and to permit persons to whom the +** Software is furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +** DEALINGS IN THE SOFTWARE. +*/ + +#ifndef GFXRECON_VULKAN_REPLAY_DUMP_RESOURCES_DELEGATE_H +#define GFXRECON_VULKAN_REPLAY_DUMP_RESOURCES_DELEGATE_H + +#include "decode/vulkan_replay_dump_resources_draw_calls.h" +#include "decode/vulkan_replay_dump_resources_compute_ray_tracing.h" +#include "decode/vulkan_replay_dump_resources_json.h" + +GFXRECON_BEGIN_NAMESPACE(gfxrecon) +GFXRECON_BEGIN_NAMESPACE(decode) + +struct VulkanDumpDrawCallInfo +{ + DumpResourceType type{ DumpResourceType::kUnknown }; + + const encode::VulkanInstanceTable* instance_table; + const encode::VulkanDeviceTable* device_table; + CommonObjectInfoTable* object_info_table; + const VulkanDeviceInfo* device_info; + const VulkanCommandBufferInfo* original_command_buffer_info; + + uint64_t cmd_index; // dc_index, disp_index, tr_index + uint64_t qs_index; // queue submit + uint64_t bcb_index; // begin command buffer + + uint64_t rp; // render pass + uint64_t sp; // subpass + const DrawCallsDumpingContext::DrawCallParameters* dc_param; // draw call + const DrawCallsDumpingContext::RenderTargets* render_targets; + + const DispatchTraceRaysDumpingContext::DispatchParameters* disp_param; // dispatch + + const DispatchTraceRaysDumpingContext::TraceRaysParameters* tr_param; // trace rays +}; + +struct VulkanDumpResourceInfo +{ + DumpResourceType type{ DumpResourceType::kUnknown }; + + const encode::VulkanInstanceTable* instance_table; + const encode::VulkanDeviceTable* device_table; + CommonObjectInfoTable* object_info_table; + const VulkanDeviceInfo* device_info; + const VulkanCommandBufferInfo* original_command_buffer_info; + + uint64_t cmd_index; // dc_index, disp_index, tr_index + uint64_t qs_index; // queue submit + uint64_t bcb_index; // begin command buffer + + uint64_t rp; // render pass + uint64_t sp; // subpass + + const VulkanImageInfo* image_info; + VkExtent3D image_extent; + const VulkanBufferInfo* buffer_info; + std::vector data; + + uint32_t set; + uint32_t binding; + VkIndexType index_type; + int attachment_index; + + bool is_dispatch; + bool before_cmd; + uint32_t array_index; + VkShaderStageFlagBits stage; + + VulkanDumpResourceInfo& operator=(const VulkanDumpDrawCallInfo& draw_call_info) + { + instance_table = draw_call_info.instance_table; + device_table = draw_call_info.device_table; + object_info_table = draw_call_info.object_info_table; + device_info = draw_call_info.device_info; + original_command_buffer_info = draw_call_info.original_command_buffer_info; + cmd_index = draw_call_info.cmd_index; + qs_index = draw_call_info.qs_index; + bcb_index = draw_call_info.bcb_index; + rp = draw_call_info.rp; + sp = draw_call_info.sp; + return *this; + } +}; + +class VulkanDumpResourcesDelegate +{ + public: + VulkanDumpResourcesDelegate(const VulkanReplayOptions& options, const std::string capture_filename) {} + virtual ~VulkanDumpResourcesDelegate() {} + + virtual bool Open() = 0; + virtual void DumpDrawCallInfo(const VulkanDumpDrawCallInfo& draw_call_info, size_t index) = 0; + virtual void DumpStart() = 0; + virtual VkResult DumpResource(const VulkanDumpResourceInfo& resource_info) = 0; + virtual void DumpEnd() = 0; + virtual void Close() = 0; +}; + +class DefaultVulkanDumpResourcesDelegate : public VulkanDumpResourcesDelegate +{ + public: + DefaultVulkanDumpResourcesDelegate(const VulkanReplayOptions& options, const std::string capture_filename) : + VulkanDumpResourcesDelegate(options, capture_filename), options_(options), dump_json_(options), + capture_filename_(capture_filename) + {} + virtual ~DefaultVulkanDumpResourcesDelegate() {} + + virtual bool Open() override + { + return dump_json_.Open(options_.capture_filename, options_.dump_resources_output_dir); + } + + virtual void DumpDrawCallInfo(const VulkanDumpDrawCallInfo& draw_call_info, size_t index) override; + + virtual void DumpStart() override { dump_json_.BlockStart(); } + + virtual VkResult DumpResource(const VulkanDumpResourceInfo& resource_info) override; + + virtual void DumpEnd() override { dump_json_.BlockEnd(); } + + virtual void Close() override { dump_json_.Close(); } + + private: + // DrawCallsDumpingContext + VkResult DumpRenderTargetImage(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateRenderTargetImageFilename(const VulkanDumpResourceInfo& resource_info, + VkImageAspectFlagBits aspect, + uint32_t mip_level, + uint32_t layer) const; + + VkResult DumpImageDescriptor(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateImageDescriptorFilename(const VulkanDumpResourceInfo& resource_info, + VkImageAspectFlagBits aspect, + uint32_t mip_level, + uint32_t layer) const; + + VkResult DumpBufferDescriptor(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateBufferDescriptorFilename(const VulkanDumpResourceInfo& resource_info) const; + + VkResult DumpInlineUniformBufferDescriptor(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateInlineUniformBufferDescriptorFilename(const VulkanDumpResourceInfo& resource_info) const; + + VkResult DumpVertexBuffer(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateVertexBufferFilename(const VulkanDumpResourceInfo& resource_info) const; + + VkResult DumpIndexBuffer(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateIndexBufferFilename(const VulkanDumpResourceInfo& resource_info) const; + + void GenerateOutputJsonDrawCallInfo(const VulkanDumpDrawCallInfo& draw_call_info, size_t index); + + // DispatchTraceRaysDumpingContext + VkResult DumpeDispatchTraceRaysImage(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateDispatchTraceRaysImageFilename(const VulkanDumpResourceInfo& resource_info, + uint32_t mip_level, + uint32_t layer, + VkImageAspectFlagBits aspect) const; + + VkResult DumpeDispatchTraceRaysBuffer(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateDispatchTraceRaysBufferFilename(const VulkanDumpResourceInfo& resource_info) const; + + VkResult DumpDispatchTraceRaysImageDescriptor(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateDispatchTraceRaysImageDescriptorFilename(const VulkanDumpResourceInfo& resource_info, + uint32_t mip_level, + uint32_t layer, + VkImageAspectFlagBits aspect) const; + + VkResult DumpDispatchTraceRaysBufferDescriptor(const VulkanDumpResourceInfo& resource_info); + + std::string GenerateDispatchTraceRaysBufferDescriptorFilename(const VulkanDumpResourceInfo& resource_info) const; + + VkResult DumpDispatchTraceRaysInlineUniformBufferDescriptor(const VulkanDumpResourceInfo& resource_info); + + std::string + GenerateDispatchTraceRaysInlineUniformBufferDescriptorFilename(const VulkanDumpResourceInfo& resource_info) const; + + void GenerateOutputJsonDispatchInfo(const VulkanDumpDrawCallInfo& draw_call_info, size_t index); + + void GenerateOutputJsonTraceRaysIndex(const VulkanDumpDrawCallInfo& draw_call_info, size_t index); + + // Keep track of images for which scalling failed so we can + // note them in the output json + std::unordered_set images_failed_scaling_; + + bool ImageFailedScaling(const std::string& filename) const { return images_failed_scaling_.count(filename); } + + VulkanReplayDumpResourcesJson dump_json_; + const VulkanReplayOptions& options_; + const std::string capture_filename_; +}; + +GFXRECON_END_NAMESPACE(gfxrecon) +GFXRECON_END_NAMESPACE(decode) + +#endif /* GFXRECON_VULKAN_REPLAY_DUMP_RESOURCES_DELEGATE_H */ diff --git a/framework/decode/vulkan_replay_dump_resources_draw_calls.cpp b/framework/decode/vulkan_replay_dump_resources_draw_calls.cpp index c80cda590f..32c2249e4f 100644 --- a/framework/decode/vulkan_replay_dump_resources_draw_calls.cpp +++ b/framework/decode/vulkan_replay_dump_resources_draw_calls.cpp @@ -22,7 +22,7 @@ #include "decode/vulkan_object_info.h" #include "decode/vulkan_replay_dump_resources_draw_calls.h" -#include "decode/vulkan_replay_dump_resources_common.h" +#include "decode/vulkan_replay_dump_resources_delegate.h" #include "format/format.h" #include "generated/generated_vulkan_enum_to_string.h" #include "graphics/vulkan_resources_util.h" @@ -58,23 +58,16 @@ DrawCallsDumpingContext::DrawCallsDumpingContext(const std::vector& const std::vector>& rp_indices, CommonObjectInfoTable& object_info_table, const VulkanReplayOptions& options, - VulkanReplayDumpResourcesJson& dump_json, - std::string capture_filename) : + VulkanDumpResourcesDelegate& delegate) : original_command_buffer_info(nullptr), current_cb_index(0), dc_indices(dc_indices), RP_indices(rp_indices), active_renderpass(nullptr), active_framebuffer(nullptr), bound_pipelines{ nullptr }, current_renderpass(0), current_subpass(0), dump_resources_before(options.dump_resources_before), aux_command_buffer(VK_NULL_HANDLE), aux_fence(VK_NULL_HANDLE), device_table(nullptr), instance_table(nullptr), object_info_table(object_info_table), - replay_device_phys_mem_props(nullptr), dump_resource_path(options.dump_resources_output_dir), - image_file_format(options.dump_resources_image_format), dump_resources_scale(options.dump_resources_scale), - dump_json(dump_json), dump_depth(options.dump_resources_dump_depth), + replay_device_phys_mem_props(nullptr), delegate_(delegate), dump_depth(options.dump_resources_dump_depth), color_attachment_to_dump(options.dump_resources_color_attachment_index), dump_vertex_index_buffers(options.dump_resources_dump_vertex_index_buffer), - output_json_per_command(options.dump_resources_json_per_command), - dump_immutable_resources(options.dump_resources_dump_immutable_resources), - dump_all_image_subresources(options.dump_resources_dump_all_image_subresources), current_render_pass_type(kNone), - capture_filename(capture_filename), dump_images_raw(options.dump_resources_dump_raw_images), - dump_images_separate_alpha(options.dump_resources_dump_separate_alpha) + dump_immutable_resources(options.dump_resources_dump_immutable_resources), current_render_pass_type(kNone) { must_backup_resources = (dc_indices.size() > 1); @@ -149,8 +142,7 @@ void DrawCallsDumpingContext::InsertNewDrawParameters( auto new_entry = draw_call_params.emplace( std::piecewise_construct, std::forward_as_tuple(index), - std::forward_as_tuple( - DrawCallsDumpingContext::kDraw, vertex_count, instance_count, first_vertex, first_instance)); + std::forward_as_tuple(DrawCallTypes::kDraw, vertex_count, instance_count, first_vertex, first_instance)); assert(new_entry.second); } @@ -161,24 +153,21 @@ void DrawCallsDumpingContext::InsertNewDrawIndexedParameters(uint64_t index, int32_t vertexOffset, uint32_t first_instance) { - auto new_entry = draw_call_params.emplace(std::piecewise_construct, - std::forward_as_tuple(index), - std::forward_as_tuple(DrawCallsDumpingContext::kDrawIndexed, - index_count, - instance_count, - first_index, - vertexOffset, - first_instance)); + auto new_entry = draw_call_params.emplace( + std::piecewise_construct, + std::forward_as_tuple(index), + std::forward_as_tuple( + DrawCallTypes::kDrawIndexed, index_count, instance_count, first_index, vertexOffset, first_instance)); assert(new_entry.second); } void DrawCallsDumpingContext::InsertNewDrawIndirectParameters( uint64_t index, const VulkanBufferInfo* buffer_info, VkDeviceSize offset, uint32_t draw_count, uint32_t stride) { - auto new_entry = draw_call_params.emplace( - std::piecewise_construct, - std::forward_as_tuple(index), - std::forward_as_tuple(DrawCallsDumpingContext::kDrawIndirect, buffer_info, offset, draw_count, stride)); + auto new_entry = + draw_call_params.emplace(std::piecewise_construct, + std::forward_as_tuple(index), + std::forward_as_tuple(kDrawIndirect, buffer_info, offset, draw_count, stride)); assert(new_entry.second); } @@ -188,7 +177,7 @@ void DrawCallsDumpingContext::InsertNewDrawIndexedIndirectParameters( auto new_entry = draw_call_params.emplace( std::piecewise_construct, std::forward_as_tuple(index), - std::forward_as_tuple(DrawCallsDumpingContext::kDrawIndexedIndirect, buffer_info, offset, draw_count, stride)); + std::forward_as_tuple(DrawCallTypes::kDrawIndexedIndirect, buffer_info, offset, draw_count, stride)); assert(new_entry.second); } @@ -202,7 +191,7 @@ void DrawCallsDumpingContext::InsertNewIndirectCountParameters(uint64_t { auto new_entry = draw_call_params.emplace(std::piecewise_construct, std::forward_as_tuple(index), - std::forward_as_tuple(DrawCallsDumpingContext::kDrawIndirectCount, + std::forward_as_tuple(DrawCallTypes::kDrawIndirectCount, buffer_info, offset, count_buffer_info, @@ -222,7 +211,7 @@ void DrawCallsDumpingContext::InsertNewDrawIndexedIndirectCountParameters(uint64 { auto new_entry = draw_call_params.emplace(std::piecewise_construct, std::forward_as_tuple(index), - std::forward_as_tuple(DrawCallsDumpingContext::kDrawIndexedIndirectCount, + std::forward_as_tuple(DrawCallTypes::kDrawIndexedIndirectCount, buffer_info, offset, count_buffer_info, @@ -242,7 +231,7 @@ void DrawCallsDumpingContext::InsertNewDrawIndirectCountKHRParameters(uint64_t { auto new_entry = draw_call_params.emplace(std::piecewise_construct, std::forward_as_tuple(index), - std::forward_as_tuple(DrawCallsDumpingContext::kDrawIndirectCountKHR, + std::forward_as_tuple(DrawCallTypes::kDrawIndirectCountKHR, buffer_info, offset, count_buffer_info, @@ -260,16 +249,15 @@ void DrawCallsDumpingContext::InsertNewDrawIndexedIndirectCountKHRParameters(uin uint32_t max_draw_count, uint32_t stride) { - auto new_entry = - draw_call_params.emplace(std::piecewise_construct, - std::forward_as_tuple(index), - std::forward_as_tuple(DrawCallsDumpingContext::kDrawIndexedIndirectCountKHR, - buffer_info, - offset, - count_buffer_info, - count_buffer_offset, - max_draw_count, - stride)); + auto new_entry = draw_call_params.emplace(std::piecewise_construct, + std::forward_as_tuple(index), + std::forward_as_tuple(DrawCallTypes::kDrawIndexedIndirectCountKHR, + buffer_info, + offset, + count_buffer_info, + count_buffer_offset, + max_draw_count, + stride)); assert(new_entry.second); } @@ -873,7 +861,25 @@ VkResult DrawCallsDumpingContext::DumpDrawCalls( if (!dump_resources_before || dump_resources_before && !(cb % 2)) { - GenerateOutputJsonDrawCallInfo(qs_index, bcb_index, cb, rp, sp); + VulkanDumpDrawCallInfo draw_call_info{}; + draw_call_info.type = DumpResourceType::kDrawCallInfo; + draw_call_info.instance_table = instance_table; + draw_call_info.device_table = device_table; + draw_call_info.object_info_table = &object_info_table; + draw_call_info.device_info = device_info; + draw_call_info.original_command_buffer_info = original_command_buffer_info; + draw_call_info.bcb_index = bcb_index; + draw_call_info.qs_index = qs_index; + draw_call_info.rp = rp; + draw_call_info.sp = sp; + draw_call_info.cmd_index = dc_index; + draw_call_info.render_targets = &render_targets[rp][sp]; + + const auto& dc_param_entry = draw_call_params.find(draw_call_info.cmd_index); + GFXRECON_ASSERT(dc_param_entry != draw_call_params.end()); + draw_call_info.dc_param = &dc_param_entry->second; + + delegate_.DumpDrawCallInfo(draw_call_info, cb); } res = RevertRenderTargetImageLayouts(queue, cb); @@ -899,612 +905,6 @@ VkResult DrawCallsDumpingContext::DumpDrawCalls( return VK_SUCCESS; } -#define DEPTH_ATTACHMENT ~0 - -std::string DrawCallsDumpingContext::GenerateRenderTargetImageFilename(VkFormat format, - VkImageAspectFlagBits aspect, - VkImageTiling tiling, - VkImageType type, - uint32_t mip_level, - uint32_t layer, - uint64_t cmd_buf_index, - uint64_t qs_index, - uint64_t bcb_index, - uint64_t dc_index, - int attachment_index) const -{ - std::string aspect_str = ImageAspectToStr(aspect); - std::string attachment_str = - attachment_index != DEPTH_ATTACHMENT ? "_att_" + std::to_string(attachment_index) : "_depth_att"; - - std::stringstream filename; - filename << capture_filename << "_"; - - const VulkanDeviceInfo* device_info = object_info_table.GetVkDeviceInfo(original_command_buffer_info->parent_id); - assert(device_info); - - const DumpedImageFormat output_image_format = GetDumpedImageFormat(device_info, - device_table, - instance_table, - object_info_table, - format, - tiling, - type, - image_file_format, - dump_images_raw); - - if (output_image_format != KFormatRaw) - { - if (dump_resources_before) - { - filename << "draw_" << ((cmd_buf_index % 2) ? "after_" : "before_") << dc_index << "_qs_" << qs_index - << "_bcb_" << bcb_index << attachment_str << "_aspect_" << aspect_str; - } - else - { - filename << "draw_" << dc_index << "_qs_" << qs_index << "_bcb_" << bcb_index << attachment_str - << "_aspect_" << aspect_str; - } - } - else - { - if (dump_resources_before) - { - filename << "draw_" << ((cmd_buf_index % 2) ? "after_" : "before_") << dc_index << "_qs_" << qs_index - << "_bcb_" << bcb_index << "_" << qs_index << "_" << bcb_index << attachment_str << "_" - << util::ToString(format) << "_aspect_" << aspect_str; - } - else - { - filename << "draw_" << dc_index << "_qs_" << qs_index << "_bcb_" << bcb_index << attachment_str << "_" - << util::ToString(format) << "_aspect_" << aspect_str; - } - } - - if (dump_all_image_subresources) - { - std::stringstream subresource_sting; - subresource_sting << "_mip_" << mip_level << "_layer_" << layer; - subresource_sting << ImageFileExtension(output_image_format); - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str() + subresource_sting.str()); - return (filedirname / filebasename).string(); - } - else - { - filename << ImageFileExtension(output_image_format); - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - return (filedirname / filebasename).string(); - } -} - -void DrawCallsDumpingContext::GenerateOutputJsonDrawCallInfo( - uint64_t qs_index, uint64_t bcb_index, uint64_t cmd_buf_index, uint64_t rp, uint64_t sp) const -{ - const size_t dc_index = dc_indices[CmdBufToDCVectorIndex(cmd_buf_index)]; - - if (output_json_per_command) - { - std::stringstream filename; - filename << capture_filename << "_"; - filename << "DrawCall_" << dc_index << "_qs_" << qs_index << "_bcb_" << bcb_index << "_dr.json"; - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - std::string full_filename = (filedirname / filebasename).string(); - - dump_json.Open(full_filename); - dump_json.BlockStart(); - } - - auto& current_block = dump_json.GetCurrentSubEntry(); - auto& drawcall_json_entries = !output_json_per_command ? current_block["drawCallCommands"] : current_block; - auto& draw_call_entry = !output_json_per_command ? drawcall_json_entries[cmd_buf_index] : drawcall_json_entries; - - const auto& dc_param_entry = draw_call_params.find(dc_index); - assert(dc_param_entry != draw_call_params.end()); - - draw_call_entry["drawIndex"] = dc_index; - draw_call_entry["beginCommandBufferIndex"] = bcb_index; - draw_call_entry["queueSubmitIndex"] = qs_index; - - // Write draw call params - auto& dc_params_json_entry = draw_call_entry["parameters"]; - dc_params_json_entry["drawCallType"] = DrawCallTypeToStr(dc_param_entry->second.type); - switch (dc_param_entry->second.type) - { - case kDraw: - { - const VkDrawIndirectCommand& dc_params = dc_param_entry->second.dc_params_union.draw; - - dc_params_json_entry["vertexCount"] = dc_params.vertexCount; - dc_params_json_entry["instanceCount"] = dc_params.instanceCount; - dc_params_json_entry["firstVertex"] = dc_params.firstVertex; - dc_params_json_entry["firstInstance"] = dc_params.firstInstance; - } - break; - - case kDrawIndexed: - { - const VkDrawIndexedIndirectCommand& dc_params = dc_param_entry->second.dc_params_union.draw_indexed; - - dc_params_json_entry["indexCount"] = dc_params.indexCount; - dc_params_json_entry["instanceCount"] = dc_params.instanceCount; - dc_params_json_entry["firstIndex"] = dc_params.firstIndex; - dc_params_json_entry["vertexOffset"] = dc_params.vertexOffset; - dc_params_json_entry["firstInstance"] = dc_params.firstInstance; - } - break; - - case kDrawIndirect: - { - const DrawCallParameters::DrawCallParamsUnion::DrawIndirectParams& dc_params = - dc_param_entry->second.dc_params_union.draw_indirect; - - assert((dc_params.draw_count && dc_params.draw_params != nullptr) || !dc_params.draw_count); - - dc_params_json_entry["drawCount"] = dc_params.draw_count; - auto& indirect_param_entries = dc_params_json_entry["indirectParams"]; - for (uint32_t di = 0; di < dc_params.draw_count; ++di) - { - indirect_param_entries[di]["vertexCount"] = dc_params.draw_params[di].vertexCount; - indirect_param_entries[di]["instanceCount"] = dc_params.draw_params[di].instanceCount; - indirect_param_entries[di]["firstVertex"] = dc_params.draw_params[di].firstVertex; - indirect_param_entries[di]["firstInstance"] = dc_params.draw_params[di].firstInstance; - } - } - break; - - case kDrawIndexedIndirect: - { - const DrawCallParameters::DrawCallParamsUnion::DrawIndirectParams& dc_params = - dc_param_entry->second.dc_params_union.draw_indirect; - - assert((dc_params.draw_count && dc_params.draw_indexed_params != nullptr) || !dc_params.draw_count); - - dc_params_json_entry["drawCount"] = dc_params.draw_count; - auto& indirect_param_entries = dc_params_json_entry["indirectParams"]; - for (uint32_t di = 0; di < dc_params.draw_count; ++di) - { - indirect_param_entries[di]["indexCount"] = dc_params.draw_indexed_params[di].indexCount; - indirect_param_entries[di]["instanceCount"] = dc_params.draw_indexed_params[di].instanceCount; - indirect_param_entries[di]["firstIndex"] = dc_params.draw_indexed_params[di].firstIndex; - indirect_param_entries[di]["vertexOffset"] = dc_params.draw_indexed_params[di].vertexOffset; - indirect_param_entries[di]["firstInstance"] = dc_params.draw_indexed_params[di].firstInstance; - } - } - break; - - case kDrawIndirectCount: - case kDrawIndirectCountKHR: - { - const DrawCallParameters::DrawCallParamsUnion::DrawIndirectCountParams& dc_params = - dc_param_entry->second.dc_params_union.draw_indirect_count; - - dc_params_json_entry["maxDrawCount"] = dc_params.max_draw_count; - dc_params_json_entry["actualDrawCount"] = dc_params.actual_draw_count; - - auto& indirect_param_entries = dc_params_json_entry["indirectParams"]; - for (uint32_t di = 0; di < dc_params.actual_draw_count; ++di) - { - indirect_param_entries[di]["vertexCount"] = dc_params.draw_params[di].vertexCount; - indirect_param_entries[di]["instanceCount"] = dc_params.draw_params[di].instanceCount; - indirect_param_entries[di]["firstVertex"] = dc_params.draw_params[di].firstVertex; - indirect_param_entries[di]["firstInstance"] = dc_params.draw_params[di].firstInstance; - } - } - break; - - case kDrawIndexedIndirectCount: - case kDrawIndexedIndirectCountKHR: - { - const DrawCallParameters::DrawCallParamsUnion::DrawIndirectCountParams& dc_params = - dc_param_entry->second.dc_params_union.draw_indirect_count; - - dc_params_json_entry["maxDrawCount"] = dc_params.max_draw_count; - dc_params_json_entry["actualDrawCount"] = dc_params.actual_draw_count; - - auto& indirect_param_entries = dc_params_json_entry["indirectParams"]; - for (uint32_t di = 0; di < dc_params.actual_draw_count; ++di) - { - indirect_param_entries[di]["indexCount"] = dc_params.draw_indexed_params[di].indexCount; - indirect_param_entries[di]["instanceCount"] = dc_params.draw_indexed_params[di].instanceCount; - indirect_param_entries[di]["firstIndex"] = dc_params.draw_indexed_params[di].firstIndex; - indirect_param_entries[di]["vertexOffset"] = dc_params.draw_indexed_params[di].vertexOffset; - indirect_param_entries[di]["firstInstance"] = dc_params.draw_indexed_params[di].firstInstance; - } - } - break; - - default: - assert(0); - } - - // Write color attachment info - if (!render_targets[rp][sp].color_att_imgs.empty()) - { - auto& rt_entries = draw_call_entry["colorAttachments"]; - - size_t f = 0; - for (size_t i = 0; i < render_targets[rp][sp].color_att_imgs.size(); ++i) - { - if (color_attachment_to_dump != kUnspecifiedColorAttachment && - static_cast(color_attachment_to_dump) != i) - { - continue; - } - - const VulkanImageInfo* image_info = render_targets[rp][sp].color_att_imgs[i]; - assert(image_info != nullptr); - - std::vector aspects; - GetFormatAspects(image_info->format, aspects); - - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < image_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) - { - std::string filenameBefore; - if (dump_resources_before) - { - filenameBefore = GenerateRenderTargetImageFilename(image_info->format, - aspect, - image_info->tiling, - image_info->type, - mip, - layer, - cmd_buf_index, - qs_index, - bcb_index, - dc_index, - i); - } - - std::string filenameAfter = - GenerateRenderTargetImageFilename(image_info->format, - aspect, - image_info->tiling, - image_info->type, - mip, - layer, - cmd_buf_index + dump_resources_before, - qs_index, - bcb_index, - dc_index, - i); - - const VkExtent3D extent = { std::max(1u, image_info->extent.width >> mip), - std::max(1u, image_info->extent.height >> mip), - image_info->extent.depth }; - - dump_json.InsertImageInfo(rt_entries[f++], - image_info->format, - image_info->type, - image_info->capture_id, - extent, - filenameAfter, - aspect, - ImageFailedScaling(filenameAfter), - mip, - layer, - dump_images_separate_alpha, - dump_resources_before ? &filenameBefore : nullptr); - - // Skip rest of layers - if (!dump_all_image_subresources) - { - break; - } - } - - // Skip rest of mip map levels - if (!dump_all_image_subresources) - { - break; - } - } - } - } - } - - // Write depth attachment info - if (dump_depth && render_targets[rp][sp].depth_att_img != nullptr) - { - auto& depth_entries = draw_call_entry["depthAttachments"]; - - const VulkanImageInfo* image_info = render_targets[rp][sp].depth_att_img; - - std::vector aspects; - GetFormatAspects(image_info->format, aspects); - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < image_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) - { - std::string filenameBefore; - if (dump_resources_before) - { - filenameBefore = GenerateRenderTargetImageFilename(image_info->format, - aspect, - image_info->tiling, - image_info->type, - mip, - layer, - cmd_buf_index, - qs_index, - bcb_index, - dc_index, - DEPTH_ATTACHMENT); - } - - std::string filenameAfter = GenerateRenderTargetImageFilename(image_info->format, - aspect, - image_info->tiling, - image_info->type, - mip, - layer, - cmd_buf_index + dump_resources_before, - qs_index, - bcb_index, - dc_index, - DEPTH_ATTACHMENT); - - const VkExtent3D extent = { std::max(1u, image_info->extent.width >> mip), - std::max(1u, image_info->extent.height >> mip), - image_info->extent.depth }; - - dump_json.InsertImageInfo(depth_entries[f++], - image_info->format, - image_info->type, - image_info->capture_id, - extent, - filenameAfter, - aspect, - ImageFailedScaling(filenameAfter), - mip, - layer, - dump_images_separate_alpha, - dump_resources_before ? &filenameBefore : nullptr); - - // Skip rest of layers - if (!dump_all_image_subresources) - { - break; - } - } - - // Skip rest of mip map levels - if (!dump_all_image_subresources) - { - break; - } - } - } - } - - // Emit in json output the references to vertex and index buffers dumped files - if (dump_vertex_index_buffers) - { - const uint64_t dc_index = dc_param_entry->first; - const DrawCallParameters& dc_param = dc_param_entry->second; - - if (IsDrawCallIndexed(dc_param.type)) - { - if (dc_param.referenced_index_buffer.buffer_info != nullptr) - { - const std::string index_buffer_filename = GenerateIndexBufferFilename( - qs_index, bcb_index, dc_index, dc_param.referenced_index_buffer.index_type); - - auto& json_entry = draw_call_entry["indexBuffer"]; - - dump_json.InsertBufferInfo( - json_entry, dc_param.referenced_index_buffer.buffer_info, index_buffer_filename); - } - } - - if (!dc_param.referenced_vertex_buffers.bound_vertex_buffer_per_binding.empty() && - !dc_param.vertex_input_state.vertex_input_binding_map.empty()) - { - auto& json_entry = draw_call_entry["vertexBuffers"]; - - uint32_t i = 0; - for (const auto& vb_binding : dc_param.vertex_input_state.vertex_input_binding_map) - { - const auto& vb_binding_buffer = - dc_param.referenced_vertex_buffers.bound_vertex_buffer_per_binding.find(vb_binding.first); - assert(vb_binding_buffer != dc_param.referenced_vertex_buffers.bound_vertex_buffer_per_binding.end()); - - if (vb_binding_buffer->second.buffer_info != nullptr) - { - const std::string vb_filename = - GenerateVertexBufferFilename(qs_index, bcb_index, dc_index, vb_binding.first); - - json_entry[i]["bufferId"] = vb_binding_buffer->second.buffer_info->capture_id; - json_entry[i]["vertexBufferBinding"] = vb_binding.first; - json_entry[i]["file"] = vb_filename; - ++i; - } - } - } - } - - // Emit in json output the references to dumped immutable descriptors - if (dump_immutable_resources) - { - const auto& dc_param_entry = draw_call_params.find(dc_index); - assert(dc_param_entry != draw_call_params.end()); - if (dc_param_entry != draw_call_params.end()) - { - const DrawCallParameters& dc_param = dc_param_entry->second; - for (const auto& shader_stage : dc_param.referenced_descriptors) - { - uint32_t stage_entry_index = 0; - for (const auto& desc_set : shader_stage.second) - { - const uint32_t desc_set_index = desc_set.first; - for (const auto& desc_binding : desc_set.second) - { - const uint32_t desc_set_binding_index = desc_binding.first; - switch (desc_binding.second.desc_type) - { - case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: - case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: - { - for (size_t img = 0; img < desc_binding.second.image_info.size(); ++img) - { - if (desc_binding.second.image_info[img].image_view_info == nullptr) - { - continue; - } - - auto& desc_shader_stage_json_entry = - draw_call_entry["descriptors"][ShaderStageToStr(shader_stage.first)]; - auto& desc_shader_binding_json_entry = - desc_shader_stage_json_entry[stage_entry_index++]; - - desc_shader_binding_json_entry["type"] = - util::ToString(desc_binding.second.desc_type); - desc_shader_binding_json_entry["set"] = desc_set_index; - desc_shader_binding_json_entry["binding"] = desc_set_binding_index; - desc_shader_binding_json_entry["arrayIndex"] = img; - - const VulkanImageInfo* image_info = object_info_table.GetVkImageInfo( - desc_binding.second.image_info[img].image_view_info->image_id); - assert(image_info != nullptr); - - std::vector aspects; - GetFormatAspects(image_info->format, aspects); - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < image_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) - { - std::string filename = - GenerateImageDescriptorFilename(image_info->format, - aspect, - image_info->tiling, - image_info->type, - image_info->capture_id, - mip, - layer, - qs_index, - bcb_index, - rp); - const VkExtent3D extent = { - std::max(1u, image_info->extent.width >> mip), - std::max(1u, image_info->extent.height >> mip), - image_info->extent.depth - }; - - auto& image_descriptor_json_entry = - desc_shader_binding_json_entry["descriptor"]; - dump_json.InsertImageInfo(image_descriptor_json_entry[f++], - image_info->format, - image_info->type, - image_info->capture_id, - extent, - filename, - aspect, - ImageFailedScaling(filename), - mip, - layer, - dump_images_separate_alpha); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - } - } - break; - - case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: - case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: - case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: - { - for (size_t buf = 0; buf < desc_binding.second.buffer_info.size(); ++buf) - { - const VulkanBufferInfo* buf_info = desc_binding.second.buffer_info[buf].buffer_info; - if (buf_info != nullptr) - { - auto& desc_shader_stage_json_entry = - draw_call_entry["descriptors"][ShaderStageToStr(shader_stage.first)]; - auto& desc_shader_binding_json_entry = - desc_shader_stage_json_entry[stage_entry_index++]; - - desc_shader_binding_json_entry["type"] = - util::ToString(desc_binding.second.desc_type); - desc_shader_binding_json_entry["set"] = desc_set_index; - desc_shader_binding_json_entry["binding"] = desc_set_binding_index; - desc_shader_binding_json_entry["arrayIndex"] = buf; - - const std::string filename = GenerateBufferDescriptorFilename( - qs_index, bcb_index, rp, buf_info->capture_id); - auto& buffer_descriptor_json_entry = - desc_shader_binding_json_entry["descriptor"]; - dump_json.InsertBufferInfo(buffer_descriptor_json_entry, buf_info, filename); - } - } - } - break; - - case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: - { - auto& desc_shader_stage_json_entry = - draw_call_entry["descriptors"][ShaderStageToStr(shader_stage.first)]; - auto& desc_shader_binding_json_entry = - desc_shader_stage_json_entry[stage_entry_index++]; - - desc_shader_binding_json_entry["type"] = - util::ToString(desc_binding.second.desc_type); - desc_shader_binding_json_entry["set"] = desc_set_index; - desc_shader_binding_json_entry["binding"] = desc_set_binding_index; - desc_shader_binding_json_entry["size"] = - desc_binding.second.inline_uniform_block.size(); - desc_shader_binding_json_entry["file"] = GenerateInlineUniformBufferDescriptorFilename( - qs_index, bcb_index, desc_set_index, desc_set_binding_index); - } - break; - - default: - break; - } - } - } - } - } - } - - if (output_json_per_command) - { - dump_json.BlockEnd(); - dump_json.Close(); - } -} - VkResult DrawCallsDumpingContext::RevertRenderTargetImageLayouts(VkQueue queue, uint64_t cmd_buf_index) { const size_t dc_index = dc_indices[CmdBufToDCVectorIndex(cmd_buf_index)]; @@ -1659,6 +1059,20 @@ VkResult DrawCallsDumpingContext::DumpRenderTargetAttachments( const VulkanDeviceInfo* device_info = object_info_table.GetVkDeviceInfo(original_command_buffer_info->parent_id); assert(device_info); + VulkanDumpResourceInfo res_info_base{}; + res_info_base.device_info = device_info; + res_info_base.device_table = device_table; + res_info_base.instance_table = instance_table; + res_info_base.object_info_table = &object_info_table; + res_info_base.original_command_buffer_info = original_command_buffer_info; + res_info_base.cmd_index = dc_index; + res_info_base.qs_index = qs_index; + res_info_base.bcb_index = bcb_index; + res_info_base.before_cmd = dump_resources_before && !(cmd_buf_index % 2); + res_info_base.rp = rp; + res_info_base.sp = sp; + res_info_base.image_extent = { render_area[rp].extent.width, render_area[rp].extent.height, 1 }; + // Dump color attachments for (size_t i = 0; i < render_targets[rp][sp].color_att_imgs.size(); ++i) { @@ -1668,253 +1082,34 @@ VkResult DrawCallsDumpingContext::DumpRenderTargetAttachments( continue; } - const VulkanImageInfo* image_info = render_targets[rp][sp].color_att_imgs[i]; - - std::vector aspects; - GetFormatAspects(image_info->format, aspects); - - const size_t total_files = dump_all_image_subresources - ? (aspects.size() * image_info->layer_count * image_info->level_count) - : aspects.size(); - - std::vector filenames(total_files); - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < image_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) - { - filenames[f++] = GenerateRenderTargetImageFilename(image_info->format, - aspect, - image_info->tiling, - image_info->type, - mip, - layer, - cmd_buf_index, - qs_index, - bcb_index, - dc_index, - i); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - - const VkExtent3D extent{ render_area[rp].extent.width, render_area[rp].extent.height, 1 }; - std::vector scaling_supported(filenames.size()); - VkResult res = DumpImageToFile(image_info, - device_info, - device_table, - instance_table, - object_info_table, - filenames, - dump_resources_scale, - scaling_supported, - image_file_format, - dump_all_image_subresources, - dump_images_raw, - dump_images_separate_alpha, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - &extent); - + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kRtv; + res_info.image_info = render_targets[rp][sp].color_att_imgs[i]; + res_info.attachment_index = i; + auto res = delegate_.DumpResource(res_info); if (res != VK_SUCCESS) { - GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) return res; } - - // Keep track of images for which scaling failed - for (size_t i = 0; i < filenames.size(); ++i) - { - if (!scaling_supported[i]) - { - images_failed_scaling.insert(filenames[i]); - } - } } // Dump depth attachment if (dump_depth && render_targets[rp][sp].depth_att_img != nullptr) { - const VulkanImageInfo* image_info = render_targets[rp][sp].depth_att_img; - - std::vector aspects; - GetFormatAspects(image_info->format, aspects); - - const size_t total_files = dump_all_image_subresources - ? (aspects.size() * image_info->layer_count * image_info->level_count) - : aspects.size(); - - std::vector filenames(total_files); - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < image_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) - { - filenames[f++] = GenerateRenderTargetImageFilename(image_info->format, - aspect, - image_info->tiling, - image_info->type, - mip, - layer, - cmd_buf_index, - qs_index, - bcb_index, - dc_index, - DEPTH_ATTACHMENT); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - - const VkExtent3D extent{ render_area[rp].extent.width, render_area[rp].extent.height, 1 }; - std::vector scaling_supported(filenames.size()); - VkResult res = DumpImageToFile(image_info, - device_info, - device_table, - instance_table, - object_info_table, - filenames, - dump_resources_scale, - scaling_supported, - image_file_format, - dump_all_image_subresources, - dump_images_raw, - dump_images_separate_alpha, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - &extent); - + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kDsv; + res_info.image_info = render_targets[rp][sp].depth_att_img; + res_info.attachment_index = DEPTH_ATTACHMENT; + auto res = delegate_.DumpResource(res_info); if (res != VK_SUCCESS) { - GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) return res; } - - // Keep track of images for which scaling failed - for (size_t i = 0; i < filenames.size(); ++i) - { - if (!scaling_supported[i]) - { - images_failed_scaling.insert(filenames[i]); - } - } } return VK_SUCCESS; } -std::string DrawCallsDumpingContext::GenerateImageDescriptorFilename(VkFormat format, - VkImageAspectFlagBits aspect, - VkImageTiling tiling, - VkImageType type, - format::HandleId image_id, - uint32_t level, - uint32_t layer, - uint64_t qs_index, - uint64_t bcb_index, - uint64_t rp) const -{ - std::string aspect_str = ImageAspectToStr(aspect); - std::stringstream base_filename; - base_filename << capture_filename << "_"; - - const VulkanDeviceInfo* device_info = object_info_table.GetVkDeviceInfo(original_command_buffer_info->parent_id); - assert(device_info); - - const DumpedImageFormat output_image_format = GetDumpedImageFormat(device_info, - device_table, - instance_table, - object_info_table, - format, - tiling, - type, - image_file_format, - dump_images_raw); - - if (output_image_format != KFormatRaw) - { - base_filename << "image_" << image_id << "_qs_" << qs_index << "_bcb_" << bcb_index << "_rp_" << rp - << "_aspect_" << aspect_str; - } - else - { - std::string whole_format_name = util::ToString(format); - std::string format_name(whole_format_name.begin() + 10, whole_format_name.end()); - - base_filename << "image_" << image_id << "_qs_" << qs_index << "_bcb_" << bcb_index << "_rp_" << rp << "_" - << format_name << "_aspect_" << aspect_str; - } - - if (dump_all_image_subresources) - { - std::stringstream sub_resources_str; - sub_resources_str << base_filename.str() << "_mip_" << level << "_layer_" << layer; - sub_resources_str << ImageFileExtension(output_image_format); - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(sub_resources_str.str()); - return (filedirname / filebasename).string(); - } - else - { - base_filename << ImageFileExtension(output_image_format); - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(base_filename.str()); - return (filedirname / filebasename).string(); - } -} - -std::string DrawCallsDumpingContext::GenerateBufferDescriptorFilename(uint64_t qs_index, - uint64_t bcb_index, - uint64_t rp, - format::HandleId buffer_id) const -{ - std::stringstream filename; - - filename << capture_filename << "_" - << "buffer_" << buffer_id << "_qs_" << qs_index << "_bcb_" << bcb_index << "_rp_" << rp << ".bin"; - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - return (filedirname / filebasename).string(); -} - -std::string DrawCallsDumpingContext::GenerateInlineUniformBufferDescriptorFilename(uint64_t qs_index, - uint64_t bcb_index, - uint32_t set, - uint32_t binding) const -{ - std::stringstream filename; - filename << capture_filename << "_" - << "inlineUniformBlock_set_" << set << "_binding_" << binding << "_qs_" << qs_index << "_bcb_" << bcb_index - << ".bin"; - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - return (filedirname / filebasename).string(); -} - VkResult DrawCallsDumpingContext::DumpImmutableDescriptors(uint64_t qs_index, uint64_t bcb_index, uint64_t dc_index, uint64_t rp) { @@ -2037,75 +1232,27 @@ DrawCallsDumpingContext::DumpImmutableDescriptors(uint64_t qs_index, uint64_t bc const VulkanDeviceInfo* device_info = object_info_table.GetVkDeviceInfo(original_command_buffer_info->parent_id); assert(device_info); + VulkanDumpResourceInfo res_info_base{}; + res_info_base.device_info = device_info; + res_info_base.device_table = device_table; + res_info_base.instance_table = instance_table; + res_info_base.object_info_table = &object_info_table; + res_info_base.original_command_buffer_info = original_command_buffer_info; + res_info_base.cmd_index = dc_index; + res_info_base.qs_index = qs_index; + res_info_base.bcb_index = bcb_index; + res_info_base.rp = rp; + for (const auto& image_info : image_descriptors) { - std::vector aspects; - GetFormatAspects(image_info->format, aspects); - - const size_t total_files = dump_all_image_subresources - ? (aspects.size() * image_info->layer_count * image_info->level_count) - : aspects.size(); - - std::vector filenames(total_files); - - size_t f = 0; - for (auto aspect : aspects) - { - for (uint32_t mip = 0; mip < image_info->level_count; ++mip) - { - for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) - { - filenames[f++] = GenerateImageDescriptorFilename(image_info->format, - aspect, - image_info->tiling, - image_info->type, - image_info->capture_id, - mip, - layer, - qs_index, - bcb_index, - rp); - - if (!dump_all_image_subresources) - { - break; - } - } - - if (!dump_all_image_subresources) - { - break; - } - } - } - - std::vector scaling_supported(total_files); - VkResult res = DumpImageToFile(image_info, - device_info, - device_table, - instance_table, - object_info_table, - filenames, - dump_resources_scale, - scaling_supported, - image_file_format, - dump_all_image_subresources, - dump_images_raw, - dump_images_separate_alpha); + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kImageDescriptor; + res_info.image_info = image_info; + auto res = delegate_.DumpResource(res_info); if (res != VK_SUCCESS) { - GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) return res; } - - // Keep track of images for which scaling failed - for (size_t i = 0; i < filenames.size(); ++i) - { - if (!scaling_supported[i]) - { - images_failed_scaling.insert(filenames[i]); - } - } } const VulkanPhysicalDeviceInfo* phys_dev_info = object_info_table.GetVkPhysicalDeviceInfo(device_info->parent_id); @@ -2119,67 +1266,47 @@ DrawCallsDumpingContext::DumpImmutableDescriptors(uint64_t qs_index, uint64_t bc for (const auto& buf : buffer_descriptors) { - const VulkanBufferInfo* buffer_info = buf.first; - const VkDeviceSize offset = buf.second.offset; - const VkDeviceSize range = buf.second.range; - const VkDeviceSize size = range == VK_WHOLE_SIZE ? buffer_info->size - offset : range; + VulkanDumpResourceInfo res_info = res_info_base; + res_info.buffer_info = buf.first; + const VkDeviceSize offset = buf.second.offset; + const VkDeviceSize range = buf.second.range; + const VkDeviceSize size = range == VK_WHOLE_SIZE ? res_info.buffer_info->size - offset : range; - std::vector data; - VkResult res = resource_util.ReadFromBufferResource( - buffer_info->handle, size, offset, buffer_info->queue_family_index, data); + VkResult res = resource_util.ReadFromBufferResource( + res_info.buffer_info->handle, size, offset, res_info.buffer_info->queue_family_index, res_info.data); if (res != VK_SUCCESS) { GFXRECON_LOG_ERROR("Reading from buffer resource %" PRIu64 " failed (%s).", - buffer_info->capture_id, + res_info.buffer_info->capture_id, util::ToString(res).c_str()) return res; } - const std::string filename = GenerateBufferDescriptorFilename(qs_index, bcb_index, rp, buffer_info->capture_id); - util::bufferwriter::WriteBuffer(filename, data.data(), data.size()); + res_info.type = DumpResourceType::kBufferDescriptor; + res = delegate_.DumpResource(res_info); + if (res != VK_SUCCESS) + { + return res; + } } for (const auto& iub : inline_uniform_blocks) { - std::string filename = - GenerateInlineUniformBufferDescriptorFilename(qs_index, bcb_index, iub.second.set, iub.second.binding); - util::bufferwriter::WriteBuffer(filename, iub.second.data->data(), iub.second.data->size()); + VulkanDumpResourceInfo res_info = res_info_base; + res_info.type = DumpResourceType::kInlineUniformBufferDescriptor; + res_info.set = iub.second.set; + res_info.binding = iub.second.binding; + res_info.data = *iub.second.data; + auto res = delegate_.DumpResource(res_info); + if (res != VK_SUCCESS) + { + return res; + } } return VK_SUCCESS; } -std::string DrawCallsDumpingContext::GenerateIndexBufferFilename(uint64_t qs_index, - uint64_t bcb_index, - uint64_t dc_index, - VkIndexType type) const -{ - std::stringstream filename; - filename << capture_filename << "_"; - std::string index_type_name = IndexTypeToStr(type); - filename << "indexBuffer_" - << "qs_" << qs_index << "_bcb_" << bcb_index << "_dc_" << dc_index << index_type_name << ".bin"; - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - return (filedirname / filebasename).string(); -} - -std::string DrawCallsDumpingContext::GenerateVertexBufferFilename(uint64_t qs_index, - uint64_t bcb_index, - uint64_t dc_index, - uint32_t binding) const -{ - std::stringstream filename; - filename << capture_filename << "_" - << "vertexBuffers_" - << "qs_" << qs_index << "_bcb_" << bcb_index << "_dc_" << dc_index << "_binding_" << binding << ".bin"; - - std::filesystem::path filedirname(dump_resource_path); - std::filesystem::path filebasename(filename.str()); - return (filedirname / filebasename).string(); -} - VkResult DrawCallsDumpingContext::FetchDrawIndirectParams(uint64_t dc_index) { assert(original_command_buffer_info); @@ -2362,6 +1489,16 @@ VkResult DrawCallsDumpingContext::DumpVertexIndexBuffers(uint64_t qs_index, uint uint32_t greatest_vertex_index = 0; + VulkanDumpResourceInfo res_info_base{}; + res_info_base.device_info = device_info; + res_info_base.device_table = device_table; + res_info_base.instance_table = instance_table; + res_info_base.object_info_table = &object_info_table; + res_info_base.original_command_buffer_info = original_command_buffer_info; + res_info_base.cmd_index = dc_index; + res_info_base.qs_index = qs_index; + res_info_base.bcb_index = bcb_index; + // Dump index buffer if (IsDrawCallIndexed(dc_params.type) && dc_params.referenced_index_buffer.buffer_info != nullptr) { @@ -2449,14 +1586,13 @@ VkResult DrawCallsDumpingContext::DumpVertexIndexBuffers(uint64_t qs_index, uint } dc_params.referenced_index_buffer.actual_size = total_size; - - std::vector index_data; - VkResult res = + VulkanDumpResourceInfo res_info = res_info_base; + VkResult res = resource_util.ReadFromBufferResource(dc_params.referenced_index_buffer.buffer_info->handle, total_size, offset, dc_params.referenced_index_buffer.buffer_info->queue_family_index, - index_data); + res_info.data); if (res != VK_SUCCESS) { GFXRECON_LOG_ERROR("Reading index buffer resource %" PRIu64 " failed (%s).", @@ -2465,12 +1601,17 @@ VkResult DrawCallsDumpingContext::DumpVertexIndexBuffers(uint64_t qs_index, uint return res; } - std::string filename = GenerateIndexBufferFilename(qs_index, bcb_index, dc_index, index_type); - util::bufferwriter::WriteBuffer(filename, index_data.data(), index_data.size()); + res_info.type = DumpResourceType::kIndex; + res_info.index_type = index_type; + res = delegate_.DumpResource(res_info); + if (res != VK_SUCCESS) + { + return res; + } for (const auto& pairs : index_count_first_index_pairs) { - const uint32_t gvi = FindGreatestVertexIndex(index_data, pairs.first, pairs.second, index_type); + const uint32_t gvi = FindGreatestVertexIndex(res_info.data, pairs.first, pairs.second, index_type); if (greatest_vertex_index < gvi) { greatest_vertex_index = gvi; @@ -2667,14 +1808,14 @@ VkResult DrawCallsDumpingContext::DumpVertexIndexBuffers(uint64_t qs_index, uint total_size = vb_entry->second.buffer_info->size - offset; } - vb_entry->second.actual_size = total_size; + vb_entry->second.actual_size = total_size; + VulkanDumpResourceInfo res_info = res_info_base; - std::vector vb_data; - VkResult res = resource_util.ReadFromBufferResource(vb_entry->second.buffer_info->handle, + VkResult res = resource_util.ReadFromBufferResource(vb_entry->second.buffer_info->handle, total_size, offset, vb_entry->second.buffer_info->queue_family_index, - vb_data); + res_info.data); if (res != VK_SUCCESS) { GFXRECON_LOG_ERROR("Reading from buffer resource failed (%s).", @@ -2682,8 +1823,15 @@ VkResult DrawCallsDumpingContext::DumpVertexIndexBuffers(uint64_t qs_index, uint return res; } - std::string filename = GenerateVertexBufferFilename(qs_index, bcb_index, dc_index, binding); - util::bufferwriter::WriteBuffer(filename, vb_data.data(), vb_data.size()); + res_info.type = DumpResourceType::kVertex; + res_info.binding = binding; + res = delegate_.DumpResource(res_info); + if (res != VK_SUCCESS) + { + GFXRECON_LOG_ERROR("Reading from buffer resource failed (%s).", + util::ToString(res).c_str()) + return res; + } } } } diff --git a/framework/decode/vulkan_replay_dump_resources_draw_calls.h b/framework/decode/vulkan_replay_dump_resources_draw_calls.h index cecd0e5d5f..e359547068 100644 --- a/framework/decode/vulkan_replay_dump_resources_draw_calls.h +++ b/framework/decode/vulkan_replay_dump_resources_draw_calls.h @@ -27,7 +27,6 @@ #include "decode/vulkan_replay_dump_resources_common.h" #include "decode/vulkan_object_info.h" #include "decode/vulkan_replay_options.h" -#include "decode/vulkan_replay_dump_resources_json.h" #include "generated/generated_vulkan_dispatch_table.h" #include "format/format.h" #include "util/defines.h" @@ -48,8 +47,7 @@ class DrawCallsDumpingContext const std::vector>& rp_indices, CommonObjectInfoTable& object_info_table, const VulkanReplayOptions& options, - VulkanReplayDumpResourcesJson& dump_json, - std::string capture_filename); + VulkanDumpResourcesDelegate& delegate); ~DrawCallsDumpingContext(); @@ -192,45 +190,6 @@ class DrawCallsDumpingContext void SetRenderArea(const VkRect2D& new_render_area); - std::string GenerateRenderTargetImageFilename(VkFormat format, - VkImageAspectFlagBits aspect, - VkImageTiling tiling, - VkImageType type, - uint32_t mip_level, - uint32_t layer, - uint64_t cmd_buf_index, - uint64_t qs_index, - uint64_t bcb_index, - uint64_t dc_index, - int attachment_index) const; - - std::string GenerateImageDescriptorFilename(VkFormat format, - VkImageAspectFlagBits aspect, - VkImageTiling tiling, - VkImageType type, - format::HandleId image_id, - uint32_t level, - uint32_t layer, - uint64_t qs_index, - uint64_t bcb_index, - uint64_t rp) const; - - std::string GenerateBufferDescriptorFilename(uint64_t qs_index, - uint64_t bcb_index, - uint64_t rp, - format::HandleId buffer_id) const; - - std::string GenerateInlineUniformBufferDescriptorFilename(uint64_t qs_index, - uint64_t bcb_index, - uint32_t set, - uint32_t binding) const; - - std::string - GenerateVertexBufferFilename(uint64_t qs_index, uint64_t bcb_index, uint64_t dc_index, uint32_t binding) const; - - std::string - GenerateIndexBufferFilename(uint64_t qs_index, uint64_t bcb_index, uint64_t dc_index, VkIndexType type) const; - using RenderPassSubpassPair = std::pair; RenderPassSubpassPair GetRenderPassIndex(uint64_t dc_index) const; size_t CmdBufToDCVectorIndex(size_t cmd_buf_index) const; @@ -247,9 +206,6 @@ class DrawCallsDumpingContext VkResult FetchDrawIndirectParams(uint64_t dc_index); - void GenerateOutputJsonDrawCallInfo( - uint64_t qs_index, uint64_t bcb_index, uint64_t cmd_buf_index, uint64_t rp, uint64_t sp) const; - VkResult RevertRenderTargetImageLayouts(VkQueue queue, uint64_t dc_index); VulkanCommandBufferInfo* original_command_buffer_info; @@ -264,18 +220,11 @@ class DrawCallsDumpingContext uint32_t current_subpass; uint32_t n_subpasses; bool dump_resources_before; - const std::string& dump_resource_path; - util::ScreenshotFormat image_file_format; - float dump_resources_scale; - VulkanReplayDumpResourcesJson& dump_json; + VulkanDumpResourcesDelegate& delegate_; bool dump_depth; int32_t color_attachment_to_dump; bool dump_vertex_index_buffers; - bool output_json_per_command; bool dump_immutable_resources; - bool dump_all_image_subresources; - bool dump_images_raw; - bool dump_images_separate_alpha; enum RenderPassType { @@ -297,6 +246,7 @@ class DrawCallsDumpingContext std::unordered_map dynamic_rendering_attachment_layouts; + public: struct RenderTargets { RenderTargets() : depth_att_img(nullptr) {} @@ -305,6 +255,7 @@ class DrawCallsDumpingContext VulkanImageInfo* depth_att_img; }; + private: // render_targets is basically a 2d array (vector of vectors). It is indexed like render_targets[rp][sp] // where rp specifies the render pass and sp the subpass. std::vector> render_targets; @@ -315,6 +266,7 @@ class DrawCallsDumpingContext // One entry per descriptor set std::unordered_map bound_descriptor_sets_gr; + public: struct VertexInputState { // One entry per binding @@ -324,9 +276,11 @@ class DrawCallsDumpingContext VulkanPipelineInfo::VertexInputAttributeMap vertex_input_attribute_map; }; + private: // Keep track of CmdSetVertexInputEXT VertexInputState dynamic_vertex_input_state; + public: // Keep track of bound vertex buffers struct BoundVertexBuffersInfo { @@ -358,8 +312,10 @@ class DrawCallsDumpingContext std::unordered_map bound_vertex_buffer_per_binding; }; + private: BoundVertexBuffersInfo bound_vertex_buffers; + public: // Keep track of bound index buffer struct BoundIndexBuffer { @@ -386,8 +342,10 @@ class DrawCallsDumpingContext VkDeviceSize actual_size; }; + private: BoundIndexBuffer bound_index_buffer; + public: enum DrawCallTypes { kDraw, @@ -676,6 +634,7 @@ class DrawCallsDumpingContext referenced_descriptors; }; + private: // One entry for each draw call std::unordered_map draw_call_params; @@ -702,12 +661,6 @@ class DrawCallsDumpingContext std::vector render_pass_dumped_descriptors; - // Keep track of images for which scalling failed so we can - // note them in the output json - std::unordered_set images_failed_scaling; - - bool ImageFailedScaling(const std::string& filename) const { return images_failed_scaling.count(filename); } - VkCommandBuffer aux_command_buffer; VkFence aux_fence; bool must_backup_resources; @@ -716,7 +669,6 @@ class DrawCallsDumpingContext const encode::VulkanInstanceTable* instance_table; CommonObjectInfoTable& object_info_table; const VkPhysicalDeviceMemoryProperties* replay_device_phys_mem_props; - std::string capture_filename; }; GFXRECON_END_NAMESPACE(gfxrecon)