init
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# Copyright (c) 2019-2021, Arm Limited and Contributors
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 the "License";
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
get_filename_component(FOLDER_NAME ${CMAKE_CURRENT_LIST_DIR} NAME)
|
||||
get_filename_component(PARENT_DIR ${CMAKE_CURRENT_LIST_DIR} PATH)
|
||||
get_filename_component(CATEGORY_NAME ${PARENT_DIR} NAME)
|
||||
|
||||
add_sample_with_tags(
|
||||
ID ${FOLDER_NAME}
|
||||
CATEGORY ${CATEGORY_NAME}
|
||||
AUTHOR "Arm"
|
||||
NAME "AFBC"
|
||||
DESCRIPTION "Using framebuffer compression to reduce bandwidth."
|
||||
TAGS
|
||||
"arm"
|
||||
SHADER_FILES_GLSL
|
||||
"base.vert"
|
||||
"base.frag")
|
||||
@@ -0,0 +1,163 @@
|
||||
////
|
||||
- Copyright (c) 2019-2024, Arm Limited and Contributors
|
||||
-
|
||||
- SPDX-License-Identifier: Apache-2.0
|
||||
-
|
||||
- Licensed under the Apache License, Version 2.0 the "License";
|
||||
- you may not use this file except in compliance with the License.
|
||||
- You may obtain a copy of the License at
|
||||
-
|
||||
- http://www.apache.org/licenses/LICENSE-2.0
|
||||
-
|
||||
- Unless required by applicable law or agreed to in writing, software
|
||||
- distributed under the License is distributed on an "AS IS" BASIS,
|
||||
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
- See the License for the specific language governing permissions and
|
||||
- limitations under the License.
|
||||
-
|
||||
////
|
||||
= Enabling AFBC in your Vulkan Application
|
||||
|
||||
ifdef::site-gen-antora[]
|
||||
TIP: The source for this sample can be found in the https://github.com/KhronosGroup/Vulkan-Samples/tree/main/samples/performance/afbc[Khronos Vulkan samples github repository].
|
||||
endif::[]
|
||||
|
||||
|
||||
== Overview
|
||||
|
||||
AFBC (Arm Frame Buffer Compression) is a real-time lossless compression algorithm found in Arm Mali GPUs, designed to tackle the ever-growing demand for higher resolution graphics.
|
||||
This format is applied to the framebuffers that are to be written to the GPU.
|
||||
This technology can offer bandwidth reductions of https://developer.arm.com/technologies/graphics-technologies/arm-frame-buffer-compression[up to 50%].
|
||||
|
||||
The sample is geared towards demonstrating the bandwidth that you can save by toggling AFBC on and off and displaying a real-time graph of the external bandwidth.
|
||||
In this case we will be focusing on the swapchain images.
|
||||
|
||||
The Vulkan API allows the developer a level of control around how the `VkSwapchainKHR` is created and formatted.
|
||||
It is here where we want to ensure that it is created and formatted in the right way so that the subsequent ``VkImage``'s that we query from it have AFBC appropriately applied.
|
||||
|
||||
It is important to note that from a device perspective to have AFBC enabled on Vulkan, you will need at least driver version `r16p0` and a `Mali G-51` or higher.
|
||||
To find out your GPU and driver version, open the link:../../../docs/misc.adoc#Debug-Window[debug window] or follow the steps in this link:../../../docs/misc.adoc#Driver-Version[article].
|
||||
|
||||
____
|
||||
Tested on: Samsung Galaxy S10, Huawei P30
|
||||
____
|
||||
|
||||
== Enabling AFBC
|
||||
|
||||
AFBC is functionally transparent to the application and will be automatically applied on a per `VkImage` basis (provided multiple checks pass on various properties of your device and your images).
|
||||
|
||||
The driver will check the applications state along with the `VkImage` properties to determine if it will enable AFBC or just continue without it.
|
||||
This section will detail the requirements.
|
||||
|
||||
`VkImage` requirements:
|
||||
|
||||
* `VkSampleCountFlagBits` must be `VK_SAMPLE_COUNT_1_BIT`
|
||||
* `VkImageType` must be `VK_IMAGE_TYPE_2D`
|
||||
* `VkImageTiling` must be `VK_IMAGE_TILING_OPTIMAL`
|
||||
* `VkFormat` <<format-support,supported list>>
|
||||
|
||||
In addition to this, your `VkImage` needs to adhere to the following flags:
|
||||
|
||||
* `VkImageUsageFlags` must not contain:
|
||||
** `VK_IMAGE_USAGE_STORAGE_BIT`
|
||||
** `VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT`
|
||||
** (Only for some devices with driver version `r16p0`) `VK_IMAGE_USAGE_TRANSFER_DST_BIT`
|
||||
* `VkImageCreateFlags` must not contain:
|
||||
** `VK_IMAGE_CREATE_ALIAS_BIT`
|
||||
** `VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT`
|
||||
|
||||
== The AFBC Sample
|
||||
|
||||
The sample presents the user with Sponza, with a graph displaying bandwidth at the top and a configuration window at the bottom.
|
||||
There is a back-and-forth oscillating camera to disable any GPU optimisations for frames that are identical.
|
||||
|
||||
The configuration itself is simple.
|
||||
There is one checkbox (labelled "Enable AFBC") that will reload the swapchain when its value is changed.
|
||||
|
||||
image::./images/afbc_disabled.jpg[Sponza AFBC off]
|
||||
|
||||
Here the sample is in its default state: AFBC off.
|
||||
At the top of the screen there is a graph displaying the external write bandwidth (measured from `L2_EXT_WRITE_BEATS`).
|
||||
|
||||
It is currently setting the `VK_IMAGE_USAGE_STORAGE_BIT` flag in the `VkImageUsageFlags` for the swapchain images, causing the driver to skip over applying AFBC to the swapchain images.
|
||||
|
||||
When we enable the check box, the sample will reload the swapchain with the right usage flags to have the driver enable AFBC.
|
||||
|
||||
image::./images/afbc_enabled.jpg[Sponza AFBC on]
|
||||
|
||||
Here is the same scene as before, except AFBC is now enabled.
|
||||
The `VK_IMAGE_USAGE_STORAGE_BIT` flag is not being set and the swapchain is being created properly.
|
||||
|
||||
The bandwidth has dropped from 788.0 MiB/s to 528.6 MiB/s, this is approximately a 33% reduction.
|
||||
|
||||
You can also confirm these numbers in Streamline.
|
||||
Here are some screenshots:
|
||||
|
||||
image:./images/streamline_disabled.png[Streamline AFBC Off] image:./images/streamline_enabled.png[Streamline AFBC On]
|
||||
|
||||
== Format Support
|
||||
|
||||
GPUs from Mali-G77 onwards support formats up to and including 32 bits per pixel regardless of color channel arrangement or sRBG.
|
||||
|
||||
Previous generations that support AFBC only support a subset of formats:
|
||||
|
||||
[cols=^]
|
||||
|===
|
||||
| Formats
|
||||
|
||||
| VK_FORMAT_R4G4B4A4_UNORM_PACK16
|
||||
| VK_FORMAT_B4G4R4A4_UNORM_PACK16
|
||||
| VK_FORMAT_R5G6B5_UNORM_PACK16
|
||||
| VK_FORMAT_R5G5B5A1_UNORM_PACK16
|
||||
| VK_FORMAT_B5G5R5A1_UNORM_PACK16
|
||||
| VK_FORMAT_A1R5G5B5_UNORM_PACK16
|
||||
| VK_FORMAT_B8G8R8_UNORM
|
||||
| VK_FORMAT_B8G8R8A8_UNORM
|
||||
| VK_FORMAT_B8G8R8A8_SRGB
|
||||
| VK_FORMAT_A8B8G8R8_UNORM
|
||||
| VK_FORMAT_A8B8G8R8_SRGB
|
||||
| VK_FORMAT_A8R8G8B8_SRGB
|
||||
| VK_FORMAT_B10G10R10A2_UNORM
|
||||
| VK_FORMAT_R4G4B4A4_UNORM
|
||||
| VK_FORMAT_R5G6B5_UNORM
|
||||
| VK_FORMAT_R5G5B5A1_UNORM
|
||||
| VK_FORMAT_R8_UNORM
|
||||
| VK_FORMAT_R8G8_UNORM
|
||||
| VK_FORMAT_R8G8B8_UNORM
|
||||
| VK_FORMAT_R8G8B8A8_UNORM
|
||||
| VK_FORMAT_R8G8B8A8_SRGB
|
||||
| VK_FORMAT_A8R8G8B8_UNORM
|
||||
| VK_FORMAT_R10G10B10A2_UNORM
|
||||
| VK_FORMAT_D24_UNORM_S8_UINT
|
||||
| VK_FORMAT_D16_UNORM
|
||||
| VK_FORMAT_D32_SFLOAT
|
||||
|===
|
||||
|
||||
== Further Reading
|
||||
|
||||
* https://www.arm.com/why-arm/technologies/graphics-technologies/arm-frame-buffer-compression[Arm Frame Buffer Compression] - developer.arm.com
|
||||
|
||||
== Best practice summary
|
||||
|
||||
*Do*
|
||||
|
||||
* Ensure that your swapchain is created correctly as per the requirements of AFBC.
|
||||
* AFBC is not a replacement for (it is independent of) texture compression like ASTC, so always compress all of the things when possible.
|
||||
* Avoid changing your image configuration at run-time (using `vkCmdCopyImage` with an invalid AFBC requirement) as it will trigger a decompression.
|
||||
* Make sure you are resolving your images using `pResolveAttachments` when it comes to multisampling.
|
||||
Any `VkImage` with `SAMPLE_COUNT > 1` will not have AFBC applied to it.
|
||||
|
||||
*Don't*
|
||||
|
||||
* Use image usage flags, such as `VK_IMAGE_USAGE_STORAGE_BIT`, unless you really need it (i.e.
|
||||
for compute on a specific image).
|
||||
|
||||
*Impact*
|
||||
|
||||
* Having an incorrect configuration of your images will cause all your surface ``VkImage``'s to be uncompressed, losing out on considerable system wide bandwidth reductions.
|
||||
|
||||
*Debugging*
|
||||
|
||||
* To test if AFBC is enabled or disabled, you can use a profiler such as Streamline and record the bandwidth values when AFBC is enabled or when AFBC is disabled.
|
||||
* You may also use the extension https://docs.vulkan.org/spec/latest/appendices/extensions.html#VK_EXT_image_compression_control[`VK_EXT_image_compression_control`] to query if AFBC is enabled.
|
||||
See the xref:/samples/performance/image_compression_control/README.adoc[Image Compression Control sample] for more details.
|
||||
@@ -0,0 +1,136 @@
|
||||
/* Copyright (c) 2019-2025, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 the "License";
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "afbc.h"
|
||||
|
||||
#include "common/vk_common.h"
|
||||
#include "filesystem/legacy.h"
|
||||
#include "gltf_loader.h"
|
||||
#include "gui.h"
|
||||
|
||||
#include "rendering/subpasses/forward_subpass.h"
|
||||
#include "stats/stats.h"
|
||||
|
||||
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
|
||||
# include "platform/android/android_platform.h"
|
||||
#endif
|
||||
|
||||
#include "scene_graph/components/camera.h"
|
||||
#include "scene_graph/components/transform.h"
|
||||
#include "scene_graph/node.h"
|
||||
|
||||
AFBCSample::AFBCSample()
|
||||
{
|
||||
// Extension that may be used to query if AFBC is enabled
|
||||
add_device_extension(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME, true);
|
||||
|
||||
auto &config = get_configuration();
|
||||
|
||||
config.insert<vkb::BoolSetting>(0, afbc_enabled, false);
|
||||
config.insert<vkb::BoolSetting>(1, afbc_enabled, true);
|
||||
}
|
||||
|
||||
bool AFBCSample::prepare(const vkb::ApplicationOptions &options)
|
||||
{
|
||||
if (!VulkanSample::prepare(options))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We want AFBC disabled at start-up
|
||||
afbc_enabled = false;
|
||||
recreate_swapchain();
|
||||
|
||||
load_scene("scenes/sponza/Sponza01.gltf");
|
||||
|
||||
auto &camera_node = vkb::add_free_camera(get_scene(), "main_camera", get_render_context().get_surface_extent());
|
||||
camera = &camera_node.get_component<vkb::sg::Camera>();
|
||||
|
||||
vkb::ShaderSource vert_shader("base.vert.spv");
|
||||
vkb::ShaderSource frag_shader("base.frag.spv");
|
||||
auto scene_subpass = std::make_unique<vkb::ForwardSubpass>(get_render_context(), std::move(vert_shader), std::move(frag_shader), get_scene(), *camera);
|
||||
|
||||
auto render_pipeline = std::make_unique<vkb::RenderPipeline>();
|
||||
render_pipeline->add_subpass(std::move(scene_subpass));
|
||||
|
||||
set_render_pipeline(std::move(render_pipeline));
|
||||
|
||||
get_stats().request_stats({vkb::StatIndex::gpu_ext_write_bytes});
|
||||
|
||||
create_gui(*window, &get_stats());
|
||||
|
||||
// Store the start time to calculate rotation
|
||||
start_time = std::chrono::system_clock::now();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AFBCSample::update(float delta_time)
|
||||
{
|
||||
if (afbc_enabled != afbc_enabled_last_value)
|
||||
{
|
||||
recreate_swapchain();
|
||||
|
||||
afbc_enabled_last_value = afbc_enabled;
|
||||
}
|
||||
|
||||
/* Pan the camera back and forth. */
|
||||
auto &camera_transform = camera->get_node()->get_component<vkb::sg::Transform>();
|
||||
|
||||
float rotation_factor = std::chrono::duration<float>(std::chrono::system_clock::now() - start_time).count();
|
||||
|
||||
glm::quat qy = glm::angleAxis(0.003f * sin(rotation_factor * 0.7f), glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
glm::quat orientation = glm::normalize(qy * camera_transform.get_rotation() * glm::angleAxis(0.0f, glm::vec3(1.0f, 0.0f, 0.0f)));
|
||||
camera_transform.set_rotation(orientation);
|
||||
|
||||
VulkanSample::update(delta_time);
|
||||
}
|
||||
|
||||
void AFBCSample::recreate_swapchain()
|
||||
{
|
||||
std::set<VkImageUsageFlagBits> image_usage_flags = {VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT};
|
||||
|
||||
if (!afbc_enabled)
|
||||
{
|
||||
// To force-disable AFBC, set an invalid image usage flag
|
||||
image_usage_flags.insert(VK_IMAGE_USAGE_STORAGE_BIT);
|
||||
}
|
||||
|
||||
get_device().wait_idle();
|
||||
|
||||
get_render_context().update_swapchain(image_usage_flags);
|
||||
}
|
||||
|
||||
void AFBCSample::draw_gui()
|
||||
{
|
||||
get_gui().show_options_window(
|
||||
/* body = */ [this]() {
|
||||
ImGui::Checkbox("Enable AFBC", &afbc_enabled);
|
||||
|
||||
if (get_device().is_extension_enabled(VK_EXT_IMAGE_COMPRESSION_CONTROL_EXTENSION_NAME))
|
||||
{
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("(%s)", vkb::image_compression_flags_to_string(get_render_context().get_swapchain().get_applied_compression()).c_str());
|
||||
}
|
||||
},
|
||||
/* lines = */ 1);
|
||||
}
|
||||
|
||||
std::unique_ptr<vkb::VulkanSampleC> create_afbc()
|
||||
{
|
||||
return std::make_unique<AFBCSample>();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Copyright (c) 2019-2024, Arm Limited and Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 the "License";
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rendering/render_pipeline.h"
|
||||
#include "scene_graph/components/camera.h"
|
||||
#include "timer.h"
|
||||
#include "vulkan_sample.h"
|
||||
|
||||
/**
|
||||
* @brief Using framebuffer compression to reduce bandwidth
|
||||
*/
|
||||
class AFBCSample : public vkb::VulkanSampleC
|
||||
{
|
||||
public:
|
||||
AFBCSample();
|
||||
|
||||
virtual ~AFBCSample() = default;
|
||||
|
||||
virtual bool prepare(const vkb::ApplicationOptions &options) override;
|
||||
|
||||
virtual void update(float delta_time) override;
|
||||
|
||||
private:
|
||||
vkb::sg::Camera *camera{nullptr};
|
||||
|
||||
virtual void draw_gui() override;
|
||||
|
||||
void recreate_swapchain();
|
||||
|
||||
bool afbc_enabled_last_value{false};
|
||||
|
||||
bool afbc_enabled{false};
|
||||
|
||||
std::chrono::system_clock::time_point start_time;
|
||||
};
|
||||
|
||||
std::unique_ptr<vkb::VulkanSampleC> create_afbc();
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 131 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Reference in New Issue
Block a user