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

Add Image Compression Control Sample (no-op merge, please ignore) #963

Conversation

JoseEmilio-ARM
Copy link
Collaborator

@JoseEmilio-ARM JoseEmilio-ARM commented Mar 6, 2024

⚠️ Due to issues with GitHub, the PR was closed with the incorrect label 'merged' (the only commit is already present in main) and cannot be re-opened, so moved the review to a new PR: #979

Description

This sample showcases how to control image compression, in particular framebuffer attachments and the swapchain. The use case is a simple post-processing effect (chromatic aberration) applied to the output color of a forward-rendering pass.
The developer can select "Default" compression, "Fixed rate" compression, or "None". The sample shows the impact each option has on bandwidth (write bytes counter) and memory footprint (image sizes once allocated). More info in the tutorial: samples/performance/image_compression_control/README.adoc

image_compression_control

Fixes #882

Also added a small change to the AFBC sample to use the new extension if available, to confirm that AFBC is being used.

Framework Changes

Image class:

Added helper functions to query for compression support, apply compression, and check that compression was applied. Also to return image size (to display footprint).

Swapchain class:

Similarly, added helper functions to query for compression support, apply compression, and check that compression was applied, for the swapchain images. This also requires exposing this control to the Render Context class.

PhysicalDevice/Device classes:

Moved is_extension_supported responsibilities to the PhysicalDevice class, so that we can check if an extension is supported (and therefore if we can request its features) before the Device is created.

String utils:

Added a few more enum-to-string functions for image flags.

General Checklist:

Please ensure the following points are checked:

  • My code follows the coding style
  • I have reviewed file licenses
  • I have commented any added functions (in line with Doxygen)
  • I have commented any code that could be hard to understand
  • My changes do not add any new compiler warnings
  • My changes do not add any new validation layer errors or warnings
  • I have used existing framework/helper functions where possible
  • My changes do not add any regressions
  • I have tested every sample to ensure everything runs correctly
  • This PR describes the scope and expected impact of the changes I am making

Note: The Samples CI runs a number of checks including:

  • I have updated the header Copyright to reflect the current year (CI build will fail if Copyright is out of date)
  • My changes build on Windows, Linux, macOS and Android. Otherwise I have documented any exceptions. Tested on Windows and Android.

Sample Checklist

If your PR contains a new or modified sample, these further checks must be carried out in addition to the General Checklist:

  • I have tested the sample on at least one compliant Vulkan implementation
  • If the sample is vendor-specific, I have tagged it appropriately
  • I have stated on what implementation the sample has been tested so that others can test on different implementations and platforms
  • Any dependent assets have been merged and published in downstream modules
  • For new samples, I have added a paragraph with a summary to the appropriate chapter in the readme of the folder that the sample belongs to e.g. api samples readme
  • For new samples, I have added a tutorial README.md file to guide users through what they need to know to implement code using this feature. For example, see conditional_rendering
  • For new samples, I have added a link to the Antora navigation so that the sample will be listed at the Vulkan documentation site

Copy link
Collaborator

@SaschaWillems SaschaWillems left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like an interesting example and a nice addition to our repo :)

Sadly for me on Windows 11 with an NVIDIA RTX 4070 this sample crashes with the following error message:

image

The assert happens in RenderFrame &RenderContext::get_active_frame().

I also get these validation errors:

[error] [framework\core\instance.cpp:50] -1876993556 - VUID-VkDeviceCreateInfo-pNext-pNext: Validation Error: [ VUID-VkDeviceCreateInfo-pNext-pNext ] Object 0: handle = 0x20e8d305360, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0x901f59ec | vkCreateDevice(): pCreateInfo->pNext includes a pointer to a VkPhysicalDeviceImageCompressionControlSwapchainFeaturesEXT, but when creating VkDevice, the parent extension (VK_EXT_image_compression_control_swapchain) was not included in ppEnabledExtensionNames. The Vulkan spec states: Each pNext member of any structure (including this one) in the pNext chain must be either NULL or a pointer to a valid struct for extending VkDeviceCreateInfo (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDeviceCreateInfo-pNext-pNext)

[error] [framework\core\instance.cpp:50] -1876993556 - VUID-VkDeviceCreateInfo-pNext-pNext: Validation Error: [ VUID-VkDeviceCreateInfo-pNext-pNext ] Object 0: handle = 0x20e8d305360, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0x901f59ec | vkCreateDevice(): pCreateInfo->pNext includes a pointer to a VkPhysicalDeviceImageCompressionControlFeaturesEXT, but when creating VkDevice, the parent extension (VK_EXT_image_compression_control) was not included in ppEnabledExtensionNames. The Vulkan spec states: Each pNext member of any structure (including this one) in the pNext chain must be either NULL or a pointer to a valid struct for extending VkDeviceCreateInfo (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDeviceCreateInfo-pNext-pNext)

@SaschaWillems
Copy link
Collaborator

The crash on my setup is most probably caused by the lack of support for VK_EXT_image_compression_control_swapchain. But in that case, the sample shouldn't crash, but rather fail gracefully by e.g. reporting the extension as unsupported.

@JoseEmilio-ARM
Copy link
Collaborator Author

The crash on my setup is most probably caused by the lack of support for VK_EXT_image_compression_control_swapchain. But in that case, the sample shouldn't crash, but rather fail gracefully by e.g. reporting the extension as unsupported.

Thanks a lot for reviewing and testing 🙏 I tried it on Windows too (Quadro T2000) and I cannot reproduce the crash or the validation messages (SDK 1.3.250.1), do you get to see the logs before the crash? The extensions are marked as optional, so I get

[warning] Optional device extension VK_EXT_image_compression_control not available, some features may be disabled
[warning] Optional device extension VK_EXT_image_compression_control_swapchain not available, some features may be disabled

Then the sample should report that the extensions are not supported like this:

image

You think my drivers are more permissive, and perhaps there's a bug in request_extension_features? or maybe we are expected to guard the calls in request_gpu_features with checks like if (device->is_enabled(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME))?

@JoseEmilio-ARM
Copy link
Collaborator Author

JoseEmilio-ARM commented Mar 7, 2024

or maybe we are expected to guard the calls in request_gpu_features with checks

Added a small patch to test this theory, @SaschaWillems please let me know if you have a chance to test again, thanks!

My bad, that seems to break things for me. Looking at other samples, they all request features this way, not sure what the issue is with this particular extension and only on some platforms 🤔 any ideas?

@SaschaWillems
Copy link
Collaborator

I'm on a more recent build of the layers (built from source), and they report an error instead of a warning. This may cause the device to not get created.

Will check with layers from the latest SDK and report back.

@SaschaWillems
Copy link
Collaborator

With SDK 1.3.275 I'm not getting any validation errors, I still get the assertion I posted above. If I ignore it, the sample will run though. So maybe something isn't properly initialized at first start? May be caused by what I described in #920.

@JoseEmilio-ARM
Copy link
Collaborator Author

With SDK 1.3.275 I'm not getting any validation errors, I still get the assertion I posted above. If I ignore it, the sample will run though. So maybe something isn't properly initialized at first start? May be caused by what I described in #920.

Thank you very much for checking, I'll look into it, although for some reason I cannot reproduce the assertion. Out of curiosity, do you get the same issue with other samples that require an extension that your platform does not support?

@SaschaWillems
Copy link
Collaborator

SaschaWillems commented Mar 9, 2024

Hard to test, as my GPU supports all extension we use in our samples. But "faking" this by requesting an unsupported extension in a sample looks to work properly. If I request an unsupported extension in an api based sample it displays an error and closes gracefully. Maybe it's something related to the ARM framework class after all?

This is where the error happens:

image

It triggers the assert, but only on the first frame of the sample. So I guess the first frame of the sample tries to access something not (yet) created. Hence why it works if I skip this. For the next frame, everything is correct.

@JoseEmilio-ARM
Copy link
Collaborator Author

It triggers the assert, but only on the first frame of the sample. So I guess the first frame of the sample tries to access something not (yet) created. Hence why it works if I skip this. For the next frame, everything is correct.

It could well be a framework issue, but finding it hard to debug without being able to reproduce. I did a clean-build on a different PC with a different GPU (RTX 3070) and the sample still works fine 🤔

On the other hand I found that the new Swapchain::query_supported_fixed_rate_compression was using extension features, so added a new guard against it (see latest commit). Any chance you could try again? and if so, could you share the sample's LOGs up to the point of the assertion?

@SaschaWillems
Copy link
Collaborator

SaschaWillems commented Mar 9, 2024

The assert on the first frame is sadly still present.

What's odd: The last three lines are

[info] Depth format selected: VK_FORMAT_D32_SFLOAT
[info] Depth format selected: VK_FORMAT_D32_SFLOAT
[info] Depth format selected: VK_FORMAT_D32_SFLOAT

Not sure why the sample (or framework) does that three times in a row.

I do see an error on the log though:

[error] [framework\core\swapchain.cpp:645] (Swapchain) To query fixed-rate compression support, device extension VK_EXT_image_compression_control_swapchain must be enabled

Here is the log up to the first assert: log_tex_compression.txt

@JoseEmilio-ARM
Copy link
Collaborator Author

@SaschaWillems thank you very much for your help, the logs allowed me to find a few more issues. Also realized I was testing release builds and that's why I could not reproduce the assertion, apologies!

I think both the assertion and the validation layer error should now be fixed.

The repeated logs about the selected depth format are expected, I think they are related to the fact that we create a render target per RenderFrame in flight, which at the moment is one per swapchain image. Agree this should be improved as we probably do not need more than 2.

SaschaWillems
SaschaWillems previously approved these changes Mar 9, 2024
Copy link
Collaborator

@SaschaWillems SaschaWillems left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can confirm that this now works as expected for me. Code and documentation also looking good to me 👍🏻

@JoseEmilio-ARM JoseEmilio-ARM self-assigned this Mar 9, 2024
@JoseEmilio-ARM JoseEmilio-ARM added the sample This is relevant to a sample label Mar 9, 2024
@gary-sweet
Copy link
Contributor

This works well for me. We only support one level of compression on our hardware, so the low/high selector in the UI just appears to do nothing. Would it be sensible to hide that UI selector if only one level is available?

@JoseEmilio-ARM
Copy link
Collaborator Author

This works well for me. We only support one level of compression on our hardware, so the low/high selector in the UI just appears to do nothing. Would it be sensible to hide that UI selector if only one level is available?

Thank you very much for testing! Good point, certainly. Please let me know if my last commit works as expected.

gary-sweet
gary-sweet previously approved these changes Mar 11, 2024
Copy link
Contributor

@gary-sweet gary-sweet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update, LGTM now.

@JoseEmilio-ARM
Copy link
Collaborator Author

@jherico I updated the Image and Swapchain classes in this PR (so that their constructors can take the new structures, introduced by the compression control extensions, in their pNext chains)

I had to rebase the Image changes now that #906 was merged. What do you think of how I updated the Image using the new Builder? It seems that #973 will conflict too...

framework/core/allocated.h Outdated Show resolved Hide resolved
framework/core/image.cpp Outdated Show resolved Hide resolved
framework/core/image.cpp Outdated Show resolved Hide resolved
framework/core/image.h Outdated Show resolved Hide resolved
framework/core/swapchain.h Outdated Show resolved Hide resolved
@JoseEmilio-ARM JoseEmilio-ARM mentioned this pull request Mar 11, 2024
12 tasks
framework/core/image.h Outdated Show resolved Hide resolved
framework/core/device.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@jherico jherico left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but bear in mind I'm not a Khronos member, so I don't think my review technically carries any weight.

Introduce type aliases on conditional types; refactor dual interface functions to single ones using those conditional types.

Plus slightly adjust a few functions in VulkanSample for consistency.

Fix indentation in CMakeLists.txt; simplify body of VulkanSample::create_instance; fix device usage in profiles sample

Introduce Parent for class VulkanSample.

Unify class VulkanSample and HPPVulkanSample.

Introduce type aliases on conditional types; refactor dual interface functions to single ones using those conditional types.

Plus slightly adjust a few functions in VulkanSample for consistency.

Fix indentation in CMakeLists.txt; simplify body of VulkanSample::create_instance; fix device usage in profiles sample

Introduce Parent for class VulkanSample.

Fix typo.

Adjust hpp_timestamp_queries and oit_depth_peeling.

Fix color_write_enable.

Fix validation errors in timeline_semaphores sample (KhronosGroup#927)

* Fix validation errors in timeline_semaphores sample

The command buffer was being implicitly reset, but wasn't resettable.

* Review feedback addressed

Used a much simpler approach to resolve the error

Allow explicit skips in batch mode (KhronosGroup#914)

* Allow explicit skips in batch mode

* Fix bug in CLI11 wrapper that inhibits multi-value flag parsing

Unify class VulkanSample and HPPVulkanSample.

Unify class VulkanSample and HPPVulkanSample.

Introduce type aliases on conditional types; refactor dual interface functions to single ones using those conditional types.

Plus slightly adjust a few functions in VulkanSample for consistency.

Fix indentation in CMakeLists.txt; simplify body of VulkanSample::create_instance; fix device usage in profiles sample

Introduce Parent for class VulkanSample.

Introduce enum class vkb::BindingType to select between C- and C++-bindings of vulkan; replaces the boolean template parameter of VulkanSample.

Adjustments after rebasing.

Update vulkan

Adjustments due to rebasing.

Unify class VulkanSample and HPPVulkanSample.

Introduce type aliases on conditional types; refactor dual interface functions to single ones using those conditional types.

Plus slightly adjust a few functions in VulkanSample for consistency.

Fix indentation in CMakeLists.txt; simplify body of VulkanSample::create_instance; fix device usage in profiles sample

Introduce Parent for class VulkanSample.

Unify class VulkanSample and HPPVulkanSample.

Introduce type aliases on conditional types; refactor dual interface functions to single ones using those conditional types.

Plus slightly adjust a few functions in VulkanSample for consistency.

Fix indentation in CMakeLists.txt; simplify body of VulkanSample::create_instance; fix device usage in profiles sample

Introduce Parent for class VulkanSample.

Fix typo.

Adjust hpp_timestamp_queries and oit_depth_peeling.

Fix color_write_enable.

Fix validation errors in timeline_semaphores sample (KhronosGroup#927)

* Fix validation errors in timeline_semaphores sample

The command buffer was being implicitly reset, but wasn't resettable.

* Review feedback addressed

Used a much simpler approach to resolve the error

Allow explicit skips in batch mode (KhronosGroup#914)

* Allow explicit skips in batch mode

* Fix bug in CLI11 wrapper that inhibits multi-value flag parsing

Unify class VulkanSample and HPPVulkanSample.

Unify class VulkanSample and HPPVulkanSample.

Introduce type aliases on conditional types; refactor dual interface functions to single ones using those conditional types.

Plus slightly adjust a few functions in VulkanSample for consistency.

Fix indentation in CMakeLists.txt; simplify body of VulkanSample::create_instance; fix device usage in profiles sample

Introduce Parent for class VulkanSample.

Introduce enum class vkb::BindingType to select between C- and C++-bindings of vulkan; replaces the boolean template parameter of VulkanSample.

Adjustments after rebasing.

Update vulkan
@JoseEmilio-ARM
Copy link
Collaborator Author

LGTM, but bear in mind I'm not a Khronos member, so I don't think my review technically carries any weight.

Thank you very much! Your suggestions made it a much better PR 🙇

Copy link
Contributor

@asuessenbach asuessenbach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of more or less minor issues.
And a great usage of the builder pattern!

framework/common/strings.cpp Outdated Show resolved Hide resolved
framework/common/strings.cpp Outdated Show resolved Hide resolved
framework/core/image.cpp Outdated Show resolved Hide resolved
framework/core/image.cpp Outdated Show resolved Hide resolved
framework/core/swapchain.cpp Outdated Show resolved Hide resolved
@JoseEmilio-ARM JoseEmilio-ARM merged commit 6fb2196 into KhronosGroup:main Mar 12, 2024
19 checks passed
@JoseEmilio-ARM
Copy link
Collaborator Author

Apologies, for some reason, after the rebase, the PR kept picking up #910 as a change, even though it is the head of main right now. I tried another force-push with just that commit, and the PR was automatically closed. Does anyone know if it possible to re-open it? Otherwise, I'll create a new PR, sorry for the inconvenience!

@JoseEmilio-ARM JoseEmilio-ARM added duplicate This issue or pull request already exists and removed sample This is relevant to a sample labels Mar 12, 2024
@JoseEmilio-ARM JoseEmilio-ARM changed the title Add Image Compression Control Sample Add Image Compression Control Sample (no-op merge, please ignore) Mar 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New sample for VK_EXT_image_compression_control
5 participants