Skip to content

Commit

Permalink
Vulkan dump resources: Convert images with blit
Browse files Browse the repository at this point in the history
  • Loading branch information
panos-lunarg committed Oct 22, 2024
1 parent 8c33488 commit f72c5c6
Show file tree
Hide file tree
Showing 17 changed files with 381 additions and 469 deletions.
3 changes: 3 additions & 0 deletions USAGE_android.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <index1,index2>]
[file]
Expand Down Expand Up @@ -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 <index1,index2>
Expand Down
7 changes: 5 additions & 2 deletions USAGE_desktop_Vulkan.md
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ gfxrecon-replay [-h | --help] [--version] [--gpu <index>]
[--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] <file>
[--pbi-all] [--pbis <index1,index2>]
[--pipeline-creation-jobs | --pcj <num_jobs>]
Expand Down Expand Up @@ -758,15 +759,17 @@ 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 <index1,index2>
Print block information between block index1 and block index2.
--pipeline-creation-jobs | --pcj <num_jobs>
Specify the number of asynchronous pipeline-creation jobs as integer.
If <num_jobs> 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
Expand Down
4 changes: 4 additions & 0 deletions android/scripts/gfxrecon.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.')
Expand Down Expand Up @@ -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')

Expand Down
174 changes: 125 additions & 49 deletions framework/decode/vulkan_replay_dump_resources_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Expand All @@ -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;

Expand All @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -448,6 +445,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info,
std::vector<bool>& scaling_supported,
util::ScreenshotFormat image_file_format,
bool dump_all_subresources,
bool dump_image_raw,
VkImageLayout layout,
const VkExtent3D* extent_p)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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());
Expand All @@ -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)
{
Expand All @@ -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)
Expand All @@ -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);

Expand All @@ -560,26 +572,26 @@ 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,
scaled_extent.height,
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,
scaled_extent.height,
subresource_sizes[0],
data.data(),
stride,
output_image_format,
image_writer_format,
vkuFormatHasAlpha(image_info->format));
}
}
Expand Down Expand Up @@ -607,7 +619,7 @@ VkResult DumpImageToFile(const ImageInfo* image_info,
const void* data_offset = reinterpret_cast<const void*>(
reinterpret_cast<const uint8_t*>(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)
Expand All @@ -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);

Expand All @@ -642,25 +654,25 @@ 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,
scaled_extent.height,
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,
scaled_extent.height,
subresource_sizes[sub_res_idx],
data_offset,
stride,
output_image_format);
image_writer_format);
}
}
else
Expand Down Expand Up @@ -854,5 +866,69 @@ void GetFormatAspects(VkFormat format, std::vector<VkImageAspectFlagBits>& 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)
Loading

0 comments on commit f72c5c6

Please sign in to comment.