Skip to content

Commit 0af559d

Browse files
committed
Adding the possibility to disable external compression
1 parent 8290b66 commit 0af559d

11 files changed

+883
-55
lines changed

layer_gpu_support/README_LAYER.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,16 +175,28 @@ allocated and handled by the driver.
175175
per component setting. Images that do not support a fixed rate compression
176176
level that meets this bit rate requirement will be left at the original
177177
application setting.
178+
* If `disable_external_compression` option is set to `1` , all the possible measures
179+
are taken so that external compression is disabled. In case is not possible to garantuee
180+
that external compression is used, the layer will return VK_ERROR_FEATURE_NOT_PRESENT.
181+
It should be set to `2` only if the application is not presenting, and is targeting vkCreateImage.
182+
Option `2` is an heuristic, compression could be disabled accidentally on internal images,
183+
and is also possible that it misses external images, if they lack COLOR_ATTACHMENT_BIT.
184+
Feel free to tune the heuristic to your specific use case.
178185

179186
#### Configuration options
180187

181188
```jsonc
182189
"framebuffer": {
183190
"disable_compression": false, // Disable all use of compression
184191
"force_default_compression": false, // Force driver default compression
185-
"force_fixed_rate_compression": 0 // Force use of fixed rate compression as close
192+
"force_fixed_rate_compression": 0, // Force use of fixed rate compression as close
186193
// to this bits-per-channel as possible, but
187194
// no lower (0 = do not force)
195+
"disable_external_compression": 0, // 0 = Perform no operation, passthrough
196+
// 1 = Force disable external compression, requires image presentation
197+
// 2 = Force disable external compression also without
198+
// presentation, requires only the use of vkCreateImage
199+
// WARNING! Currently implemented as an heuristic
188200
}
189201
```
190202

layer_gpu_support/layer_config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
"framebuffer": {
4141
"disable_compression": false,
4242
"force_default_compression": false,
43-
"force_fixed_rate_compression": 0
43+
"force_fixed_rate_compression": 0,
44+
"disable_external_compression": 0
4445
}
4546
}

layer_gpu_support/source/CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ add_library(
4747
layer_config.cpp
4848
layer_device_functions_dispatch.cpp
4949
layer_device_functions_image.cpp
50+
layer_device_functions_swapchain.cpp
51+
layer_device_functions_allocate_memory.cpp
5052
layer_device_functions_pipelines.cpp
5153
layer_device_functions_queue.cpp
5254
layer_device_functions_render_pass.cpp
5355
layer_device_functions_trace_rays.cpp
54-
layer_device_functions_transfer.cpp)
56+
layer_device_functions_transfer.cpp
57+
layer_instance_functions_get_physical_properties.cpp)
5558

5659
target_include_directories(
5760
${VK_LAYER} PRIVATE

layer_gpu_support/source/layer_config.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ void LayerConfig::parse_framebuffer_options(const json& config)
167167
bool disable_all_compression = framebuffer.at("disable_compression");
168168
bool default_all_compression = framebuffer.at("force_default_compression");
169169
uint64_t force_fixed_rate_compression = framebuffer.at("force_fixed_rate_compression");
170+
int disable_external_compression = framebuffer.at("disable_external_compression");
170171

171172
// Apply precedence ladder
172173
if (disable_all_compression)
@@ -228,13 +229,16 @@ void LayerConfig::parse_framebuffer_options(const json& config)
228229
conf_framebuffer_disable_compression = disable_all_compression;
229230
conf_framebuffer_force_default_compression = default_all_compression;
230231
conf_framebuffer_force_fixed_rate_compression = fixed_rate_mask;
232+
conf_disable_external_compression = disable_external_compression;
231233

232234
LAYER_LOG("Layer framebuffer configuration");
233235
LAYER_LOG("===============================");
234236
LAYER_LOG(" - Disable framebuffer compression: %d", conf_framebuffer_disable_compression);
235237
LAYER_LOG(" - Force default framebuffer compression: %d", conf_framebuffer_force_default_compression);
236238
LAYER_LOG(" - Force fixed rate compression: %lu bpc", force_fixed_rate_compression);
237239
LAYER_LOG(" - Force fixed rate compression mask: %08x", conf_framebuffer_force_fixed_rate_compression);
240+
LAYER_LOG(" - Force disable external compression: %d", conf_disable_external_compression);
241+
238242
}
239243

240244
/* See header for documentation. */
@@ -430,3 +434,9 @@ uint32_t LayerConfig::framebuffer_force_fixed_rate_compression() const
430434
{
431435
return conf_framebuffer_force_fixed_rate_compression;
432436
}
437+
438+
/* See header for documentation. */
439+
int LayerConfig::disable_external_compression() const
440+
{
441+
return conf_disable_external_compression;
442+
}

layer_gpu_support/source/layer_config.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,15 @@ class LayerConfig
165165
*/
166166
uint32_t framebuffer_force_fixed_rate_compression() const;
167167

168+
169+
/**
170+
* @brief External compression control for swapchains/images.
171+
* 0 = passthrough (default),
172+
* 1 = strip compression on external images,
173+
* 2 = strip compression on external images even without presentation, using heuristic (no garantuee!)
174+
*/
175+
int disable_external_compression() const;
176+
168177
private:
169178
/**
170179
* @brief Parse the configuration options for the feature module.
@@ -315,4 +324,17 @@ class LayerConfig
315324
* If zero, then no force is set and default compression will be used.
316325
*/
317326
uint32_t conf_framebuffer_force_fixed_rate_compression {0};
327+
328+
/**
329+
* @brief Forces disabling external compression.
330+
*
331+
* 0 = Perform no operation, passthrough.
332+
* 1 = Force disable external compression, requires image presentation.
333+
* 2 = Force disable external compression also without.
334+
* presentation, requires only the use of vkCreateImage.
335+
*
336+
* WARNING! Currently implemented as an heuristic.
337+
*/
338+
int conf_disable_external_compression {0};
339+
318340
};

layer_gpu_support/source/layer_device_functions.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,3 +369,23 @@ VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateImage<user_tag>(VkDevice device,
369369
const VkImageCreateInfo* pCreateInfo,
370370
const VkAllocationCallbacks* pAllocator,
371371
VkImage* pImage);
372+
373+
374+
// Functions for swapchains
375+
376+
/* See Vulkan API for documentation. */
377+
template <>
378+
VKAPI_ATTR VkResult VKAPI_CALL layer_vkCreateSwapchainKHR<user_tag>(VkDevice device,
379+
const VkSwapchainCreateInfoKHR* pCreateInfo,
380+
const VkAllocationCallbacks* pAllocator,
381+
VkSwapchainKHR* pSwapchain
382+
);
383+
384+
// Functions for external DMA-buf
385+
386+
template <>
387+
VKAPI_ATTR VkResult VKAPI_CALL layer_vkAllocateMemory<user_tag>(VkDevice device,
388+
const VkMemoryAllocateInfo* pAllocateInfo,
389+
const VkAllocationCallbacks* pAllocator,
390+
VkDeviceMemory* pMemory
391+
);
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* SPDX-License-Identifier: MIT
3+
* ----------------------------------------------------------------------------
4+
* Copyright (c) 2025 Arm Limited
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to
8+
* deal in the Software without restriction, including without limitation the
9+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10+
* sell copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22+
* IN THE SOFTWARE.
23+
* ----------------------------------------------------------------------------
24+
*/
25+
#include <vulkan/utility/vk_safe_struct.hpp>
26+
#include <vulkan/utility/vk_struct_helper.hpp>
27+
28+
#include "device.hpp"
29+
#include "framework/device_dispatch_table.hpp"
30+
31+
#include <bit>
32+
#include <mutex>
33+
34+
extern std::mutex g_vulkanLock;
35+
36+
/**
37+
* @brief Intercept vkAllocateMemory and hard-fail on external memory imports
38+
* that could mandate external compression; otherwise pass through to the driver.
39+
*
40+
* @details Scans @p pAllocateInfo->pNext for import structs. If it finds
41+
* VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID or
42+
* VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR with
43+
* VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, it returns
44+
* VK_ERROR_FEATURE_NOT_PRESENT to preserve the guarantee that
45+
* external compression is not used. When no such imports are present, the
46+
* call is forwarded unchanged.
47+
*
48+
* @param device Logical device allocating the memory.
49+
* @param pAllocateInfo Allocation parameters; its pNext chain is inspected
50+
* for import info.
51+
* @param pAllocator Optional allocation callbacks.
52+
* @param pMemory Receives the allocated device memory on success.
53+
*
54+
* @return VK_SUCCESS on success, or a VkResult propagated from the driver.
55+
* Returns VK_ERROR_FEATURE_NOT_PRESENT when disallowed external
56+
* import types are detected in the pNext chain.
57+
*
58+
* @note This is a strict policy check; additional import structures may be
59+
* rejected in the future to maintain the compression-off guarantee.
60+
*/
61+
62+
/* See Vulkan API for documentation. */
63+
template <>
64+
VKAPI_ATTR VkResult VKAPI_CALL layer_vkAllocateMemory<user_tag>(
65+
VkDevice device,
66+
const VkMemoryAllocateInfo* pAllocateInfo,
67+
const VkAllocationCallbacks* pAllocator,
68+
VkDeviceMemory* pMemory
69+
) {
70+
71+
LAYER_TRACE(__func__);
72+
73+
//fprintf(stderr, "[libGPULayers] HIT %s\n", __func__); fflush(stderr);
74+
75+
std::unique_lock<std::mutex> lock { g_vulkanLock };
76+
auto* layer = Device::retrieve(device);
77+
const auto& config = layer->instance->config;
78+
79+
int disable_external_compression = config.disable_external_compression();
80+
81+
//absolute passthrough if feature is off
82+
if (disable_external_compression == 0) {
83+
lock.unlock();
84+
return layer->driver.vkAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
85+
}
86+
87+
// Scan pNext for imports that we cannot sanitize -> hard-fail to keep the 100% guarantee that we can disable external compression
88+
for (const VkBaseInStructure* n = (const VkBaseInStructure*)pAllocateInfo->pNext; n; n = n->pNext) {
89+
90+
if (n->sType == VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID) {
91+
printf("[libGPULayers] vkAllocateMemory: AHardwareBuffer IMPORT detected. "
92+
"Cannot guarantee external compression is disabled (buffer created outside Vulkan). Failing by policy.\n");
93+
return VK_ERROR_FEATURE_NOT_PRESENT;
94+
}
95+
96+
if (n->sType == VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR) {
97+
const VkImportMemoryFdInfoKHR* fdInfo = (const VkImportMemoryFdInfoKHR*)n;
98+
if (fdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT) {
99+
printf("[libGPULayers] vkAllocateMemory: DMA-BUF memory IMPORT detected (fd=%d). "
100+
"Cannot guarantee external compression (DRM modifier may imply compression). Failing by policy.\n",
101+
fdInfo->fd);
102+
return VK_ERROR_FEATURE_NOT_PRESENT;
103+
}
104+
}
105+
106+
}
107+
108+
// Release the lock to call into the driver
109+
lock.unlock();
110+
return layer->driver.vkAllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
111+
112+
}

0 commit comments

Comments
 (0)