|
| 1 | +# Extension support in a layer |
| 2 | + |
| 3 | +It might be useful for some layers to implement an extension, such as |
| 4 | +`VK_EXT_frame_boundary`, even if the underlying driver does not support it. |
| 5 | +This page explains the general approach that needs to be taken, and the |
| 6 | +specific API modifications that need to be applied for specific extensions. |
| 7 | + |
| 8 | +The core libGPULayers framework allows you to expose additional extensions via |
| 9 | +the default `vkEnumerate*ExtensionProperties()` implementation, but per-layer |
| 10 | +code must implement the API modifications in any other functions as needed. |
| 11 | + |
| 12 | +## Exposing a new extension |
| 13 | + |
| 14 | +New extensions are advertised to applications by adding the extension string to |
| 15 | +the list returned by `vkEnumerate*ExtensionProperties()`. This functionality |
| 16 | +is provided in the common framework default functions. Layer implementations |
| 17 | +add the new extension information that they want to expose to either: |
| 18 | + |
| 19 | +* `Instance::injectedInstanceExtensions` for instance extensions. |
| 20 | +* `Instance::injectedDeviceExtensions` for device extensions. |
| 21 | + |
| 22 | +Device extensions will be removed from this list if we can detect that the |
| 23 | +underlying device already supports them, which means we can just pass through |
| 24 | +rather than emulating support. |
| 25 | + |
| 26 | +### Handling extended API entry points |
| 27 | + |
| 28 | +All entrypoints that are touched by an extension need to be intercepted with a |
| 29 | +`user_tag` version of that function, which will implement the functionality |
| 30 | +that the layer requires. |
| 31 | + |
| 32 | +If the driver beneath the layer actually supports the extension, the extended |
| 33 | +API parameters can be passed down to the driver without modification. This |
| 34 | +scenario can be detected by checking that the extension name is no longer in |
| 35 | +the `injectedExtensions` list, although the layer will probably want to cache |
| 36 | +this check to reduce performance overhead. |
| 37 | + |
| 38 | +If the driver beneath the layer does not support the extension, the extended |
| 39 | +API parameters should be rewritten to remove the extension before passing down |
| 40 | +to the driver. User structure inputs to the Vulkan API are usually marked as |
| 41 | +`const`, so we must take a safe-struct copy which we can modify and then pass |
| 42 | +that copy to the driver. |
| 43 | + |
| 44 | +Note that Vulkan specifies that components must ignore structures in the |
| 45 | +`pNext` chain that they do not understand: |
| 46 | + |
| 47 | +> Any component of the implementation (the loader, any enabled layers, and |
| 48 | +> drivers) must skip over, without processing (other than reading the `sType` |
| 49 | +> and `pNext` members) any extending structures in the chain not defined by |
| 50 | +> core versions or extensions supported by that component. |
| 51 | +
|
| 52 | +Any extension structures can therefore be left in-situ when being emulated, but |
| 53 | +any other API parameter modifications must be unpicked to hide the emulation. |
| 54 | + |
| 55 | +## Common extension notes |
| 56 | + |
| 57 | +This section is a set of brief notes about extensions that we have implemented, |
| 58 | +summarizing the changes needed and referencing where you can find an example |
| 59 | +of the changes if you need something similar. |
| 60 | + |
| 61 | +### VK_EXT_frame_boundary |
| 62 | + |
| 63 | +This extension allows applications to annotate arbitrary submit calls to |
| 64 | +indicate which frame the submitted work belongs to, instead of relying on |
| 65 | +`vkQueuePresent()`. This can be useful for multi-threaded applications, |
| 66 | +where CPU processing for frames can overlap, and for applications which |
| 67 | +do not have frames, but that want to use tools such as RenderDoc that |
| 68 | +require them. |
| 69 | + |
| 70 | +The `layer_gpu_timeline` layer is an example of a layer exposing this |
| 71 | +extension using emulation on devices that do not support it. |
| 72 | + |
| 73 | +#### Exposing extension |
| 74 | + |
| 75 | +Adding exposure handling: |
| 76 | + |
| 77 | +* Add `VK_EXT_frame_boundary` to device extension list. |
| 78 | +* Populate the `VkPhysicalDeviceFrameBoundary` in the |
| 79 | + `VkPhysicalDeviceFeatures2.pNext` list returned by |
| 80 | + `vkGetPhysicalDeviceFeatures2()`, forcing the value to `VK_TRUE`, if the |
| 81 | + extension is "supported" but feature-disabled by the driver. |
| 82 | +* Query `VkPhysicalDeviceFrameBoundary` in `VkDeviceCreateInfo.pNext` to see if |
| 83 | + application enabled the extension. |
| 84 | + |
| 85 | +#### Implementing extension |
| 86 | + |
| 87 | +Adding implementation handling: |
| 88 | + |
| 89 | +* Add `VkFrameBoundaryEXT` extension struct handling to: |
| 90 | + * `vkQueueSubmit()` |
| 91 | + * `vkQueueSubmit2()` |
| 92 | + * `vkQueuePresent()` |
| 93 | + * `vkQueueBindSparse()` |
| 94 | + |
| 95 | +#### Implementation notes |
| 96 | + |
| 97 | +Most applications using this that I have seen are using it to demarcate frames |
| 98 | +when using a single submitting render thread for off-screen rendering or |
| 99 | +compute use cases that do not use `vkQueuePresent()`. In these systems just |
| 100 | +detecting the frame boundary flag in the extension structure passed to a queue |
| 101 | +submit is enough, and how we would use `vkQueuePresent()` to do the same |
| 102 | +without this extension. |
| 103 | + |
| 104 | +It is possible for applications to have multiple concurrent frames being |
| 105 | +submitted in an overlapping manner, which can be handled by tagging work with |
| 106 | +the frame ID found in the extension structure for each `vkQueue*()` call. This |
| 107 | +will require downstream data handling to cope with overlapping frame |
| 108 | +submissions, which most of our layers do not handle, as it is rarely |
| 109 | +encountered. |
| 110 | + |
| 111 | +- - - |
| 112 | + |
| 113 | +_Copyright © 2025, Arm Limited and contributors._ |
0 commit comments