From af377ba1b5a6ef4ff6852903f063cf241941e51d Mon Sep 17 00:00:00 2001 From: Panagiotis Apostolou Date: Sun, 13 Aug 2023 12:18:29 +0300 Subject: [PATCH] Screenshot size during replay is now configurable Use --screenshot-size x at replay in order to set the size of the generated screenshot files --- android/scripts/gfxrecon.py | 5 +++ framework/decode/screenshot_handler.cpp | 45 ++++++++++++++----- framework/decode/screenshot_handler.h | 6 ++- .../decode/vulkan_replay_consumer_base.cpp | 4 +- framework/decode/vulkan_replay_options.h | 1 + tools/replay/replay_settings.h | 3 +- tools/tool_settings.h | 32 +++++++++++++ 7 files changed, 81 insertions(+), 15 deletions(-) diff --git a/android/scripts/gfxrecon.py b/android/scripts/gfxrecon.py index f74a602066..6f9e82a7d8 100755 --- a/android/scripts/gfxrecon.py +++ b/android/scripts/gfxrecon.py @@ -75,6 +75,7 @@ def CreateReplayParser(): parser.add_argument('--screenshot-format', metavar='FORMAT', choices=['bmp', 'png'], help='Image file format to use for screenshot generation. Available formats are: bmp, png (forwarded to replay tool)') parser.add_argument('--screenshot-dir', metavar='DIR', help='Directory to write screenshots. Default is "/sdcard" (forwarded to replay tool)') parser.add_argument('--screenshot-prefix', metavar='PREFIX', help='Prefix to apply to the screenshot file name. Default is "screenshot" (forwarded to replay tool)') + parser.add_argument('--screenshot-size', metavar='SIZE', help='Screenshot dimensions. Expected format is x.') parser.add_argument('--sfa', '--skip-failed-allocations', action='store_true', default=False, help='Skip vkAllocateMemory, vkAllocateCommandBuffers, and vkAllocateDescriptorSets calls that failed during capture (forwarded to replay tool)') parser.add_argument('--opcd', '--omit-pipeline-cache-data', action='store_true', default=False, help='Omit pipeline cache data from calls to vkCreatePipelineCache and skip calls to vkGetPipelineCacheData (forwarded to replay tool)') parser.add_argument('--surface-index', metavar='N', help='Restrict rendering to the Nth surface object created. Used with captures that include multiple surfaces. Default is -1 (render to all surfaces; forwarded to replay tool)') @@ -127,6 +128,10 @@ def MakeExtrasString(args): arg_list.append('--screenshot-prefix') arg_list.append('{}'.format(args.screenshot_prefix)) + if args.screenshot_size: + arg_list.append('--screenshot-size') + arg_list.append('{}'.format(args.screenshot_size)) + if args.sfa: arg_list.append('--sfa') diff --git a/framework/decode/screenshot_handler.cpp b/framework/decode/screenshot_handler.cpp index f9465453a2..089d3e06a1 100644 --- a/framework/decode/screenshot_handler.cpp +++ b/framework/decode/screenshot_handler.cpp @@ -82,7 +82,9 @@ void ScreenshotHandler::WriteImage(const std::string& filen VkImage image, VkFormat format, uint32_t width, - uint32_t height) + uint32_t height, + uint32_t copy_width, + uint32_t copy_height) { if ((device_table == nullptr) || (allocator == nullptr)) { @@ -90,6 +92,16 @@ void ScreenshotHandler::WriteImage(const std::string& filen return; } + if (copy_width == 0) + { + copy_width = width; + } + + if (copy_height == 0) + { + copy_height = height; + } + VkResult result = VK_SUCCESS; // TODO: Improved queue selection; ensure queue supports transfer operations. @@ -131,10 +143,10 @@ void ScreenshotHandler::WriteImage(const std::string& filen bool create_resource = false; // If the copy resource is not initialized, or the image properties have changed, recompute the copy size. - if ((buffer_size == 0) || (copy_resource.width != width) || (copy_resource.height != height) || + if ((buffer_size == 0) || (copy_resource.width != copy_width) || (copy_resource.height != copy_height) || (copy_resource.format != copy_format)) { - buffer_size = GetCopyBufferSize(device, device_table, copy_format, width, height); + buffer_size = GetCopyBufferSize(device, device_table, copy_format, copy_width, copy_height); create_resource = true; } @@ -151,6 +163,8 @@ void ScreenshotHandler::WriteImage(const std::string& filen copy_format, width, height, + copy_width, + copy_height, ©_resource); } else if (buffer_size == 0) @@ -262,8 +276,8 @@ void ScreenshotHandler::WriteImage(const std::string& filen blit_region.dstOffsets[0].x = 0; blit_region.dstOffsets[0].y = 0; blit_region.dstOffsets[0].z = 0; - blit_region.dstOffsets[1].x = width; - blit_region.dstOffsets[1].y = height; + blit_region.dstOffsets[1].x = copy_width; + blit_region.dstOffsets[1].y = copy_height; blit_region.dstOffsets[1].z = 1; device_table->CmdBlitImage(command_buffer, @@ -303,7 +317,7 @@ void ScreenshotHandler::WriteImage(const std::string& filen copy_region.imageSubresource.baseArrayLayer = 0; copy_region.imageSubresource.layerCount = 1; copy_region.imageOffset = { 0, 0, 0 }; - copy_region.imageExtent = { width, height, 1 }; + copy_region.imageExtent = { copy_width, copy_height, 1 }; device_table->CmdCopyImageToBuffer(command_buffer, copy_image, @@ -377,8 +391,12 @@ void ScreenshotHandler::WriteImage(const std::string& filen 1, &invalidate_range, ©_resource.buffer_memory_data); } - WriteImageFile( - filename_prefix, screenshot_format_, width, height, copy_resource.buffer_size, data); + WriteImageFile(filename_prefix, + screenshot_format_, + copy_width, + copy_height, + copy_resource.buffer_size, + data); allocator->UnmapResourceMemoryDirect(copy_resource.buffer_data); } @@ -534,6 +552,8 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice VkFormat screenshot_format, uint32_t width, uint32_t height, + uint32_t copy_width, + uint32_t copy_height, CopyResource* copy_resource) const { assert(device_table != nullptr); @@ -597,7 +617,8 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice ©_resource->memory_property_flags); } - if ((result == VK_SUCCESS) && (image_format != screenshot_format)) + if ((result == VK_SUCCESS) && + ((image_format != screenshot_format) || (width != copy_width) || height != copy_height)) { // The source image format does not match the image file format and requires a format conversion. Create an // image to serve as the tranfer destination of a blit based color conversion. @@ -606,7 +627,7 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice image_create_info.flags = 0; image_create_info.imageType = VK_IMAGE_TYPE_2D; image_create_info.format = screenshot_format; - image_create_info.extent = { width, height, 1 }; + image_create_info.extent = { copy_width, copy_height, 1 }; image_create_info.mipLevels = 1; image_create_info.arrayLayers = 1; image_create_info.samples = VK_SAMPLE_COUNT_1_BIT; @@ -659,8 +680,8 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice // Resource creation succeeded. copy_resource->buffer_size = buffer_size; copy_resource->format = screenshot_format; - copy_resource->width = width; - copy_resource->height = height; + copy_resource->width = copy_width; + copy_resource->height = copy_height; } else { diff --git a/framework/decode/screenshot_handler.h b/framework/decode/screenshot_handler.h index e86b11af25..65f28b61db 100644 --- a/framework/decode/screenshot_handler.h +++ b/framework/decode/screenshot_handler.h @@ -59,7 +59,9 @@ class ScreenshotHandler : public ScreenshotHandlerBase VkImage image, VkFormat format, uint32_t width, - uint32_t height); + uint32_t height, + uint32_t copy_width, + uint32_t copy_height); void DestroyDeviceResources(VkDevice device, const encode::DeviceTable* device_table); @@ -108,6 +110,8 @@ class ScreenshotHandler : public ScreenshotHandlerBase VkFormat screenshot_format, uint32_t width, uint32_t height, + uint32_t copy_width, + uint32_t copy_height, CopyResource* copy_resource) const; void DestroyCopyResource(VkDevice device, CopyResource* copy_resource) const; diff --git a/framework/decode/vulkan_replay_consumer_base.cpp b/framework/decode/vulkan_replay_consumer_base.cpp index 27db8c7a43..76d260d607 100644 --- a/framework/decode/vulkan_replay_consumer_base.cpp +++ b/framework/decode/vulkan_replay_consumer_base.cpp @@ -2150,7 +2150,9 @@ void VulkanReplayConsumerBase::WriteScreenshots(const Decoded_VkPresentInfoKHR* swapchain_info->images[image_index], swapchain_info->format, swapchain_info->width, - swapchain_info->height); + swapchain_info->height, + options_.screenshot_width, + options_.screenshot_height); } } } diff --git a/framework/decode/vulkan_replay_options.h b/framework/decode/vulkan_replay_options.h index 3945ae978a..b60675f95a 100644 --- a/framework/decode/vulkan_replay_options.h +++ b/framework/decode/vulkan_replay_options.h @@ -55,6 +55,7 @@ struct VulkanReplayOptions : public ReplayOptions std::vector screenshot_ranges; std::string screenshot_dir; std::string screenshot_file_prefix{ kDefaultScreenshotFilePrefix }; + uint32_t screenshot_width, screenshot_height; std::string replace_dir; }; diff --git a/tools/replay/replay_settings.h b/tools/replay/replay_settings.h index 1560e0a6cf..6c8491ade7 100644 --- a/tools/replay/replay_settings.h +++ b/tools/replay/replay_settings.h @@ -35,7 +35,7 @@ const char kOptions[] = 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,--" - "screenshot-dir,--screenshot-prefix,--mfr|--measurement-frame-range,--fw|--force-windowed"; + "screenshot-dir,--screenshot-prefix,--screenshot-size,--mfr|--measurement-frame-range,--fw|--force-windowed"; static void PrintUsage(const char* exe_name) { @@ -53,6 +53,7 @@ static void PrintUsage(const char* exe_name) GFXRECON_WRITE_CONSOLE("\t\t\t[--pause-frame ] [--paused] [--sync] [--screenshot-all]"); GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshots ] [--screenshot-format ]"); GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshot-dir ] [--screenshot-prefix ]"); + GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshot-size x]"); GFXRECON_WRITE_CONSOLE("\t\t\t[--sfa | --skip-failed-allocations] [--replace-shaders ]"); GFXRECON_WRITE_CONSOLE("\t\t\t[--opcd | --omit-pipeline-cache-data] [--wsi ]"); GFXRECON_WRITE_CONSOLE("\t\t\t[--use-cached-psos] [--surface-index ]"); diff --git a/tools/tool_settings.h b/tools/tool_settings.h index b591b386e9..ceada7f699 100644 --- a/tools/tool_settings.h +++ b/tools/tool_settings.h @@ -94,6 +94,7 @@ const char kScreenshotRangeArgument[] = "--screenshots"; const char kScreenshotFormatArgument[] = "--screenshot-format"; const char kScreenshotDirArgument[] = "--screenshot-dir"; const char kScreenshotFilePrefixArgument[] = "--screenshot-prefix"; +const char kScreenshotSizeArgument[] = "--screenshot-size"; const char kForceWindowedShortArgument[] = "--fw"; const char kForceWindowedLongArgument[] = "--force-windowed"; const char kOutput[] = "--output"; @@ -464,6 +465,36 @@ static std::string GetScreenshotDir(const gfxrecon::util::ArgumentParser& arg_pa return kDefaultScreenshotDir; } +static void GetScreenshotSize(const gfxrecon::util::ArgumentParser& arg_parser, uint32_t& width, uint32_t& height) +{ + const auto& value = arg_parser.GetArgumentValue(kScreenshotSizeArgument); + + if (!value.empty()) + { + std::size_t x = value.find("x"); + if (x != std::string::npos) + { + try + { + width = std::stoul(value.substr(0, x)); + height = std::stoul(value.substr(x + 1)); + } + catch (std::exception& e) + { + width = height = 0; + } + } + else + { + width = height = 0; + } + } + else + { + width = height = 0; + } +} + static std::vector GetScreenshotRanges(const gfxrecon::util::ArgumentParser& arg_parser) { @@ -770,6 +801,7 @@ GetVulkanReplayOptions(const gfxrecon::util::ArgumentParser& arg_parse replay_options.screenshot_format = GetScreenshotFormat(arg_parser); replay_options.screenshot_dir = GetScreenshotDir(arg_parser); replay_options.screenshot_file_prefix = arg_parser.GetArgumentValue(kScreenshotFilePrefixArgument); + GetScreenshotSize(arg_parser, replay_options.screenshot_width, replay_options.screenshot_height); if (arg_parser.IsOptionSet(kQuitAfterMeasurementRangeOption)) { replay_options.quit_after_measurement_frame_range = true;