Skip to content

Commit

Permalink
Screenshot size during replay is now configurable
Browse files Browse the repository at this point in the history
Use --screenshot-size <width>x<height> at replay in order to set the
size of the generated screenshot files
  • Loading branch information
panos-lunarg committed Aug 14, 2023
1 parent 7a7d18d commit af377ba
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 15 deletions.
5 changes: 5 additions & 0 deletions android/scripts/gfxrecon.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <width>x<height>.')
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)')
Expand Down Expand Up @@ -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')

Expand Down
45 changes: 33 additions & 12 deletions framework/decode/screenshot_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,26 @@ 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))
{
GFXRECON_LOG_ERROR("Screenshot could not be created: missing device table or allocator");
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.
Expand Down Expand Up @@ -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;
}

Expand All @@ -151,6 +163,8 @@ void ScreenshotHandler::WriteImage(const std::string& filen
copy_format,
width,
height,
copy_width,
copy_height,
&copy_resource);
}
else if (buffer_size == 0)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -377,8 +391,12 @@ void ScreenshotHandler::WriteImage(const std::string& filen
1, &invalidate_range, &copy_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);
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -597,7 +617,8 @@ VkResult ScreenshotHandler::CreateCopyResource(VkDevice
&copy_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.
Expand All @@ -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;
Expand Down Expand Up @@ -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
{
Expand Down
6 changes: 5 additions & 1 deletion framework/decode/screenshot_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion framework/decode/vulkan_replay_consumer_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions framework/decode/vulkan_replay_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct VulkanReplayOptions : public ReplayOptions
std::vector<ScreenshotRange> screenshot_ranges;
std::string screenshot_dir;
std::string screenshot_file_prefix{ kDefaultScreenshotFilePrefix };
uint32_t screenshot_width, screenshot_height;
std::string replace_dir;
};

Expand Down
3 changes: 2 additions & 1 deletion tools/replay/replay_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -53,6 +53,7 @@ static void PrintUsage(const char* exe_name)
GFXRECON_WRITE_CONSOLE("\t\t\t[--pause-frame <N>] [--paused] [--sync] [--screenshot-all]");
GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshots <N1(-N2),...>] [--screenshot-format <format>]");
GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshot-dir <dir>] [--screenshot-prefix <file-prefix>]");
GFXRECON_WRITE_CONSOLE("\t\t\t[--screenshot-size <width>x<height>]");
GFXRECON_WRITE_CONSOLE("\t\t\t[--sfa | --skip-failed-allocations] [--replace-shaders <dir>]");
GFXRECON_WRITE_CONSOLE("\t\t\t[--opcd | --omit-pipeline-cache-data] [--wsi <platform>]");
GFXRECON_WRITE_CONSOLE("\t\t\t[--use-cached-psos] [--surface-index <N>]");
Expand Down
32 changes: 32 additions & 0 deletions tools/tool_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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<gfxrecon::decode::ScreenshotRange>
GetScreenshotRanges(const gfxrecon::util::ArgumentParser& arg_parser)
{
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit af377ba

Please sign in to comment.