Skip to content

Commit 74cbcc4

Browse files
committed
Screenshot size during replay is now configurable
Adds two new replay options that controls the screenshot dimensions: --screenshot-size <width>x<height> explicitly sets the dimensions of the generated screenshot --screenshot-scale <number> Scales the swapchain images by that number. Number can be decimal
1 parent 7a7d18d commit 74cbcc4

7 files changed

Lines changed: 117 additions & 15 deletions

File tree

android/scripts/gfxrecon.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ def CreateReplayParser():
7575
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)')
7676
parser.add_argument('--screenshot-dir', metavar='DIR', help='Directory to write screenshots. Default is "/sdcard" (forwarded to replay tool)')
7777
parser.add_argument('--screenshot-prefix', metavar='PREFIX', help='Prefix to apply to the screenshot file name. Default is "screenshot" (forwarded to replay tool)')
78+
parser.add_argument('--screenshot-size', metavar='SIZE', help='Screenshot dimensions. Ignored if --screenshot-scale is specified. Expected format is <width>x<height>.')
79+
parser.add_argument('--screenshot-scale', metavar='SCALE', help='Scale screenshot dimensions. Overrides --screenshot-size, if specified. Expects a number which can be decimal')
7880
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)')
7981
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)')
8082
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 +129,14 @@ def MakeExtrasString(args):
127129
arg_list.append('--screenshot-prefix')
128130
arg_list.append('{}'.format(args.screenshot_prefix))
129131

132+
if args.screenshot_size:
133+
arg_list.append('--screenshot-size')
134+
arg_list.append('{}'.format(args.screenshot_size))
135+
136+
if args.screenshot_scale:
137+
arg_list.append('--screenshot-scale')
138+
arg_list.append('{}'.format(args.screenshot_scale))
139+
130140
if args.sfa:
131141
arg_list.append('--sfa')
132142

framework/decode/screenshot_handler.cpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ void ScreenshotHandler::WriteImage(const std::string& filen
8282
VkImage image,
8383
VkFormat format,
8484
uint32_t width,
85-
uint32_t height)
85+
uint32_t height,
86+
uint32_t copy_width,
87+
uint32_t copy_height)
8688
{
8789
if ((device_table == nullptr) || (allocator == nullptr))
8890
{
@@ -131,10 +133,10 @@ void ScreenshotHandler::WriteImage(const std::string& filen
131133
bool create_resource = false;
132134

133135
// If the copy resource is not initialized, or the image properties have changed, recompute the copy size.
134-
if ((buffer_size == 0) || (copy_resource.width != width) || (copy_resource.height != height) ||
136+
if ((buffer_size == 0) || (copy_resource.width != copy_width) || (copy_resource.height != copy_height) ||
135137
(copy_resource.format != copy_format))
136138
{
137-
buffer_size = GetCopyBufferSize(device, device_table, copy_format, width, height);
139+
buffer_size = GetCopyBufferSize(device, device_table, copy_format, copy_width, copy_height);
138140
create_resource = true;
139141
}
140142

@@ -151,6 +153,8 @@ void ScreenshotHandler::WriteImage(const std::string& filen
151153
copy_format,
152154
width,
153155
height,
156+
copy_width,
157+
copy_height,
154158
&copy_resource);
155159
}
156160
else if (buffer_size == 0)
@@ -262,8 +266,8 @@ void ScreenshotHandler::WriteImage(const std::string& filen
262266
blit_region.dstOffsets[0].x = 0;
263267
blit_region.dstOffsets[0].y = 0;
264268
blit_region.dstOffsets[0].z = 0;
265-
blit_region.dstOffsets[1].x = width;
266-
blit_region.dstOffsets[1].y = height;
269+
blit_region.dstOffsets[1].x = copy_width;
270+
blit_region.dstOffsets[1].y = copy_height;
267271
blit_region.dstOffsets[1].z = 1;
268272

269273
device_table->CmdBlitImage(command_buffer,
@@ -303,7 +307,7 @@ void ScreenshotHandler::WriteImage(const std::string& filen
303307
copy_region.imageSubresource.baseArrayLayer = 0;
304308
copy_region.imageSubresource.layerCount = 1;
305309
copy_region.imageOffset = { 0, 0, 0 };
306-
copy_region.imageExtent = { width, height, 1 };
310+
copy_region.imageExtent = { copy_width, copy_height, 1 };
307311

308312
device_table->CmdCopyImageToBuffer(command_buffer,
309313
copy_image,
@@ -377,8 +381,12 @@ void ScreenshotHandler::WriteImage(const std::string& filen
377381
1, &invalidate_range, &copy_resource.buffer_memory_data);
378382
}
379383

380-
WriteImageFile(
381-
filename_prefix, screenshot_format_, width, height, copy_resource.buffer_size, data);
384+
WriteImageFile(filename_prefix,
385+
screenshot_format_,
386+
copy_width,
387+
copy_height,
388+
copy_resource.buffer_size,
389+
data);
382390

383391
allocator->UnmapResourceMemoryDirect(copy_resource.buffer_data);
384392
}
@@ -534,6 +542,8 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice
534542
VkFormat screenshot_format,
535543
uint32_t width,
536544
uint32_t height,
545+
uint32_t copy_width,
546+
uint32_t copy_height,
537547
CopyResource* copy_resource) const
538548
{
539549
assert(device_table != nullptr);
@@ -597,7 +607,8 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice
597607
&copy_resource->memory_property_flags);
598608
}
599609

600-
if ((result == VK_SUCCESS) && (image_format != screenshot_format))
610+
if ((result == VK_SUCCESS) &&
611+
((image_format != screenshot_format) || (width != copy_width) || (height != copy_height)))
601612
{
602613
// The source image format does not match the image file format and requires a format conversion. Create an
603614
// image to serve as the tranfer destination of a blit based color conversion.
@@ -606,7 +617,7 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice
606617
image_create_info.flags = 0;
607618
image_create_info.imageType = VK_IMAGE_TYPE_2D;
608619
image_create_info.format = screenshot_format;
609-
image_create_info.extent = { width, height, 1 };
620+
image_create_info.extent = { copy_width, copy_height, 1 };
610621
image_create_info.mipLevels = 1;
611622
image_create_info.arrayLayers = 1;
612623
image_create_info.samples = VK_SAMPLE_COUNT_1_BIT;
@@ -659,8 +670,8 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice
659670
// Resource creation succeeded.
660671
copy_resource->buffer_size = buffer_size;
661672
copy_resource->format = screenshot_format;
662-
copy_resource->width = width;
663-
copy_resource->height = height;
673+
copy_resource->width = copy_width;
674+
copy_resource->height = copy_height;
664675
}
665676
else
666677
{

framework/decode/screenshot_handler.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ class ScreenshotHandler : public ScreenshotHandlerBase
5959
VkImage image,
6060
VkFormat format,
6161
uint32_t width,
62-
uint32_t height);
62+
uint32_t height,
63+
uint32_t copy_width,
64+
uint32_t copy_height);
6365

6466
void DestroyDeviceResources(VkDevice device, const encode::DeviceTable* device_table);
6567

@@ -108,6 +110,8 @@ class ScreenshotHandler : public ScreenshotHandlerBase
108110
VkFormat screenshot_format,
109111
uint32_t width,
110112
uint32_t height,
113+
uint32_t copy_width,
114+
uint32_t copy_height,
111115
CopyResource* copy_resource) const;
112116

113117
void DestroyCopyResource(VkDevice device, CopyResource* copy_resource) const;

framework/decode/vulkan_replay_consumer_base.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2142,6 +2142,17 @@ void VulkanReplayConsumerBase::WriteScreenshots(const Decoded_VkPresentInfoKHR*
21422142
filename_prefix += "_frame_";
21432143
filename_prefix += std::to_string(screenshot_handler_->GetCurrentFrame());
21442144

2145+
// If both copy_scale and copy_width are provided, use copy_scale.
2146+
const uint32_t screenshot_width =
2147+
options_.screenshot_scale
2148+
? (options_.screenshot_scale * swapchain_info->width)
2149+
: (options_.screenshot_width ? options_.screenshot_width : swapchain_info->width);
2150+
2151+
const uint32_t screenshot_height =
2152+
options_.screenshot_scale
2153+
? (options_.screenshot_scale * swapchain_info->height)
2154+
: (options_.screenshot_height ? options_.screenshot_height : swapchain_info->height);
2155+
21452156
screenshot_handler_->WriteImage(filename_prefix,
21462157
device_info->handle,
21472158
GetDeviceTable(device_info->handle),
@@ -2150,7 +2161,9 @@ void VulkanReplayConsumerBase::WriteScreenshots(const Decoded_VkPresentInfoKHR*
21502161
swapchain_info->images[image_index],
21512162
swapchain_info->format,
21522163
swapchain_info->width,
2153-
swapchain_info->height);
2164+
swapchain_info->height,
2165+
screenshot_width,
2166+
screenshot_height);
21542167
}
21552168
}
21562169
}

framework/decode/vulkan_replay_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ struct VulkanReplayOptions : public ReplayOptions
5555
std::vector<ScreenshotRange> screenshot_ranges;
5656
std::string screenshot_dir;
5757
std::string screenshot_file_prefix{ kDefaultScreenshotFilePrefix };
58+
uint32_t screenshot_width, screenshot_height;
59+
float screenshot_scale;
5860
std::string replace_dir;
5961
};
6062

tools/replay/replay_settings.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ const char kOptions[] =
3535
const char kArguments[] =
3636
"--log-level,--log-file,--gpu,--gpu-group,--pause-frame,--wsi,--surface-index,-m|--memory-translation,"
3737
"--replace-shaders,--screenshots,--denied-messages,--allowed-messages,--screenshot-format,--"
38-
"screenshot-dir,--screenshot-prefix,--mfr|--measurement-frame-range,--fw|--force-windowed";
38+
"screenshot-dir,--screenshot-prefix,--screenshot-size,--screenshot-scale,--mfr|--measurement-frame-range,--fw|--"
39+
"force-windowed";
3940

4041
static void PrintUsage(const char* exe_name)
4142
{
@@ -53,6 +54,8 @@ static void PrintUsage(const char* exe_name)
5354
GFXRECON_WRITE_CONSOLE("\t\t\t[--pause-frame <N>] [--paused] [--sync] [--screenshot-all]");
5455
GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshots <N1(-N2),...>] [--screenshot-format <format>]");
5556
GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshot-dir <dir>] [--screenshot-prefix <file-prefix>]");
57+
GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshot-size <width>x<height>]");
58+
GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshot-scale <scale>]");
5659
GFXRECON_WRITE_CONSOLE("\t\t\t[--sfa | --skip-failed-allocations] [--replace-shaders <dir>]");
5760
GFXRECON_WRITE_CONSOLE("\t\t\t[--opcd | --omit-pipeline-cache-data] [--wsi <platform>]");
5861
GFXRECON_WRITE_CONSOLE("\t\t\t[--use-cached-psos] [--surface-index <N>]");

tools/tool_settings.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ const char kScreenshotRangeArgument[] = "--screenshots";
9494
const char kScreenshotFormatArgument[] = "--screenshot-format";
9595
const char kScreenshotDirArgument[] = "--screenshot-dir";
9696
const char kScreenshotFilePrefixArgument[] = "--screenshot-prefix";
97+
const char kScreenshotSizeArgument[] = "--screenshot-size";
98+
const char kScreenshotScaleArgument[] = "--screenshot-scale";
9799
const char kForceWindowedShortArgument[] = "--fw";
98100
const char kForceWindowedLongArgument[] = "--force-windowed";
99101
const char kOutput[] = "--output";
@@ -464,6 +466,60 @@ static std::string GetScreenshotDir(const gfxrecon::util::ArgumentParser& arg_pa
464466
return kDefaultScreenshotDir;
465467
}
466468

469+
static void GetScreenshotSize(const gfxrecon::util::ArgumentParser& arg_parser, uint32_t& width, uint32_t& height)
470+
{
471+
const auto& value = arg_parser.GetArgumentValue(kScreenshotSizeArgument);
472+
473+
if (!value.empty())
474+
{
475+
std::size_t x = value.find("x");
476+
if (x != std::string::npos)
477+
{
478+
try
479+
{
480+
width = std::stoul(value.substr(0, x));
481+
height = std::stoul(value.substr(x + 1));
482+
}
483+
catch (std::exception& e)
484+
{
485+
GFXRECON_LOG_WARNING("Ignoring invalid screenshot width x height option. Expected format is "
486+
"--screenshot-size [width]x[height]");
487+
width = height = 0;
488+
}
489+
}
490+
else
491+
{
492+
width = height = 0;
493+
}
494+
}
495+
else
496+
{
497+
width = height = 0;
498+
}
499+
}
500+
501+
static float GetScreenshotScale(const gfxrecon::util::ArgumentParser& arg_parser)
502+
{
503+
const auto& value = arg_parser.GetArgumentValue(kScreenshotScaleArgument);
504+
505+
float scale = 0.0f;
506+
507+
if (!value.empty())
508+
{
509+
try
510+
{
511+
scale = std::stof(value);
512+
}
513+
catch (std::exception& e)
514+
{
515+
GFXRECON_LOG_WARNING(
516+
"Ignoring invalid screenshot scale option. Expected format is --screenshot-scale [scale]");
517+
}
518+
}
519+
520+
return scale;
521+
}
522+
467523
static std::vector<gfxrecon::decode::ScreenshotRange>
468524
GetScreenshotRanges(const gfxrecon::util::ArgumentParser& arg_parser)
469525
{
@@ -770,6 +826,9 @@ GetVulkanReplayOptions(const gfxrecon::util::ArgumentParser& arg_parse
770826
replay_options.screenshot_format = GetScreenshotFormat(arg_parser);
771827
replay_options.screenshot_dir = GetScreenshotDir(arg_parser);
772828
replay_options.screenshot_file_prefix = arg_parser.GetArgumentValue(kScreenshotFilePrefixArgument);
829+
GetScreenshotSize(arg_parser, replay_options.screenshot_width, replay_options.screenshot_height);
830+
replay_options.screenshot_scale = GetScreenshotScale(arg_parser);
831+
773832
if (arg_parser.IsOptionSet(kQuitAfterMeasurementRangeOption))
774833
{
775834
replay_options.quit_after_measurement_frame_range = true;

0 commit comments

Comments
 (0)