Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added handling missing VK_EXT_swapchain_colorspace #1287

Merged
merged 7 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions USAGE_android.md
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ usage: gfxrecon.py replay [-h] [--push-file LOCAL_FILE] [--version] [--pause-fra
[--measurement-file DEVICE_FILE] [--quit-after-measurement-range]
[--flush-measurement-range] [-m MODE]
[--swapchain MODE] [--use-captured-swapchain-indices]
[--use-colorspace-fallback]
[file]

Launch the replay tool.
Expand Down Expand Up @@ -858,17 +859,21 @@ optional arguments:
If this is specified the replayer will flush and wait
for all current GPU work to finish at the start and end
of the measurement range. (forwarded to replay tool)
--use-colorspace-fallback
Swap the swapchain color space if unsupported by replay device.
Check if color space is not supported by replay device and swap
to VK_COLOR_SPACE_SRGB_NONLINEAR_KHR. (forwarded to replay tool).
```

The command will force-stop an active replay process before starting the replay
activity with the following:

```bash
adb shell am force-stop com.lunarg.gfxreconstruct.replay
adb shell am start -n "com.lunarg.gfxreconstruct.replay/android.app.NativeActivity" \
-a android.intent.action.MAIN \
-c android.intent.category.LAUNCHER \
--es "args" \
adb shell am start -n "com.lunarg.gfxreconstruct.replay/android.app.NativeActivity" \
-a android.intent.action.MAIN \
-c android.intent.category.LAUNCHER \
--es "args" \
"<arg-list>"
```

Expand Down
5 changes: 5 additions & 0 deletions USAGE_desktop_Vulkan.md
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ gfxrecon-replay [-h | --help] [--version] [--gpu <index>]
[--flush-measurement-range]
[--log-level <level>] [--log-file <file>] [--log-debugview]
[--api <api>] [--no-debug-popup] <file>
[--use-colorspace-fallback]

Required arguments:
<file> Path to the capture file to replay.
Expand Down Expand Up @@ -531,6 +532,10 @@ Optional arguments:
If this is specified the replayer will flush
and wait for all current GPU work to finish at the
start and end of the measurement range.
--use-colorspace-fallback
Swap the swapchain color space if unsupported by replay device.
Check if color space is not supported by replay device and
fallback to VK_COLOR_SPACE_SRGB_NONLINEAR_KHR.
```

### 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 @@ -84,6 +84,7 @@ def CreateReplayParser():
parser.add_argument('--remove-unsupported', action='store_true', default=False, help='Remove unsupported extensions and features from instance and device creation parameters (forwarded to replay tool)')
parser.add_argument('--validate', action='store_true', default=False, help='Enables the Khronos Vulkan validation layer (forwarded to replay tool)')
parser.add_argument('--onhb', '--omit-null-hardware-buffers', action='store_true', default=False, help='Omit Vulkan calls that would pass a NULL AHardwareBuffer* (forwarded to replay tool)')
parser.add_argument('--use-colorspace-fallback', action='store_true', default=False, help='Swap the swapchain color space if unsupported by replay device. Check if color space is not supported by replay device and swap to VK_COLOR_SPACE_SRGB_NONLINEAR_KHR. (forwarded to replay tool).')
parser.add_argument('--mfr', '--measurement-frame-range', metavar='START-END', help='Custom framerange to measure FPS for. This range will include the start frame but not the end frame. The measurement frame range defaults to all frames except the loading frame but can be configured for any range. If the end frame is past the last frame in the trace it will be clamped to the frame after the last (so in that case the results would include the last frame). (forwarded to replay tool)')
parser.add_argument('--measurement-file', metavar='DEVICE_FILE', help='Write measurements to a file at the specified path. Default is: \'/sdcard/gfxrecon-measurements.json\' on android and \'./gfxrecon-measurements.json\' on desktop. (forwarded to replay tool)')
parser.add_argument('--quit-after-measurement-range', action='store_true', default=False, help='If this is specified the replayer will abort when it reaches the <end_frame> specified in the --measurement-frame-range argument. (forwarded to replay tool)')
Expand Down Expand Up @@ -166,6 +167,9 @@ def MakeExtrasString(args):
if args.use_captured_swapchain_indices:
arg_list.append('--use-captured-swapchain-indices')

if args.use_colorspace_fallback:
arg_list.append('--use-colorspace-fallback')

if args.mfr:
arg_list.append('--mfr')
arg_list.append('{}'.format(args.mfr))
Expand Down
20 changes: 20 additions & 0 deletions framework/decode/vulkan_feature_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <set>
#include <string>
#include <vector>
#include <algorithm>

GFXRECON_BEGIN_NAMESPACE(gfxrecon)
GFXRECON_BEGIN_NAMESPACE(decode)
Expand Down Expand Up @@ -169,6 +170,25 @@ void RemoveUnsupportedExtensions(const std::vector<VkExtensionProperties>& prope
}
}

void RemoveExtensionIfUnsupported(const std::vector<VkExtensionProperties>& properties,
std::vector<const char*>* extensions,
const char* extension_to_remove)
{
if (!feature_util::IsSupportedExtension(properties, extension_to_remove))
{
auto extension_iter =
std::find_if(extensions->begin(), extensions->end(), [&extension_to_remove](const char* extension) {
return util::platform::StringCompare(extension_to_remove, extension) == 0;
});
if (extension_iter != extensions->end())
{
GFXRECON_LOG_WARNING("Extension %s, which is not supported by the replay device, will not be enabled",
*extension_iter);
extensions->erase(extension_iter);
}
}
}

// Remove any extensions which can be enabled by the application, but can be ignored during replay if
// they don't exist on the target device.
void RemoveIgnorableExtensions(const std::vector<VkExtensionProperties>& properties,
Expand Down
5 changes: 4 additions & 1 deletion framework/decode/vulkan_feature_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ bool IsSupportedExtension(const std::vector<VkExtensionProperties>& properties,
void RemoveUnsupportedExtensions(const std::vector<VkExtensionProperties>& properties,
std::vector<const char*>* extensions);

bool IsSupportedExtension(const std::vector<VkExtensionProperties>& properties, const char* extension);
void RemoveExtensionIfUnsupported(const std::vector<VkExtensionProperties>& properties,
std::vector<const char*>* extensions,
const char* extension);

void RemoveIgnorableExtensions(const std::vector<VkExtensionProperties>& properties,
std::vector<const char*>* extensions);

Expand Down
69 changes: 50 additions & 19 deletions framework/decode/vulkan_replay_consumer_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "decode/vulkan_object_cleanup_util.h"
#include "format/format_util.h"
#include "generated/generated_vulkan_struct_handle_mappers.h"
#include "generated/generated_vulkan_constant_maps.h"
#include "graphics/vulkan_device_util.h"
#include "graphics/vulkan_util.h"
#include "util/file_path.h"
Expand Down Expand Up @@ -2283,6 +2284,14 @@ VulkanReplayConsumerBase::OverrideCreateInstance(VkResult original_result,
// Remove enabled extensions that are not available from the replay instance.
feature_util::RemoveUnsupportedExtensions(available_extensions, &filtered_extensions);
}
else if (options_.use_colorspace_fallback)
{
for (auto& extension_name : kColorSpaceExtensionNames)
{
feature_util::RemoveExtensionIfUnsupported(
available_extensions, &filtered_extensions, extension_name);
}
}
else
{
// Remove enabled extensions that are ignorable from the replay instance.
Expand Down Expand Up @@ -4998,29 +5007,51 @@ VkResult VulkanReplayConsumerBase::OverrideCreateSwapchainKHR(

ProcessSwapchainFullScreenExclusiveInfo(pCreateInfo->GetMetaStructPointer());

if (screenshot_handler_ == nullptr)
{
result = swapchain_->CreateSwapchainKHR(original_result,
func,
device_info,
replay_create_info,
GetAllocationCallbacks(pAllocator),
pSwapchain,
GetDeviceTable(device_info->handle));
}
else
VkSwapchainCreateInfoKHR modified_create_info = (*replay_create_info);

if (screenshot_handler_ != nullptr)
{
// Screenshots are active, so ensure that swapchain images can be used as a transfer source.
VkSwapchainCreateInfoKHR modified_create_info = (*replay_create_info);
modified_create_info.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
result = swapchain_->CreateSwapchainKHR(original_result,
func,
device_info,
&modified_create_info,
GetAllocationCallbacks(pAllocator),
pSwapchain,
GetDeviceTable(device_info->handle));
}

bool colorspace_extension_used_unsupported = false;
PhysicalDeviceInfo* physical_device_info = object_info_table_.GetPhysicalDeviceInfo(device_info->parent_id);
InstanceInfo* instance_info = object_info_table_.GetInstanceInfo(physical_device_info->parent_id);

auto colorspace_extension_map_iterator = kColorSpaceExtensionMap.find(replay_create_info->imageColorSpace);
if (colorspace_extension_map_iterator != kColorSpaceExtensionMap.end())
{
auto supported_extension_iterator = std::find(instance_info->enabled_extensions.begin(),
instance_info->enabled_extensions.end(),
colorspace_extension_map_iterator->second);
colorspace_extension_used_unsupported =
supported_extension_iterator == instance_info->enabled_extensions.end();
}

if (colorspace_extension_used_unsupported)
{
if (options_.use_colorspace_fallback)
{
modified_create_info.imageColorSpace = VkColorSpaceKHR::VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
GFXRECON_LOG_INFO("Forcing supported color space for swapchain (ID = %" PRIu64 ")",
swapchain_info->capture_id);
}
else
{
GFXRECON_LOG_ERROR("Swapchain (ID = %" PRIu64
") uses color space provided by unsupported VK_EXT_swapchain_colorspace",
swapchain_info->capture_id);
}
}

result = swapchain_->CreateSwapchainKHR(original_result,
func,
device_info,
&modified_create_info,
GetAllocationCallbacks(pAllocator),
pSwapchain,
GetDeviceTable(device_info->handle));
}
else
{
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 @@ -47,6 +47,7 @@ struct VulkanReplayOptions : public ReplayOptions
bool skip_failed_allocations{ false };
bool omit_pipeline_cache_data{ false };
bool remove_unsupported_features{ false };
bool use_colorspace_fallback{ false };
util::SwapchainOption swapchain_option{ util::SwapchainOption::kVirtual };
int32_t override_gpu_group_index{ -1 };
int32_t surface_index{ -1 };
Expand Down
1 change: 1 addition & 0 deletions framework/generated/generate_vulkan.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
'generated_vulkan_struct_to_json.cpp',
'generated_vulkan_enum_to_json.h',
'generated_vulkan_enum_to_json.cpp',
'generated_vulkan_constant_maps.h'
]

if __name__ == '__main__':
Expand Down
75 changes: 75 additions & 0 deletions framework/generated/generated_vulkan_constant_maps.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
** Copyright (c) 2018-2023 Valve Corporation
** Copyright (c) 2018-2023 LunarG, Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and associated documentation files (the "Software"),
** to deal in the Software without restriction, including without limitation
** the rights to use, copy, modify, merge, publish, distribute, sublicense,
** and/or sell copies of the Software, and to permit persons to whom the
** Software is furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
** DEALINGS IN THE SOFTWARE.
*/

/*
** This file is generated from the Khronos Vulkan XML API Registry.
**
*/

#ifndef GFXRECON_GENERATED_VULKAN_CONSTANT_MAPS_H
#define GFXRECON_GENERATED_VULKAN_CONSTANT_MAPS_H

#include "util/defines.h"

#include "vulkan/vulkan.h"
#include "vk_video/vulkan_video_codec_h264std.h"
#include "vk_video/vulkan_video_codec_h264std_decode.h"
#include "vk_video/vulkan_video_codec_h264std_encode.h"
#include "vk_video/vulkan_video_codec_h265std.h"
#include "vk_video/vulkan_video_codec_h265std_decode.h"
#include "vk_video/vulkan_video_codec_h265std_encode.h"
#include "vk_video/vulkan_video_codecs_common.h"

#include <unordered_map>
#include <vector>
GFXRECON_BEGIN_NAMESPACE(gfxrecon)
GFXRECON_BEGIN_NAMESPACE(decode)

static const std::unordered_map<VkColorSpaceKHR, const char *> kColorSpaceExtensionMap = {
{VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_BT709_LINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_BT709_NONLINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_BT2020_LINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_HDR10_ST2084_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_DOLBYVISION_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_HDR10_HLG_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_PASS_THROUGH_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_DCI_P3_LINEAR_EXT, "VK_EXT_swapchain_colorspace"},
{VK_COLOR_SPACE_DISPLAY_NATIVE_AMD, "VK_AMD_display_native_hdr"},
};

static const std::vector<const char *> kColorSpaceExtensionNames = {
"VK_AMD_display_native_hdr",
"VK_EXT_swapchain_colorspace",
charles-lunarg marked this conversation as resolved.
Show resolved Hide resolved
};

GFXRECON_END_NAMESPACE(decode)
GFXRECON_END_NAMESPACE(gfxrecon)

#endif
17 changes: 17 additions & 0 deletions framework/generated/vulkan_generators/gencode.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@
from vulkan_struct_to_json_header_generator import VulkanStructToJsonHeaderGenerator, VulkanStructToJsonHeaderGeneratorOptions
from vulkan_struct_to_json_body_generator import VulkanStructToJsonBodyGenerator, VulkanStructToJsonBodyGeneratorOptions

# Constants
from vulkan_constant_maps_generator import VulkanConstantMapsGenerator, VulkanConstantMapsGeneratorOptions

# Simple timer functions
start_time = None

Expand Down Expand Up @@ -699,6 +702,20 @@ def make_gen_opts(args):
)
]

gen_opts['generated_vulkan_constant_maps.h'] = [
VulkanConstantMapsGenerator,
VulkanConstantMapsGeneratorOptions(
filename='generated_vulkan_constant_maps.h',
directory=directory,
blacklists=blacklists,
platform_types=platform_types,
prefix_text=prefix_strings + vk_prefix_strings,
protect_file=True,
protect_feature=False,
extraVulkanHeaders=extraVulkanHeaders
)
]

def gen_target(args):
"""Generate a target based on the options in the matching gen_opts{} object.
This is encapsulated in a function so it can be profiled and/or timed.
Expand Down
Loading