diff --git a/USAGE_android.md b/USAGE_android.md index 458bcb8692..8215ae99bb 100644 --- a/USAGE_android.md +++ b/USAGE_android.md @@ -709,6 +709,7 @@ usage: gfxrecon.py replay [-h] [--push-file LOCAL_FILE] [--version] [--pause-fra [--dump-resources-dump-vertex-index-buffers] [--dump-resources-json-output-per-command] [--dump-resources-dump-immutable-resources] + [--dump-resources-dump-raw-images] [--dump-resources-dump-all-image-subresources] [--pbi-all] [--pbis ] [file] @@ -902,6 +903,8 @@ optional arguments: Enables dumping of resources that are used as inputs in the commands requested for dumping --dump-resources-dump-all-image-subresources Enables dumping of all image sub resources (mip map levels and array layers) + --dump-resources-dump-raw-images + When enabled all image resources will be dumped verbatim as raw bin files. --pbi-all Print all block information. --pbis diff --git a/USAGE_desktop_Vulkan.md b/USAGE_desktop_Vulkan.md index ca4de634ad..6ea3aa9d37 100644 --- a/USAGE_desktop_Vulkan.md +++ b/USAGE_desktop_Vulkan.md @@ -542,6 +542,7 @@ gfxrecon-replay [-h | --help] [--version] [--gpu ] [--dump-resources-dump-vertex-index-buffers] [--dump-resources-json-output-per-command] [--dump-resources-dump-immutable-resources] + [--dump-resources-dump-raw-images] [--dump-resources-dump-all-image-subresources] [--pbi-all] [--pbis ] [--pipeline-creation-jobs | --pcj ] @@ -758,7 +759,9 @@ Optional arguments: Enables dumping of resources that are used as inputs in the commands requested for dumping. --dump-resources-dump-all-image-subresources Enables dumping of all image sub resources (mip map levels and array layers). - --pbi-all + --dump-resources-dump-raw-images + When enabled all image resources will be dumped verbatim as raw bin files. + --pbi-all Print all block information. --pbis Print block information between block index1 and block index2. @@ -766,7 +769,7 @@ Optional arguments: Specify the number of asynchronous pipeline-creation jobs as integer. If is negative it will be added to the number of cpu-cores, e.g. -1 -> num_cores - 1. Default: 0 (do not use asynchronous operations) - + ``` ### Key Controls diff --git a/android/scripts/gfxrecon.py b/android/scripts/gfxrecon.py index 6b2084f3dc..c2c9742db8 100644 --- a/android/scripts/gfxrecon.py +++ b/android/scripts/gfxrecon.py @@ -111,6 +111,7 @@ def CreateReplayParser(): parser.add_argument('--dump-resources-json-output-per-command', action='store_true', default=False, help= 'Enables storing a json output file for each dumped command. Default is disabled.') parser.add_argument('--dump-resources-dump-immutable-resources', action='store_true', default=False, help= 'Dump immutable immutable shader resources.') parser.add_argument('--dump-resources-dump-all-image-subresources', action='store_true', default=False, help= 'Dump all available mip levels and layers when dumping images.') + parser.add_argument('--dump-resources-dump-raw-images', action='store_true', default=False, help= 'Dump images verbatim as raw binary files.') parser.add_argument('--pbi-all', action='store_true', default=False, help='Print all block information.') parser.add_argument('--pbis', metavar='RANGES', default=False, help='Print block information between block index1 and block index2') parser.add_argument('--pcj', '--pipeline-creation-jobs', action='store_true', default=False, help='Specify the number of pipeline-creation-jobs or background-threads.') @@ -271,6 +272,9 @@ def MakeExtrasString(args): if args.dump_resources_dump_all_image_subresources: arg_list.append('--dump-resources-dump-all-image-subresources') + if args.dump_resources_dump_raw_images: + arg_list.append('--dump-resources-dump-raw-images') + if args.pbi_all: arg_list.append('--pbi-all') diff --git a/framework/decode/vulkan_replay_dump_resources_common.cpp b/framework/decode/vulkan_replay_dump_resources_common.cpp index 37746b3b7b..3975929ab1 100644 --- a/framework/decode/vulkan_replay_dump_resources_common.cpp +++ b/framework/decode/vulkan_replay_dump_resources_common.cpp @@ -59,7 +59,7 @@ bool IsFormatAstcCompressed(VkFormat format) return vkuFormatIsCompressed_ASTC_HDR(format) || vkuFormatIsCompressed_ASTC_LDR(format); } -util::imagewriter::DataFormats VkFormatToImageWriterDataFormat(VkFormat format) +static util::imagewriter::DataFormats VkFormatToImageWriterDataFormat(VkFormat format) { if (IsFormatAstcCompressed(format)) { @@ -68,9 +68,6 @@ util::imagewriter::DataFormats VkFormatToImageWriterDataFormat(VkFormat format) switch (format) { - case VK_FORMAT_R8_UNORM: - return util::imagewriter::DataFormats::kFormat_R8; - case VK_FORMAT_R8G8B8_UNORM: return util::imagewriter::DataFormats::kFormat_RGB; @@ -81,19 +78,10 @@ util::imagewriter::DataFormats VkFormatToImageWriterDataFormat(VkFormat format) case VK_FORMAT_B8G8R8_UNORM: return util::imagewriter::DataFormats::kFormat_BGR; - case VK_FORMAT_R16G16B16A16_SFLOAT: - return util::imagewriter::DataFormats::kFormat_R16G16B16A16_SFLOAT; - - case VK_FORMAT_B10G11R11_UFLOAT_PACK32: - return util::imagewriter::DataFormats::kFormat_B10G11R11_UFLOAT; - case VK_FORMAT_B8G8R8A8_SRGB: case VK_FORMAT_B8G8R8A8_UNORM: return util::imagewriter::DataFormats::kFormat_BGRA; - case VK_FORMAT_A2B10G10R10_UNORM_PACK32: - return util::imagewriter::DataFormats::kFormat_A2B10G10R10; - case VK_FORMAT_D32_SFLOAT: case VK_FORMAT_D32_SFLOAT_S8_UINT: return util::imagewriter::DataFormats::kFormat_D32_FLOAT; @@ -109,36 +97,45 @@ util::imagewriter::DataFormats VkFormatToImageWriterDataFormat(VkFormat format) } } -const char* ImageFileExtension(VkFormat format, util::ScreenshotFormat image_file_format) +const char* ImageFileExtension(DumpedImageFormat image_format) { - const util::imagewriter::DataFormats output_image_format = VkFormatToImageWriterDataFormat(format); - - if (output_image_format != util::imagewriter::DataFormats::kFormat_UNSPECIFIED) + switch (image_format) { - if (output_image_format == util::imagewriter::DataFormats::kFormat_ASTC) - { + case kFormatBMP: + return ".bmp"; + + case KFormatPNG: + return ".png"; + + case KFormatAstc: return ".astc"; - } - else - { - switch (image_file_format) - { - case util::ScreenshotFormat::kBmp: - return ".bmp"; - case util::ScreenshotFormat::kPng: - return ".png"; + case KFormatRaw: + default: + return ".bin"; + } +} - default: - assert(0); - return ".bmp"; - } - } +static VkFormat ChooseDestinationImageFormat(VkFormat format) +{ + VkFormat dst_format; + + if (vkuFormatIsSRGB(format)) + { + dst_format = vkuFormatHasAlpha(format) ? VK_FORMAT_B8G8R8A8_SRGB : VK_FORMAT_B8G8R8_SRGB; + } + else if (vkuFormatIsDepthOrStencil(format)) + { + // Converting depth format with vkCmdBlit is not allowed. + // We will do the conversion on the cpu. + dst_format = format; } else { - return ".bin"; + dst_format = vkuFormatHasAlpha(format) ? VK_FORMAT_B8G8R8A8_UNORM : VK_FORMAT_B8G8R8_UNORM; } + + return dst_format; } uint32_t GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& memory_properties, @@ -448,6 +445,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info, std::vector& scaling_supported, util::ScreenshotFormat image_file_format, bool dump_all_subresources, + bool dump_image_raw, VkImageLayout layout, const VkExtent3D* extent_p) { @@ -477,6 +475,8 @@ VkResult DumpImageToFile(const ImageInfo* image_info, (extent_p != nullptr) ? extent_p->height : image_info->extent.height, (extent_p != nullptr) ? extent_p->depth : image_info->extent.depth }; + const VkFormat dst_format = ChooseDestinationImageFormat(image_info->format); + uint32_t f = 0; for (size_t i = 0; i < aspects.size(); ++i) { @@ -504,7 +504,8 @@ VkResult DumpImageToFile(const ImageInfo* image_info, subresource_sizes, scaled, false, - scale); + scale, + dst_format); assert(!subresource_offsets.empty()); assert(!subresource_sizes.empty()); @@ -519,7 +520,18 @@ VkResult DumpImageToFile(const ImageInfo* image_info, return res; } - const util::imagewriter::DataFormats output_image_format = VkFormatToImageWriterDataFormat(image_info->format); + const DumpedImageFormat output_image_format = GetDumpedImageFormat(device_info, + device_table, + instance_table, + object_info_table, + image_info->format, + image_info->tiling, + image_info->type, + image_file_format, + dump_image_raw); + + const util::imagewriter::DataFormats image_writer_format = VkFormatToImageWriterDataFormat(dst_format); + assert(image_writer_format != util::imagewriter::DataFormats::kFormat_UNSPECIFIED); if ((image_info->level_count == 1 && image_info->layer_count == 1) || !dump_all_subresources) { @@ -529,7 +541,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info, if (aspects[i] == VK_IMAGE_ASPECT_STENCIL_BIT) continue; - if (output_image_format != util::imagewriter::DataFormats::kFormat_UNSPECIFIED) + if (output_image_format != KFormatRaw) { VkExtent3D scaled_extent; if (scale != 1.0f && scaled) @@ -543,10 +555,10 @@ VkResult DumpImageToFile(const ImageInfo* image_info, scaled_extent = image_info->extent; } - const uint32_t texel_size = vkuFormatElementSizeWithAspect(image_info->format, aspects[i]); + const uint32_t texel_size = vkuFormatElementSizeWithAspect(dst_format, aspects[i]); const uint32_t stride = texel_size * scaled_extent.width; - if (output_image_format == util::imagewriter::DataFormats::kFormat_ASTC) + if (output_image_format == KFormatAstc) { VKU_FORMAT_INFO format_info = vkuGetFormatInfo(image_info->format); @@ -560,7 +572,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info, data.data(), subresource_sizes[0]); } - else if (image_file_format == util::ScreenshotFormat::kBmp) + else if (output_image_format == kFormatBMP) { util::imagewriter::WriteBmpImage(filename, scaled_extent.width, @@ -568,10 +580,10 @@ VkResult DumpImageToFile(const ImageInfo* image_info, subresource_sizes[0], data.data(), stride, - output_image_format, + image_writer_format, vkuFormatHasAlpha(image_info->format)); } - else if (image_file_format == util::ScreenshotFormat::kPng) + else if (output_image_format == KFormatPNG) { util::imagewriter::WritePngImage(filename, scaled_extent.width, @@ -579,7 +591,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info, subresource_sizes[0], data.data(), stride, - output_image_format, + image_writer_format, vkuFormatHasAlpha(image_info->format)); } } @@ -607,7 +619,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info, const void* data_offset = reinterpret_cast( reinterpret_cast(data.data()) + subresource_offsets[sub_res_idx]); - if (output_image_format != util::imagewriter::DataFormats::kFormat_UNSPECIFIED) + if (output_image_format != KFormatRaw) { VkExtent3D scaled_extent; if (scale != 1.0f && scaled) @@ -628,7 +640,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info, const uint32_t texel_size = vkuFormatElementSizeWithAspect(image_info->format, aspect); const uint32_t stride = texel_size * scaled_extent.width; - if (output_image_format == util::imagewriter::DataFormats::kFormat_ASTC) + if (output_image_format == KFormatAstc) { VKU_FORMAT_INFO format_info = vkuGetFormatInfo(image_info->format); @@ -642,7 +654,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info, data.data(), subresource_sizes[sub_res_idx]); } - else if (image_file_format == util::ScreenshotFormat::kBmp) + else if (output_image_format == kFormatBMP) { util::imagewriter::WriteBmpImage(filename, scaled_extent.width, @@ -650,9 +662,9 @@ VkResult DumpImageToFile(const ImageInfo* image_info, subresource_sizes[sub_res_idx], data_offset, stride, - output_image_format); + image_writer_format); } - else if (image_file_format == util::ScreenshotFormat::kPng) + else if (output_image_format == KFormatPNG) { util::imagewriter::WritePngImage(filename, scaled_extent.width, @@ -660,7 +672,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info, subresource_sizes[sub_res_idx], data_offset, stride, - output_image_format); + image_writer_format); } } else @@ -854,5 +866,69 @@ void GetFormatAspects(VkFormat format, std::vector& aspec } } +DumpedImageFormat GetDumpedImageFormat(const DeviceInfo* device_info, + const encode::VulkanDeviceTable* device_table, + const encode::VulkanInstanceTable* instance_table, + VulkanObjectInfoTable& object_info_table, + VkFormat src_format, + VkImageTiling src_image_tiling, + VkImageType type, + util::ScreenshotFormat image_file_format, + bool dump_raw) +{ + const PhysicalDeviceInfo* phys_dev_info = object_info_table.GetPhysicalDeviceInfo(device_info->parent_id); + assert(phys_dev_info); + + // If there's a request for images to be dumped as raw bin files + if (dump_raw) + { + // We consider astc as a raw bin format + if (IsFormatAstcCompressed(src_format)) + { + return KFormatAstc; + } + else + { + return KFormatRaw; + } + } + + // Astc images will be dumped as .astc files + if (IsFormatAstcCompressed(src_format)) + { + return KFormatAstc; + } + + graphics::VulkanResourcesUtil resource_util(device_info->handle, + device_info->parent, + *device_table, + *instance_table, + *phys_dev_info->replay_device_info->memory_properties); + + // Image cannot be converted into a format compatible for dumping in an image file + const VkFormat dst_format = ChooseDestinationImageFormat(src_format); + bool is_blit_supported = resource_util.IsBlitSupported(src_format, src_image_tiling, dst_format); + if (!vkuFormatIsDepthOrStencil(src_format) && src_format != dst_format && !is_blit_supported) + { + return KFormatRaw; + } + + // Choose the requested preference for image file extension + switch (image_file_format) + { + case util::ScreenshotFormat::kBmp: + return kFormatBMP; + + case util::ScreenshotFormat::kPng: + return KFormatPNG; + + default: + assert(0); + return KFormatRaw; + } + + return KFormatRaw; +} + GFXRECON_END_NAMESPACE(gfxrecon) GFXRECON_END_NAMESPACE(decode) diff --git a/framework/decode/vulkan_replay_dump_resources_common.h b/framework/decode/vulkan_replay_dump_resources_common.h index e64076c522..caf44826f6 100644 --- a/framework/decode/vulkan_replay_dump_resources_common.h +++ b/framework/decode/vulkan_replay_dump_resources_common.h @@ -60,9 +60,25 @@ PipelineBindPoints VkPipelineBindPointToPipelineBindPoint(VkPipelineBindPoint bi bool IsFormatAstcCompressed(VkFormat format); -util::imagewriter::DataFormats VkFormatToImageWriterDataFormat(VkFormat format); +enum DumpedImageFormat +{ + kFormatBMP, + KFormatPNG, + KFormatAstc, + KFormatRaw +}; + +DumpedImageFormat GetDumpedImageFormat(const DeviceInfo* device_info, + const encode::VulkanDeviceTable* device_table, + const encode::VulkanInstanceTable* instance_table, + VulkanObjectInfoTable& object_info_table, + VkFormat src_format, + VkImageTiling src_image_tiling, + VkImageType type, + util::ScreenshotFormat image_file_format, + bool dump_raw = false); -const char* ImageFileExtension(VkFormat format, util::ScreenshotFormat image_file_format); +const char* ImageFileExtension(DumpedImageFormat image_format); uint32_t GetMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& memory_properties, uint32_t type_bits, @@ -100,6 +116,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info, std::vector& scaling_supported, util::ScreenshotFormat image_file_format, bool dump_all_subresources = false, + bool dump_image_raw = false, VkImageLayout layout = VK_IMAGE_LAYOUT_MAX_ENUM, const VkExtent3D* extent_p = nullptr); 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 8ba6d75f7b..6508c8ca53 100644 --- a/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.cpp +++ b/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.cpp @@ -64,7 +64,7 @@ DispatchTraceRaysDumpingContext::DispatchTraceRaysDumpingContext(const std::vect 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) + reached_end_command_buffer(false), dump_images_raw(options.dump_resources_dump_raw_images) {} DispatchTraceRaysDumpingContext::~DispatchTraceRaysDumpingContext() @@ -918,6 +918,8 @@ std::string DispatchTraceRaysDumpingContext::GenerateDispatchTraceRaysImageFilen uint32_t mip, uint32_t layer, VkImageAspectFlagBits aspect, + VkImageTiling tiling, + VkImageType type, bool is_dispatch, uint64_t qs_index, uint64_t bcb_index, @@ -928,9 +930,21 @@ std::string DispatchTraceRaysDumpingContext::GenerateDispatchTraceRaysImageFilen VkShaderStageFlagBits stage, bool before_cmd) const { - const util::imagewriter::DataFormats output_image_format = VkFormatToImageWriterDataFormat(format); - const std::string shader_stage_name = ShaderStageToStr(stage); - const std::string aspect_str = ImageAspectToStr(aspect); + const DeviceInfo* device_info = object_info_table.GetDeviceInfo(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 << '_'; @@ -940,7 +954,7 @@ std::string DispatchTraceRaysDumpingContext::GenerateDispatchTraceRaysImageFilen 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 != util::imagewriter::DataFormats::kFormat_UNSPECIFIED) + if (output_image_format != KFormatRaw) { filename << "_" << util::ToString(format).c_str(); } @@ -951,7 +965,7 @@ std::string DispatchTraceRaysDumpingContext::GenerateDispatchTraceRaysImageFilen 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 != util::imagewriter::DataFormats::kFormat_UNSPECIFIED) + if (output_image_format != KFormatRaw) { filename << "_" << util::ToString(format).c_str(); } @@ -963,7 +977,7 @@ std::string DispatchTraceRaysDumpingContext::GenerateDispatchTraceRaysImageFilen filename << "_mip_" << mip << "_layer_" << layer; } - filename << ImageFileExtension(format, image_file_format); + filename << ImageFileExtension(output_image_format); std::filesystem::path filedirname(dump_resource_path); std::filesystem::path filebasename(filename.str()); @@ -1086,6 +1100,8 @@ VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_inde mip, layer, aspect, + modified_image_info.tiling, + modified_image_info.type, is_dispatch, qs_index, bcb_index, @@ -1120,6 +1136,7 @@ VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_inde scaling_supported, image_file_format, false, + dump_images_raw, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); if (res != VK_SUCCESS) { @@ -1201,6 +1218,8 @@ VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_inde mip, layer, aspect, + modified_image_info.tiling, + modified_image_info.type, is_dispatch, qs_index, bcb_index, @@ -1235,6 +1254,7 @@ VkResult DispatchTraceRaysDumpingContext::DumpMutableResources(uint64_t bcb_inde scaling_supported, image_file_format, false, + dump_images_raw, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); if (res != VK_SUCCESS) { @@ -1383,6 +1403,8 @@ std::string DispatchTraceRaysDumpingContext::GenerateImageDescriptorFilename(VkF uint32_t layer, format::HandleId image_id, VkImageAspectFlagBits aspect, + VkImageTiling tiling, + VkImageType type, uint64_t qs_index, uint64_t bcb_index) const { @@ -1391,7 +1413,20 @@ std::string DispatchTraceRaysDumpingContext::GenerateImageDescriptorFilename(VkF base_filename << capture_filename << '_'; - if (VkFormatToImageWriterDataFormat(format) != util::imagewriter::DataFormats::kFormat_UNSPECIFIED) + const DeviceInfo* device_info = object_info_table.GetDeviceInfo(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 && output_image_format != KFormatAstc) { base_filename << "image_" << image_id << "_qs_" << qs_index << "_bcb_" << bcb_index << "_aspect_" << aspect_str; } @@ -1404,17 +1439,16 @@ std::string DispatchTraceRaysDumpingContext::GenerateImageDescriptorFilename(VkF if (dump_all_image_subresources) { - std::stringstream sub_resources_str; sub_resources_str << base_filename.str() << "_mip_" << mip << "_layer_" << layer; - sub_resources_str << ImageFileExtension(format, image_file_format); + 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(format, image_file_format); + base_filename << ImageFileExtension(output_image_format); std::filesystem::path filedirname(dump_resource_path); std::filesystem::path filebasename(base_filename.str()); return (filedirname / filebasename).string(); @@ -1679,8 +1713,15 @@ VkResult DispatchTraceRaysDumpingContext::DumpImmutableDescriptors(uint64_t qs_i { for (uint32_t layer = 0; layer < img_info->layer_count; ++layer) { - filenames[f++] = GenerateImageDescriptorFilename( - img_info->format, mip, layer, img_info->capture_id, aspect, qs_index, bcb_index); + 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) { @@ -1705,7 +1746,8 @@ VkResult DispatchTraceRaysDumpingContext::DumpImmutableDescriptors(uint64_t qs_i dump_resources_scale, scaling_supported, image_file_format, - dump_all_image_subresources); + dump_all_image_subresources, + dump_images_raw); if (res != VK_SUCCESS) { GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) @@ -2127,6 +2169,8 @@ void DispatchTraceRaysDumpingContext::GenerateOutputJsonDispatchInfo(uint64_t qs mip, layer, aspect, + img_info->tiling, + img_info->type, true, qs_index, bcb_index, @@ -2231,6 +2275,8 @@ void DispatchTraceRaysDumpingContext::GenerateOutputJsonDispatchInfo(uint64_t qs mip, layer, aspect, + img_info->tiling, + img_info->type, true, qs_index, bcb_index, @@ -2347,6 +2393,8 @@ void DispatchTraceRaysDumpingContext::GenerateOutputJsonDispatchInfo(uint64_t qs layer, img_info->capture_id, aspect, + img_info->tiling, + img_info->type, qs_index, bcb_index); @@ -2560,6 +2608,8 @@ void DispatchTraceRaysDumpingContext::GenerateOutputJsonTraceRaysIndex(uint64_t mip, layer, aspect, + img_info->tiling, + img_info->type, false, qs_index, bcb_index, @@ -2663,6 +2713,8 @@ void DispatchTraceRaysDumpingContext::GenerateOutputJsonTraceRaysIndex(uint64_t mip, layer, aspect, + img_info->tiling, + img_info->type, false, qs_index, bcb_index, @@ -2781,6 +2833,8 @@ void DispatchTraceRaysDumpingContext::GenerateOutputJsonTraceRaysIndex(uint64_t layer, img_info->capture_id, aspect, + img_info->tiling, + img_info->type, qs_index, bcb_index); 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 c49bd51358..34f26a46c4 100644 --- a/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.h +++ b/framework/decode/vulkan_replay_dump_resources_compute_ray_tracing.h @@ -125,6 +125,8 @@ class DispatchTraceRaysDumpingContext uint32_t mip, uint32_t layer, VkImageAspectFlagBits aspect, + VkImageTiling tiling, + VkImageType type, bool is_dispatch, uint64_t qs_index, uint64_t bcb_index, @@ -150,6 +152,8 @@ class DispatchTraceRaysDumpingContext uint32_t layer, format::HandleId image_id, VkImageAspectFlagBits aspect, + VkImageTiling tiling, + VkImageType type, uint64_t bcb_index, uint64_t cmd_index) const; @@ -197,6 +201,7 @@ class DispatchTraceRaysDumpingContext bool output_json_per_command; bool dump_immutable_resources; bool dump_all_image_subresources; + bool dump_images_raw; // One entry per descriptor set for each compute and ray tracing binding points std::unordered_map bound_descriptor_sets_compute; diff --git a/framework/decode/vulkan_replay_dump_resources_draw_calls.cpp b/framework/decode/vulkan_replay_dump_resources_draw_calls.cpp index cedebc4ec7..4fb0e19f49 100644 --- a/framework/decode/vulkan_replay_dump_resources_draw_calls.cpp +++ b/framework/decode/vulkan_replay_dump_resources_draw_calls.cpp @@ -73,7 +73,7 @@ DrawCallsDumpingContext::DrawCallsDumpingContext(const std::vector& 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) + capture_filename(capture_filename), dump_images_raw(options.dump_resources_dump_raw_images) { must_backup_resources = (dc_indices.size() > 1); @@ -899,6 +899,8 @@ VkResult DrawCallsDumpingContext::DumpDrawCalls( std::string DrawCallsDumpingContext::GenerateRenderTargetImageFilename(VkFormat format, VkImageAspectFlagBits aspect, + VkImageTiling tiling, + VkImageType type, uint32_t mip_level, uint32_t layer, uint64_t cmd_buf_index, @@ -913,7 +915,21 @@ std::string DrawCallsDumpingContext::GenerateRenderTargetImageFilename(VkFormat std::stringstream filename; filename << capture_filename << "_"; - if (VkFormatToImageWriterDataFormat(format) != util::imagewriter::DataFormats::kFormat_UNSPECIFIED) + + const DeviceInfo* device_info = object_info_table.GetDeviceInfo(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) { @@ -945,7 +961,7 @@ std::string DrawCallsDumpingContext::GenerateRenderTargetImageFilename(VkFormat { std::stringstream subresource_sting; subresource_sting << "_mip_" << mip_level << "_layer_" << layer; - subresource_sting << ImageFileExtension(format, image_file_format); + subresource_sting << ImageFileExtension(output_image_format); std::filesystem::path filedirname(dump_resource_path); std::filesystem::path filebasename(filename.str() + subresource_sting.str()); @@ -953,7 +969,7 @@ std::string DrawCallsDumpingContext::GenerateRenderTargetImageFilename(VkFormat } else { - filename << ImageFileExtension(format, image_file_format); + filename << ImageFileExtension(output_image_format); std::filesystem::path filedirname(dump_resource_path); std::filesystem::path filebasename(filename.str()); @@ -1133,6 +1149,8 @@ void DrawCallsDumpingContext::GenerateOutputJsonDrawCallInfo( { filenameBefore = GenerateRenderTargetImageFilename(image_info->format, aspect, + image_info->tiling, + image_info->type, mip, layer, cmd_buf_index, @@ -1145,6 +1163,8 @@ void DrawCallsDumpingContext::GenerateOutputJsonDrawCallInfo( std::string filenameAfter = GenerateRenderTargetImageFilename(image_info->format, aspect, + image_info->tiling, + image_info->type, mip, layer, cmd_buf_index + dump_resources_before, @@ -1208,6 +1228,8 @@ void DrawCallsDumpingContext::GenerateOutputJsonDrawCallInfo( { filenameBefore = GenerateRenderTargetImageFilename(image_info->format, aspect, + image_info->tiling, + image_info->type, mip, layer, cmd_buf_index, @@ -1219,6 +1241,8 @@ void DrawCallsDumpingContext::GenerateOutputJsonDrawCallInfo( std::string filenameAfter = GenerateRenderTargetImageFilename(image_info->format, aspect, + image_info->tiling, + image_info->type, mip, layer, cmd_buf_index + dump_resources_before, @@ -1364,6 +1388,8 @@ void DrawCallsDumpingContext::GenerateOutputJsonDrawCallInfo( std::string filename = GenerateImageDescriptorFilename(image_info->format, aspect, + image_info->tiling, + image_info->type, image_info->capture_id, mip, layer, @@ -1651,8 +1677,17 @@ VkResult DrawCallsDumpingContext::DumpRenderTargetAttachments( { for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) { - filenames[f++] = GenerateRenderTargetImageFilename( - image_info->format, aspect, mip, layer, cmd_buf_index, qs_index, bcb_index, dc_index, i); + 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) { @@ -1679,6 +1714,7 @@ VkResult DrawCallsDumpingContext::DumpRenderTargetAttachments( scaling_supported, image_file_format, dump_all_image_subresources, + dump_images_raw, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &extent); @@ -1720,6 +1756,8 @@ VkResult DrawCallsDumpingContext::DumpRenderTargetAttachments( { filenames[f++] = GenerateRenderTargetImageFilename(image_info->format, aspect, + image_info->tiling, + image_info->type, mip, layer, cmd_buf_index, @@ -1753,6 +1791,7 @@ VkResult DrawCallsDumpingContext::DumpRenderTargetAttachments( scaling_supported, image_file_format, dump_all_image_subresources, + dump_images_raw, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, &extent); @@ -1777,6 +1816,8 @@ VkResult DrawCallsDumpingContext::DumpRenderTargetAttachments( std::string DrawCallsDumpingContext::GenerateImageDescriptorFilename(VkFormat format, VkImageAspectFlagBits aspect, + VkImageTiling tiling, + VkImageType type, format::HandleId image_id, uint32_t level, uint32_t layer, @@ -1788,9 +1829,20 @@ std::string DrawCallsDumpingContext::GenerateImageDescriptorFilename(VkFormat std::stringstream base_filename; base_filename << capture_filename << "_"; - const util::imagewriter::DataFormats output_format = VkFormatToImageWriterDataFormat(format); - if (output_format != util::imagewriter::DataFormats::kFormat_UNSPECIFIED && - output_format != util::imagewriter::DataFormats::kFormat_ASTC) + const DeviceInfo* device_info = object_info_table.GetDeviceInfo(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 && output_image_format != KFormatAstc) { base_filename << "image_" << image_id << "_qs_" << qs_index << "_bcb_" << bcb_index << "_rp_" << rp << "_aspect_" << aspect_str; @@ -1808,7 +1860,7 @@ std::string DrawCallsDumpingContext::GenerateImageDescriptorFilename(VkFormat { std::stringstream sub_resources_str; sub_resources_str << base_filename.str() << "_mip_" << level << "_layer_" << layer; - sub_resources_str << ImageFileExtension(format, image_file_format); + sub_resources_str << ImageFileExtension(output_image_format); std::filesystem::path filedirname(dump_resource_path); std::filesystem::path filebasename(sub_resources_str.str()); @@ -1816,7 +1868,7 @@ std::string DrawCallsDumpingContext::GenerateImageDescriptorFilename(VkFormat } else { - base_filename << ImageFileExtension(format, image_file_format); + base_filename << ImageFileExtension(output_image_format); std::filesystem::path filedirname(dump_resource_path); std::filesystem::path filebasename(base_filename.str()); return (filedirname / filebasename).string(); @@ -1993,8 +2045,16 @@ DrawCallsDumpingContext::DumpImmutableDescriptors(uint64_t qs_index, uint64_t bc { for (uint32_t layer = 0; layer < image_info->layer_count; ++layer) { - filenames[f++] = GenerateImageDescriptorFilename( - image_info->format, aspect, image_info->capture_id, mip, layer, qs_index, bcb_index, rp); + 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) { @@ -2019,7 +2079,8 @@ DrawCallsDumpingContext::DumpImmutableDescriptors(uint64_t qs_index, uint64_t bc dump_resources_scale, scaling_supported, image_file_format, - dump_all_image_subresources); + dump_all_image_subresources, + dump_images_raw); if (res != VK_SUCCESS) { GFXRECON_LOG_ERROR("Dumping image failed (%s)", util::ToString(res).c_str()) diff --git a/framework/decode/vulkan_replay_dump_resources_draw_calls.h b/framework/decode/vulkan_replay_dump_resources_draw_calls.h index 55bee07d22..6adbb87d05 100644 --- a/framework/decode/vulkan_replay_dump_resources_draw_calls.h +++ b/framework/decode/vulkan_replay_dump_resources_draw_calls.h @@ -192,6 +192,8 @@ class DrawCallsDumpingContext std::string GenerateRenderTargetImageFilename(VkFormat format, VkImageAspectFlagBits aspect, + VkImageTiling tiling, + VkImageType type, uint32_t mip_level, uint32_t layer, uint64_t cmd_buf_index, @@ -202,6 +204,8 @@ class DrawCallsDumpingContext std::string GenerateImageDescriptorFilename(VkFormat format, VkImageAspectFlagBits aspect, + VkImageTiling tiling, + VkImageType type, format::HandleId image_id, uint32_t level, uint32_t layer, @@ -268,6 +272,7 @@ class DrawCallsDumpingContext bool output_json_per_command; bool dump_immutable_resources; bool dump_all_image_subresources; + bool dump_images_raw; enum RenderPassType { diff --git a/framework/decode/vulkan_replay_dump_resources_json.cpp b/framework/decode/vulkan_replay_dump_resources_json.cpp index 40da6ddc0f..75b7499b42 100644 --- a/framework/decode/vulkan_replay_dump_resources_json.cpp +++ b/framework/decode/vulkan_replay_dump_resources_json.cpp @@ -48,6 +48,7 @@ VulkanReplayDumpResourcesJson::VulkanReplayDumpResourcesJson(const VulkanReplayO dr_options["dumpResourcesDumpVertexIndexBuffer"] = options.dump_resources_dump_vertex_index_buffer; dr_options["dumpResourcesDumpImmutableResources"] = options.dump_resources_dump_immutable_resources; dr_options["dumpResourcesDumpAllImageSubresources"] = options.dump_resources_dump_all_image_subresources; + dr_options["dumpResourcesDumpRawImages"] = options.dump_resources_dump_raw_images; }; bool VulkanReplayDumpResourcesJson::InitializeFile(const std::string& filename) diff --git a/framework/decode/vulkan_replay_options.h b/framework/decode/vulkan_replay_options.h index 93a281e0ab..7771a66d58 100644 --- a/framework/decode/vulkan_replay_options.h +++ b/framework/decode/vulkan_replay_options.h @@ -99,6 +99,7 @@ struct VulkanReplayOptions : public ReplayOptions bool dump_resources_json_per_command{ false }; bool dump_resources_dump_immutable_resources{ false }; bool dump_resources_dump_all_image_subresources{ false }; + bool dump_resources_dump_raw_images{ false }; bool preload_measurement_range{ false }; }; diff --git a/framework/graphics/vulkan_resources_util.cpp b/framework/graphics/vulkan_resources_util.cpp index 9840949d6e..0269588b20 100644 --- a/framework/graphics/vulkan_resources_util.cpp +++ b/framework/graphics/vulkan_resources_util.cpp @@ -1639,36 +1639,52 @@ VkResult VulkanResourcesUtil::ReadFromImageResourceStaging(VkImage std::vector& subresource_sizes, bool& scaling_supported, bool all_layers_per_level, - float scale) + float scale, + VkFormat dst_format) { VkResult result = VK_SUCCESS; VkImage resolve_image = VK_NULL_HANDLE; VkDeviceMemory resolve_memory = VK_NULL_HANDLE; VkImage scaled_image = VK_NULL_HANDLE; VkDeviceMemory scaled_image_mem = VK_NULL_HANDLE; - VkExtent3D scaled_extent = extent; VkQueue queue; uint64_t resource_size; VkImageAspectFlags transition_aspect; VkImage copy_image; + // No format conversion + if (dst_format == VK_FORMAT_UNDEFINED) + { + dst_format = format; + } + assert(mip_levels <= 1 + floor(log2(std::max(std::max(extent.width, extent.height), extent.depth)))); assert((aspect == VK_IMAGE_ASPECT_COLOR_BIT) || (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) || (aspect == VK_IMAGE_ASPECT_STENCIL_BIT)); - subresource_offsets.clear(); - subresource_sizes.clear(); + const bool is_blit_supported = IsBlitSupported(format, tiling, dst_format); + if (scale > 1.0f) + { + scaling_supported = IsScalingSupported(format, tiling, dst_format, type, extent, scale); + } + else + { + scaling_supported = (scale == 1.0f ? true : is_blit_supported); + } - scaled_extent.width = std::max(scaled_extent.width * scale, 1.0f); - scaled_extent.height = std::max(scaled_extent.height * scale, 1.0f); + const bool use_blit = (format != dst_format && is_blit_supported) || (scale != 1.0f && scaling_supported); - scaling_supported = - IsBlitSupported(format, tiling, format) && IsScalingSupported(format, tiling, format, type, extent, scale); + const VkExtent3D scaled_extent = { static_cast(std::max(extent.width * scale, 1.0f)), + static_cast(std::max(extent.height * scale, 1.0f)), + static_cast(std::max(extent.depth * scale, 1.0f)) }; + + subresource_offsets.clear(); + subresource_sizes.clear(); resource_size = GetImageResourceSizesOptimal(image, - format, + use_blit ? dst_format : format, type, - scaling_supported ? scaled_extent : extent, + use_blit ? scaled_extent : extent, mip_levels, array_layers, tiling, @@ -1738,11 +1754,12 @@ VkResult VulkanResourcesUtil::ReadFromImageResourceStaging(VkImage image, layout, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, transition_aspect, queue_family_index); } - // Blit image to change dimensions - if (scale != 1.0f) + // Blit image to change dimensions or convert format + if (use_blit) { result = BlitImage(copy_image, format, + dst_format, type, tiling, extent, @@ -1759,16 +1776,10 @@ VkResult VulkanResourcesUtil::ReadFromImageResourceStaging(VkImage { return result; } - - if (!scaling_supported) - { - scaled_image = copy_image; - } } else { - scaled_image = copy_image; - scaling_supported = true; + scaled_image = copy_image; } assert(scaled_image != VK_NULL_HANDLE); @@ -1776,7 +1787,7 @@ VkResult VulkanResourcesUtil::ReadFromImageResourceStaging(VkImage // Copy image to staging buffer CopyImageBuffer(scaled_image, staging_buffer_.buffer, - scaling_supported ? scaled_extent : extent, + use_blit ? scaled_extent : extent, mip_levels, array_layers, aspect, @@ -1838,7 +1849,7 @@ VkResult VulkanResourcesUtil::ReadFromImageResourceStaging(VkImage device_table_.FreeMemory(device_, resolve_memory, nullptr); } - if (scale != 1.0f && scaling_supported) + if (use_blit) { device_table_.DestroyImage(device_, scaled_image, nullptr); device_table_.FreeMemory(device_, scaled_image_mem, nullptr); @@ -2061,6 +2072,20 @@ bool VulkanResourcesUtil::IsBlitSupported(VkFormat src_format, VkFormat dst_format, VkImageTiling* dst_image_tiling) const { + // Integer formats must match + if ((vkuFormatIsSINT(src_format) != vkuFormatIsSINT(dst_format)) || + (vkuFormatIsUINT(src_format) != vkuFormatIsUINT(dst_format))) + { + return false; + } + + // Depth formats must be the same for src and destination images + if ((vkuFormatIsDepthOrStencil(src_format) != vkuFormatIsDepthOrStencil(dst_format)) || + (vkuFormatIsDepthOrStencil(src_format) && src_format != dst_format)) + { + return false; + } + VkFormatProperties src_format_props; instance_table_.GetPhysicalDeviceFormatProperties(physical_device_, src_format, &src_format_props); @@ -2130,6 +2155,7 @@ bool VulkanResourcesUtil::IsScalingSupported(VkFormat src_format, VkResult VulkanResourcesUtil::BlitImage(VkImage image, VkFormat format, + VkFormat dst_format, VkImageType type, VkImageTiling tiling, const VkExtent3D& extent, @@ -2146,30 +2172,19 @@ VkResult VulkanResourcesUtil::BlitImage(VkImage image, scaled_image_mem = VK_NULL_HANDLE; VkImageTiling dst_img_tiling; - bool scaling_supported = IsBlitSupported(format, tiling, format, &dst_img_tiling); - if (!scaling_supported) - { - GFXRECON_LOG_WARNING("Image with format %s cannot be scaled. Scaling will be disabled for these images.", - util::ToString(format).c_str()); - } + bool blit_supported = IsBlitSupported(format, tiling, dst_format, &dst_img_tiling); // In case of scalling an image up, check if the image resolution is supported by the implementation - if (scaling_supported && scale > 1.0f) + if (blit_supported && scale > 1.0f) { - scaling_supported = IsScalingSupported(format, tiling, format, type, extent, scale); - if (!scaling_supported) + blit_supported = IsScalingSupported(format, tiling, dst_format, type, extent, scale); + if (!blit_supported) { - GFXRECON_LOG_ERROR_ONCE("Scaled image is too large. Image dimensions (%u x %u) exceeds " - "implementation's limits for image formats of %s", - static_cast(extent.width * scale), - static_cast(extent.height * scale), - util::ToString(format).c_str()); - - scaling_supported = false; + blit_supported = false; } } - if (!scaling_supported) + if (!blit_supported) { return VK_SUCCESS; } @@ -2179,8 +2194,8 @@ VkResult VulkanResourcesUtil::BlitImage(VkImage image, create_info.pNext = nullptr; create_info.flags = 0; create_info.imageType = type; - create_info.format = format; - create_info.extent = scaled_extent; + create_info.format = dst_format; + create_info.extent = extent; create_info.mipLevels = mip_levels; create_info.arrayLayers = array_layers; create_info.samples = VK_SAMPLE_COUNT_1_BIT; @@ -2252,7 +2267,7 @@ VkResult VulkanResourcesUtil::BlitImage(VkImage image, img_barrier.subresourceRange = { aspectMask, 0, mip_levels, 0, array_layers }; device_table_.CmdPipelineBarrier(command_buffer_, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, @@ -2272,17 +2287,18 @@ VkResult VulkanResourcesUtil::BlitImage(VkImage image, blit_region.dstOffsets[0].z = 0; assert(mip_levels); + // assert(dst_img_mip_levels); std::vector blit_regions(mip_levels); for (uint32_t i = 0; i < mip_levels; ++i) { - blit_region.srcOffsets[1].x = (int32_t)extent.width >> i; - blit_region.srcOffsets[1].y = (int32_t)extent.height >> i; - blit_region.srcOffsets[1].z = (int32_t)extent.depth >> i; + blit_region.srcOffsets[1].x = std::max((int32_t)extent.width >> i, 1); + blit_region.srcOffsets[1].y = std::max((int32_t)extent.height >> i, 1); + blit_region.srcOffsets[1].z = std::max((int32_t)extent.depth >> i, 1); blit_region.srcSubresource = { aspectMask, i, 0, array_layers }; - blit_region.dstOffsets[1].x = (int32_t)scaled_extent.width >> i; - blit_region.dstOffsets[1].y = (int32_t)scaled_extent.height >> i; - blit_region.dstOffsets[1].z = (int32_t)scaled_extent.depth >> i; + blit_region.dstOffsets[1].x = std::max((int32_t)scaled_extent.width >> i, 1); + blit_region.dstOffsets[1].y = std::max((int32_t)scaled_extent.height >> i, 1); + blit_region.dstOffsets[1].z = std::max((int32_t)scaled_extent.depth >> i, 1); blit_region.dstSubresource = { aspectMask, i, 0, array_layers }; blit_regions[i] = blit_region; diff --git a/framework/graphics/vulkan_resources_util.h b/framework/graphics/vulkan_resources_util.h index bd9d82cf28..1aeec6bbca 100644 --- a/framework/graphics/vulkan_resources_util.h +++ b/framework/graphics/vulkan_resources_util.h @@ -116,7 +116,8 @@ class VulkanResourcesUtil std::vector& subresource_sizes, bool& scaling_supported, bool all_layers_per_level = false, - float scale = 1.0f); + float scale = 1.0f, + VkFormat dst_format = VK_FORMAT_UNDEFINED); // Use this function to dump an image sub resources into data vector. // This function is intented to be used when the image content can be accessed directly and expects to received a @@ -230,6 +231,7 @@ class VulkanResourcesUtil VkResult BlitImage(VkImage image, VkFormat format, + VkFormat dst_format, VkImageType type, VkImageTiling tiling, const VkExtent3D& extent, diff --git a/framework/util/image_writer.cpp b/framework/util/image_writer.cpp index 01020adc0e..dc0fd66e0b 100644 --- a/framework/util/image_writer.cpp +++ b/framework/util/image_writer.cpp @@ -85,136 +85,6 @@ const uint32_t kImageBppNoAlpha = 3; // Expecting 3 bytes per pixel for 32-b static std::unique_ptr temporary_buffer; static size_t temporary_buffer_size = 0; -// This function is a copy from Renderdoc sources -inline float ConvertFromHalf(uint16_t comp) -{ - bool sign = (comp & 0x8000) != 0; - int exponent = (comp & 0x7C00) >> 10; - int mantissa = comp & 0x03FF; - - if (exponent == 0x00) - { - if (mantissa == 0) - return sign ? -0.0f : 0.0f; - - // subnormal - float ret = (float)mantissa; - int* alias = (int*)&ret; - - // set sign bit and set exponent to 2^-24 - // (2^-14 from spec for subnormals * 2^-10 to convert (float)mantissa to 0.mantissa) - *alias = (sign ? 0x80000000 : 0) | (*alias - (24 << 23)); - - return ret; - } - else if (exponent < 0x1f) - { - exponent -= 15; - - float ret = 0.0f; - int* alias = (int*)&ret; - - // convert to float. Put sign bit in the right place, convert exponent to be - // [-128,127] and put in the right place, then shift mantissa up. - *alias = (sign ? 0x80000000 : 0) | (exponent + 127) << 23 | (mantissa << 13); - - return ret; - } - else // if(exponent = 0x1f) - { - union - { - int i; - float f; - } ret; - - if (mantissa == 0) - ret.i = (sign ? 0x80000000 : 0) | 0x7F800000; - else - ret.i = 0x7F800001; - - return ret.f; - } -} - -// This function is a copy from Renderdoc sources -static float Ufloat11ToFloat(uint16_t val) -{ - const uint32_t mantissa = val & 0x3f; - const uint32_t exponent = (val >> 6) & 0x1f; - static const uint32_t lead_bit = 0x40; - - if (mantissa == 0 && exponent == 0) - { - return 0.0f; - } - else - { - if (exponent == 0x1f) - { - if (mantissa == 0) - { - // +inf - return std::numeric_limits::max(); - } - else - { - // NaN... I don't think we want a Nan in a pixel - return 0.0f; - } - } - else if (exponent != 0) - { - uint32_t combined = lead_bit | mantissa; - return (static_cast(combined) / static_cast(lead_bit)) * - pow(2.0f, static_cast(exponent) - 15.0f); - } - else /* if (exponent == 0) */ - { - return static_cast(mantissa) / static_cast(lead_bit) * pow(2.0f, 1.0f - 15.0f); - } - } -} - -// This function is a copy from Renderdoc sources -static float Ufloat10ToFloat(uint16_t val) -{ - const uint32_t mantissa = val & 0x1f; - const uint32_t exponent = (val >> 5) & 0x1f; - static const uint32_t lead_bit = 0x20; - - if (mantissa == 0 && exponent == 0) - { - return 0.0f; - } - else - { - if (exponent == 0x1f) - { - if (mantissa == 0) - { - // +inf - return std::numeric_limits::max(); - } - else - { - // NaN... I don't think we want a Nan in a pixel - return 0.0f; - } - } - else if (exponent != 0) - { - uint32_t combined = lead_bit | mantissa; - return (static_cast(combined) / static_cast(lead_bit)) * - pow(2.0f, static_cast(exponent) - 15.0f); - } - else /* if (exponent == 0) */ - { - return static_cast(mantissa) / static_cast(lead_bit) * pow(2.0f, 1.0f - 15.0f); - } - } -} - #define CheckFwriteRetVal(_val_, _file_) \ { \ if (!_val_) \ @@ -256,69 +126,6 @@ static const uint8_t* ConvertIntoTemporaryBuffer(uint32_t width, switch (format) { - case kFormat_R8: - { - const uint8_t* bytes = reinterpret_cast(data); - - for (uint32_t y = 0; y < height; ++y) - { - for (uint32_t x = 0; x < width; ++x) - { - const uint8_t r = bytes[x]; - - *(temp_buffer++) = r; - *(temp_buffer++) = r; - *(temp_buffer++) = r; - - if (write_alpha) - { - *(temp_buffer++) = 0xff; - } - } - - bytes += data_pitch; - temp_buffer = reinterpret_cast(temporary_buffer.get()) + (y + 1) * output_pitch; - } - } - break; - - case kFormat_RGB: - { - const uint8_t* bytes = reinterpret_cast(data); - - for (uint32_t y = 0; y < height; ++y) - { - for (uint32_t x = 0; x < width; ++x) - { - const uint8_t r = bytes[(3 * x) + 0]; - const uint8_t g = bytes[(3 * x) + 1]; - const uint8_t b = bytes[(3 * x) + 2]; - - if (is_png) - { - *(temp_buffer++) = r; - *(temp_buffer++) = g; - *(temp_buffer++) = b; - } - else - { - *(temp_buffer++) = b; - *(temp_buffer++) = g; - *(temp_buffer++) = r; - } - - if (write_alpha) - { - *(temp_buffer++) = 0xff; - } - } - - bytes += data_pitch; - temp_buffer = reinterpret_cast(temporary_buffer.get()) + (y + 1) * output_pitch; - } - } - break; - case kFormat_RGBA: { const uint8_t* bytes = reinterpret_cast(data); @@ -432,140 +239,6 @@ static const uint8_t* ConvertIntoTemporaryBuffer(uint32_t width, } break; - case kFormat_B10G11R11_UFLOAT: - { - const uint32_t* u32_vals = reinterpret_cast(data); - - for (uint32_t y = 0; y < height; ++y) - { - for (uint32_t x = 0; x < width; ++x) - { - // clang-format off - const float b = Ufloat10ToFloat(static_cast((u32_vals[x] & (0xFFC00000)) >> 22)); - const float g = Ufloat11ToFloat(static_cast((u32_vals[x] & (0x003FF800)) >> 11)); - const float r = Ufloat11ToFloat(static_cast((u32_vals[x] & (0x000007FF)) >> 0)); - // clang-format on - - const uint8_t b_u8 = static_cast(std::min(b, 1.0f) * 255.0f); - const uint8_t g_u8 = static_cast(std::min(g, 1.0f) * 255.0f); - const uint8_t r_u8 = static_cast(std::min(r, 1.0f) * 255.0f); - - if (is_png) - { - *(temp_buffer++) = r_u8; - *(temp_buffer++) = g_u8; - *(temp_buffer++) = b_u8; - } - else - { - *(temp_buffer++) = b_u8; - *(temp_buffer++) = g_u8; - *(temp_buffer++) = r_u8; - } - - if (write_alpha) - { - *(temp_buffer++) = 0xff; - } - } - - u32_vals = reinterpret_cast(reinterpret_cast(u32_vals) + data_pitch); - temp_buffer = reinterpret_cast(temporary_buffer.get()) + (y + 1) * output_pitch; - } - } - break; - - case kFormat_A2B10G10R10: - { - const uint32_t* u32_vals = reinterpret_cast(data); - - for (uint32_t y = 0; y < height; ++y) - { - for (uint32_t x = 0; x < width; ++x) - { - uint8_t a = static_cast((u32_vals[x] & 0xC0000000) >> 30); - uint8_t b = static_cast((u32_vals[x] & 0x3FF00000) >> 20); - uint8_t g = static_cast((u32_vals[x] & 0x000FFC00) >> 10); - uint8_t r = static_cast((u32_vals[x] & 0x000003FF) >> 0); - - r = static_cast(static_cast(r) / 1023.0f * 255.0f); - g = static_cast(static_cast(g) / 1023.0f * 255.0f); - b = static_cast(static_cast(b) / 1023.0f * 255.0f); - a = static_cast(static_cast(a) / 3.0f * 255.0f); - - if (is_png) - { - *(temp_buffer++) = r; - *(temp_buffer++) = g; - *(temp_buffer++) = b; - } - else - { - *(temp_buffer++) = b; - *(temp_buffer++) = g; - *(temp_buffer++) = r; - } - - if (write_alpha) - { - *(temp_buffer++) = a; - } - } - - u32_vals = reinterpret_cast(reinterpret_cast(u32_vals) + data_pitch); - temp_buffer = reinterpret_cast(temporary_buffer.get()) + (y + 1) * output_pitch; - } - } - break; - - case kFormat_R16G16B16A16_SFLOAT: - { - const uint64_t* u64_vals = reinterpret_cast(data); - - for (uint32_t y = 0; y < height; ++y) - { - for (uint32_t x = 0; x < width; ++x) - { - uint16_t a_u16 = static_cast((u64_vals[x] & 0xFFFF000000000000ULL) >> 48); - uint16_t b_u16 = static_cast((u64_vals[x] & 0x0000FFFF00000000ULL) >> 32); - uint16_t g_u16 = static_cast((u64_vals[x] & 0x00000000FFFF0000ULL) >> 16); - uint16_t r_u16 = static_cast((u64_vals[x] & 0x000000000000FFFFULL) >> 0); - - float r_f = ConvertFromHalf(r_u16); - float g_f = ConvertFromHalf(g_u16); - float b_f = ConvertFromHalf(b_u16); - float a_f = ConvertFromHalf(a_u16); - - uint8_t r = static_cast(r_f * 255.0f); - uint8_t g = static_cast(g_f * 255.0f); - uint8_t b = static_cast(b_f * 255.0f); - uint8_t a = static_cast(a_f * 255.0f); - - if (is_png) - { - *(temp_buffer++) = r; - *(temp_buffer++) = g; - *(temp_buffer++) = b; - } - else - { - *(temp_buffer++) = b; - *(temp_buffer++) = g; - *(temp_buffer++) = r; - } - - if (write_alpha) - { - *(temp_buffer++) = a; - } - } - - u64_vals = reinterpret_cast(reinterpret_cast(u64_vals) + data_pitch); - temp_buffer = reinterpret_cast(temporary_buffer.get()) + (y + 1) * output_pitch; - } - } - break; - case kFormat_D32_FLOAT: { const float* floats = reinterpret_cast(data); diff --git a/framework/util/image_writer.h b/framework/util/image_writer.h index e704ec47c8..b6470829af 100644 --- a/framework/util/image_writer.h +++ b/framework/util/image_writer.h @@ -67,14 +67,10 @@ struct BmpInfoHeader enum DataFormats { kFormat_UNSPECIFIED = 0, - kFormat_R8, kFormat_RGB, kFormat_RGBA, kFormat_BGR, - kFormat_R16G16B16A16_SFLOAT, - kFormat_B10G11R11_UFLOAT, kFormat_BGRA, - kFormat_A2B10G10R10, kFormat_D32_FLOAT, kFormat_D24_UNORM, kFormat_D16_UNORM, @@ -85,9 +81,6 @@ constexpr size_t DataFormatsSizes(DataFormats format) { switch (format) { - case kFormat_R8: - return 1; - case kFormat_D16_UNORM: return 2; @@ -99,13 +92,8 @@ constexpr size_t DataFormatsSizes(DataFormats format) case kFormat_RGBA: case kFormat_BGRA: case kFormat_D32_FLOAT: - case kFormat_B10G11R11_UFLOAT: - case kFormat_A2B10G10R10: return 4; - case kFormat_R16G16B16A16_SFLOAT: - return 8; - case kFormat_ASTC: GFXRECON_LOG_WARNING("%s(): Cannot calculate element size for ASTC.", __func__); return 0; diff --git a/tools/replay/replay_settings.h b/tools/replay/replay_settings.h index aa40615c48..96bf18bd3f 100644 --- a/tools/replay/replay_settings.h +++ b/tools/replay/replay_settings.h @@ -35,7 +35,8 @@ const char kOptions[] = "offscreen-swapchain-frame-boundary,--wait-before-present,--dump-resources-before-draw," "--dump-resources-dump-depth-attachment,--dump-" "resources-dump-vertex-index-buffers,--dump-resources-json-output-per-command,--dump-resources-dump-immutable-" - "resources,--dump-resources-dump-all-image-subresources,--pbi-all,--preload-measurement-range"; + "resources,--dump-resources-dump-all-image-subresources,--dump-resources-dump-raw-images,--pbi-all,--" + "preload-measurement-range"; const char kArguments[] = "--log-level,--log-file,--gpu,--gpu-group,--pause-frame,--wsi,--surface-index,-m|--memory-translation," "--replace-shaders,--screenshots,--denied-messages,--allowed-messages,--screenshot-format,--" diff --git a/tools/tool_settings.h b/tools/tool_settings.h index 82111cf0b1..f459f8362a 100644 --- a/tools/tool_settings.h +++ b/tools/tool_settings.h @@ -141,6 +141,7 @@ const char kDumpResourcesDumpVertexIndexBuffers[] = "--dump-resources-dump-verte const char kDumpResourcesJsonPerCommand[] = "--dump-resources-json-output-per-command"; const char kDumpResourcesDumpImmutableResources[] = "--dump-resources-dump-immutable-resources"; const char kDumpResourcesDumpImageSubresources[] = "--dump-resources-dump-all-image-subresources"; +const char kDumpResourcesDumpRawImages[] = "--dump-resources-dump-raw-images"; enum class WsiPlatform { @@ -1098,6 +1099,7 @@ GetVulkanReplayOptions(const gfxrecon::util::ArgumentParser& arg_parse arg_parser.IsOptionSet(kDumpResourcesDumpImmutableResources); replay_options.dump_resources_dump_all_image_subresources = arg_parser.IsOptionSet(kDumpResourcesDumpImageSubresources); + replay_options.dump_resources_dump_raw_images = arg_parser.IsOptionSet(kDumpResourcesDumpRawImages); std::string dr_color_att_idx = arg_parser.GetArgumentValue(kDumpResourcesColorAttIdxArg); if (!dr_color_att_idx.empty())