From 9c8d03d962b91d52ca1a20ac8af79d165ec95f60 Mon Sep 17 00:00:00 2001 From: "Hector, Tobias" Date: Fri, 22 Aug 2025 11:59:55 +0100 Subject: [PATCH 1/6] Add GLSL_EXT_structured_descriptor_heap --- .../GLSL_EXT_structured_descriptor_heap.txt | 274 ++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 extensions/ext/GLSL_EXT_structured_descriptor_heap.txt diff --git a/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt new file mode 100644 index 0000000..e8aa921 --- /dev/null +++ b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt @@ -0,0 +1,274 @@ +Name + + EXT_structured_descriptor_heap + +Name Strings + + GL_EXT_structured_descriptor_heap + +Contact + + Tobias Hector (tobias.hector 'at' amd.com), AMD + +Notice + + Copyright (c) 2025 The Khronos Group Inc. Copyright terms at + http://www.khronos.org/registry/speccopyright.html + +Status + + Draft + +Version + + Last Modified Date: 2025-09-17 + Revision: 1 + +Dependencies + + This extension can be applied to OpenGL GLSL versions 4.20 + (#version 420) and higher. + + This extension can be applied to OpenGL ES ESSL versions 3.10 + (#version 310) and higher. + + This extension is written against revision 8 of the OpenGL Shading Language + version 4.60, dated August 14, 2023. + + This extension is written against version 1 of GLSL_EXT_descriptor_heap. + + This extension interacts with GLSL_EXT_buffer_reference and + GLSL_EXT_buffer_reference2. + + This extension interacts with GL_KHR_ray_tracing and GL_KHR_ray_query. + +Overview + + This extension document modifies the shader interface to allow declaring + new `resourceheap` and `samplerheap` blocks that enable applications to + pull structured data and descriptors from Vulkan resource and sampler + heaps. + + For example, the following code is now valid: + + ```glsl + resourceheap { + texture2D myTexture; + uint myInteger; + buffer { + uint data; + } myBuffer; + uniform { + uint data; + } myUniformBuffer; + } myResourceHeapView[]; + ``` + + Such code for each element of `myResourceHeapView` will read each member + at an appropriately aligned offset in the resource heap. + Layout of plain-old-data is always performed as if `scalar` layout were + used. + + Mapping to SPIR-V + ----------------- + + The structure is laid out in the same way as any other structure would + be, with the exception that resource variables are laid out using the + `OffsetIdEXT` decoration based on the result of `OpConstantSizeOfEXT` for + various descriptor types, as their sizes are not known until client API + compilation. + + For example, the above declaration would map to the following SPIR-V: + + ```spir-v + // Heap type decorations + OpMemberDecorateIdEXT %heap_t OffsetIdEXT %heap_offset_0 0 + OpMemberDecorateIdEXT %heap_t OffsetIdEXT %heap_offset_1 1 + OpMemberDecorateIdEXT %heap_t OffsetIdEXT %heap_offset_2 2 + OpMemberDecorateIdEXT %heap_t OffsetIdEXT %heap_offset_3 3 + OpDecorateIdEXT %heap_array_t ArrayStrideIdEXT %heap_size_aligned + + // Heap types + %float_t = OpTypeFloat 32 + %texture_t = OpTypeImage %float_t 2D 0 0 0 1 Unknown + %uint_t = OpTypeInt 32 0 + %storage_buffer_t = OpTypeBufferEXT StorageBuffer + %uniform_buffer_t = OpTypeBufferEXT Uniform + %heap_t = OpTypeStruct %texture_t %uint_t %storage_buffer_t %uniform_buffer_t + %buffer_data_t = OpTypeStruct %uint_t + %heap_array_t = OpTypeRuntimeArray %heap_t + + // Heap member sizes + %texture_size = OpConstantSizeOfEXT %texture_t + %uint_size = OpConstant 4 + %buffer_size = OpConstantSizeOfEXT %storage_buffer_t + + // Heap member offsets + %heap_offset_0 = OpConstant %uint_t 0 + %heap_offset_1 = OpSpecConstantOp OpIAdd %uint_t %heap_offset_0 %texture_size + %heap_offset_2 = OpSpecConstantOp OpIAdd %uint_t %heap_offset_1 %uint_size + %heap_offset_3 = OpSpecConstantOp OpIAdd %uint_t %heap_offset_2 %buffer_size + + // Total heap size + %heap_size = OpSpecConstantOp OpIAdd %uint_t %heap_offset_3 %buffer_size + + // Calculate the required heap alignment + %texture_is_bigger = OpSpecConstantOp OpUGreaterThan %boolean_t %texture_size %buffer_size + %resource_size = OpSpecConstantOp OpSelect %uint_t %texture_is_bigger %texture_size %buffer_size + %resource_is_bigger = OpSpecConstantOp OpUGreaterThan %boolean_t %resource_size %uint_size + %heap_alignment = OpSpecConstantOp OpSelect %uint_t %resource_is_bigger %resource_size %uint_size + + // Calculate the aligned size of the heap structure + %heap_count = OpSpecConstantOp OpUDiv %uint_t %heap_size %heap_alignment + %heap_modulo = OpSpecConstantOp OpUMod %uint_t %heap_size %heap_alignment + %heap_modulo_count = OpSpecConstantOp OpUDiv %uint_t %heap_modulo %heap_modulo + %heap_aligned_count = OpSpecConstantOp OpIAdd %uint_t %heap_count %heap_modulo_count + %heap_size_aligned = OpSpecConstantOp OpIMul %uint_t %heap_aligned_count %heap_alignment + ``` + +Modifications to the OpenGL Shading Language Specification, Version 4.60 + + Including the following line in a shader can be used to control the + language features described in this extension: + + #extension GL_EXT_structured_descriptor_heap : + + where is as specified in section 3.3. + + A new preprocessor #define is added: + + #define GL_EXT_structured_descriptor_heap 1 + + +Additions to Chapter 4 of the OpenGL Shading Language Specification +(Variables and Types) + + Modify Section 4.1.9, Arrays + + Replace: + + Except for the last declared member of a shader storage block (see + section “Interface Blocks”) or a descriptor heap declaration (without + set and binding qualifiers), the size of an array must be declared + (explicitly sized) before it is indexed with anything other than a + constant integral expression. + + With: + + Except for the last declared member of a shader storage block (see + section “Interface Blocks”), a resource or sampler heap block, or a + descriptor heap declaration (without set and binding qualifiers), the + size of an array must be declared (explicitly sized) before it is + indexed with anything other than a constant integral expression. + + Add: + + Any resourceheap or samplerheap block may be declared without an + explicit size. + In this case, the effective array size is inferred at run-time from + the size of the data store backing the heap. + Such run-time-sized arrays may be indexed with general integer + expressions. + However, it is a compile-time error to pass them as an argument to a + function or index them with a negative constant expression. + + Modify Section 4.3, Storage Qualifiers + + Add to the table of storage qualifiers: + + |=== + | Storage Qualifier | Meaning + | resourceheap | Value is stored in a resource heap. + Values do not change across the primitive being + processed. + Forms linkage between a shader, API, and the + application. + | samplerheap | Value is stored in a sampler heap. + Values do not change across the primitive being + processed. + Forms linkage between a shader, API, and the + application. + |=== + + Add a new section 4.3.10, Heap Variables + + The `resourceheap` and `samplerheap` qualifiers are used to declare + global interface blocks whose values are stored in the data store of a + resource or sampler heap, respectively, bound through the API. + Heap variables are read-only, with the underlying storage shared among + all active shader invocations. + Arrays of blocks, including unsized arrays, are allowed. + + `resourceheap` blocks may contain plain-old-data variables, buffer and + uniform blocks, image*, texture*, and accelerationStructure* + declarations, and buffer references. + Structures or arrays containing these types are also allowed. + These types may not be nested inside buffer or uniform blocks. + All `resourceheap` blocks are aliases of one another. + + `samplerheap` blocks may contain plain-old-data variables and sampler* + declarations. + Structures or arrays containing these types are also allowed. + All `samplerheap` blocks are aliases of one another. + + + Modify Section 4.4, Layout Qualifiers + + Add to the table of layout qualifiers: + + | Layout | Qualifier | Individual | Block | Block | Allowed | + | Qualifier | Only | Variable | | Member | Interfaces | + |------------------------------------------------------------------------------| + | descriptor_stride = | | | X | | resourceheap | + | | | | | | /samplerheap | + |------------------------------------------------------------------------------| + +Interactions with GL_KHR_ray_query and GL_KHR_ray_tracing + + If both GL_KHR_ray_query and GL_KHR_ray_tracing are not supported, + acceleration structures cannot be specified as heap variables. + + When supported, acceleration structures can be declared in a + `resourceheap` block as follows: + + ```glsl + resourceheap { + accelerationStructureKHR myAccelerationStructure; + } myResourceHeapView[]; + ``` + +Interactions with GLSL_EXT_buffer_reference + + If GLSL_EXT_buffer_reference is not supported, buffer references cannot + be specified as heap variables. + + When supported, buffer references can be declared in a `resourceheap` + block in any of the following manners: + + ```glsl + layout(buffer_reference) buffer ForwardRefType; + + layout(buffer_reference, std430, buffer_reference_align = 16) buffer ConcreteRefType { + ... + }; + + resourceheap { + ForwardRefType forwardRef; + ConcreteRefType concreteRef; + layout(buffer_reference) buffer { + uint data; + } inlineRef; + } myResourceHeapView[]; + + layout(buffer_reference) buffer ForwardRefType { + ... + }; + ``` + + Each of these is accessed as a buffer device address in SPIR-V. + +Revision History + + Rev. Date Author Changes + ---- ----------- -------- ------------------------------------------- + 1 17-Sep-2025 thector Initial revision. From b2cce3fea0f920bd8e744bae6323164baaaf67d0 Mon Sep 17 00:00:00 2001 From: "Hector, Tobias" Date: Thu, 18 Sep 2025 12:32:44 +0100 Subject: [PATCH 2/6] Update spec to tighten up behavior and allow offsets --- .../GLSL_EXT_structured_descriptor_heap.txt | 280 ++++++++++++------ 1 file changed, 197 insertions(+), 83 deletions(-) diff --git a/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt index e8aa921..4a7177f 100644 --- a/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt +++ b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt @@ -40,6 +40,8 @@ Dependencies This extension interacts with GLSL_EXT_buffer_reference and GLSL_EXT_buffer_reference2. + This extension interacts with GL_EXT_scalar_block_layout. + This extension interacts with GL_KHR_ray_tracing and GL_KHR_ray_query. Overview @@ -49,25 +51,56 @@ Overview pull structured data and descriptors from Vulkan resource and sampler heaps. + Each block can also be declared with a variable indicating a byte offset + applied to each lookup, so that different regions of the heap can be used + for different resource types. + For example, the following code is now valid: ```glsl - resourceheap { + layout (constant_id = 0) const uint materialsOffset = 0; + + layout (push_constant) uniform MyPushData { + vec4 someData; + uint someMoreData; + uint buffersOffset; + } myPushData; + + struct MaterialData { texture2D myTexture; - uint myInteger; - buffer { + uniform { uint data; } myBuffer; - uniform { + vec4 data0; + uint data1; + }; + + layout (heap_offset = materialsOffset) resourceheap MaterialHeap { + uint materialCount; + MaterialData materials[]; + } materialHeap; + + layout (heap_offset = myPushData.buffersOffset) resourceheap BufferHeap { + uint bufferCount; + layout (descriptor_stride = 128) buffer { + vec4 data; + } myFirstBuffer; + buffer { uint data; - } myUniformBuffer; - } myResourceHeapView[]; + } myStorageBuffers[]; + } bufferHeap; + + samplerheap SamplerHeap { + sampler samplers[]; + } samplerHeap; ``` - Such code for each element of `myResourceHeapView` will read each member - at an appropriately aligned offset in the resource heap. - Layout of plain-old-data is always performed as if `scalar` layout were - used. + Accessing parts of these heap blocks is performed similarly to buffer + block access, with each element read from an appropriate offset into the + heap. + Layout of data is always as if `scalar` layout were used for a buffer. + The size of resource types in the heap is dependent on the client API, + though can be overridden with the "descriptor_stride" qualifier. Mapping to SPIR-V ----------------- @@ -77,53 +110,60 @@ Overview `OffsetIdEXT` decoration based on the result of `OpConstantSizeOfEXT` for various descriptor types, as their sizes are not known until client API compilation. + This does add some complexity to compilation as various sizes and + alignments must now be calculated when the shader is compiled in the + client API. - For example, the above declaration would map to the following SPIR-V: + For example, the `MaterialData materials[];` declaration would map to the + following SPIR-V: ```spir-v - // Heap type decorations - OpMemberDecorateIdEXT %heap_t OffsetIdEXT %heap_offset_0 0 - OpMemberDecorateIdEXT %heap_t OffsetIdEXT %heap_offset_1 1 - OpMemberDecorateIdEXT %heap_t OffsetIdEXT %heap_offset_2 2 - OpMemberDecorateIdEXT %heap_t OffsetIdEXT %heap_offset_3 3 - OpDecorateIdEXT %heap_array_t ArrayStrideIdEXT %heap_size_aligned - - // Heap types - %float_t = OpTypeFloat 32 - %texture_t = OpTypeImage %float_t 2D 0 0 0 1 Unknown - %uint_t = OpTypeInt 32 0 - %storage_buffer_t = OpTypeBufferEXT StorageBuffer - %uniform_buffer_t = OpTypeBufferEXT Uniform - %heap_t = OpTypeStruct %texture_t %uint_t %storage_buffer_t %uniform_buffer_t - %buffer_data_t = OpTypeStruct %uint_t - %heap_array_t = OpTypeRuntimeArray %heap_t - - // Heap member sizes - %texture_size = OpConstantSizeOfEXT %texture_t - %uint_size = OpConstant 4 - %buffer_size = OpConstantSizeOfEXT %storage_buffer_t - - // Heap member offsets - %heap_offset_0 = OpConstant %uint_t 0 - %heap_offset_1 = OpSpecConstantOp OpIAdd %uint_t %heap_offset_0 %texture_size - %heap_offset_2 = OpSpecConstantOp OpIAdd %uint_t %heap_offset_1 %uint_size - %heap_offset_3 = OpSpecConstantOp OpIAdd %uint_t %heap_offset_2 %buffer_size - - // Total heap size - %heap_size = OpSpecConstantOp OpIAdd %uint_t %heap_offset_3 %buffer_size - - // Calculate the required heap alignment - %texture_is_bigger = OpSpecConstantOp OpUGreaterThan %boolean_t %texture_size %buffer_size - %resource_size = OpSpecConstantOp OpSelect %uint_t %texture_is_bigger %texture_size %buffer_size - %resource_is_bigger = OpSpecConstantOp OpUGreaterThan %boolean_t %resource_size %uint_size - %heap_alignment = OpSpecConstantOp OpSelect %uint_t %resource_is_bigger %resource_size %uint_size - - // Calculate the aligned size of the heap structure - %heap_count = OpSpecConstantOp OpUDiv %uint_t %heap_size %heap_alignment - %heap_modulo = OpSpecConstantOp OpUMod %uint_t %heap_size %heap_alignment - %heap_modulo_count = OpSpecConstantOp OpUDiv %uint_t %heap_modulo %heap_modulo - %heap_aligned_count = OpSpecConstantOp OpIAdd %uint_t %heap_count %heap_modulo_count - %heap_size_aligned = OpSpecConstantOp OpIMul %uint_t %heap_aligned_count %heap_alignment + // Offset and Stride decorations + OpMemberDecorateIdEXT %materials_t OffsetIdEXT %offset_0 0 + OpMemberDecorateIdEXT %materials_t OffsetIdEXT %offset_1 1 + OpMemberDecorateIdEXT %materials_t OffsetIdEXT %offset_2 2 + OpMemberDecorateIdEXT %materials_t OffsetIdEXT %offset_3 3 + OpDecorateIdEXT %materials_t_array_t ArrayStrideIdEXT %materials_size + + // Types + %float_t = OpTypeFloat 32 + %texture_t = OpTypeImage %float_t 2D 0 0 0 1 Unknown + %buffer_t = OpTypeBufferEXT Uniform + %vec4_t = OpTypeVector %float_t 4 + %uint_t = OpTypeInt 32 0 + %materials_t = OpTypeStruct %texture_t %buffer_t %vec4_t %uint_t + %materials_array_t = OpTypeRuntimeArray %materials_t + + // Member sizes/alignments + %texture_size = OpConstantSizeOfEXT %texture_t + %buffer_size = OpConstantSizeOfEXT %uniform_buffer_t + %vec4_size = OpConstant 16 + %vec4_alignment = OpConstant 4 // Only type with alignment != size known to the shader + %uint_size = OpConstant 4 + + // MaterialData structure alignment + %texture_bigger = OpSpecConstantOp OpUGreaterThan %boolean_t %texture_size %buffer_size + %texture_buffer_align = OpSpecConstantOp OpSelect %uint_t %member0_bigger %texture_size %buffer_size + %plain_old_data_align = OpConstant 4 // We know the largest alignment of POD statically + %texture_buffer_bigger = OpSpecConstantOp OpUGreaterThan %boolean_t %texture_buffer_size %plain_old_data_align + %materials_alignment = OpSpecConstantOp OpSelect %uint_t %texture_buffer_bigger %texture_buffer_align %plain_old_data_align + + // Member offsets + %offset_0 = OpConstant %uint_t 0 + %offset_1_unaligned = OpSpecConstantOp OpIAdd %uint_t %offset_0 %texture_size + %offset_1_padding = OpSpecConstantOp OpUMod %buffer_size %offset_1_unaligned + %offset_1 = OpSpecConstantOp OpIAdd %uint_t %offset_1_unaligned %offset_1_padding + %offset_2_unaligned = OpSpecConstantOp OpIAdd %uint_t %offset_1 %buffer_size + %offset_2_padding = OpSpecConstantOp OpUMod %vec4_alignment %offset_2_unaligned + %offset_2 = OpSpecConstantOp OpIAdd %uint_t %offset_2_unaligned %offset_2_padding + %offset_3_unaligned = OpSpecConstantOp OpIAdd %uint_t %offset_2 %vec4_size + %offset_3_padding = OpSpecConstantOp OpUMod %uint_size %offset_3_unaligned + %offset_3 = OpSpecConstantOp OpIAdd %uint_t %offset_3_unaligned %offset_3_padding + + // Size of the MaterialData type + %materials_size_unaligned = OpSpecConstantOp OpIAdd %uint_t %offset_3 %uint_size + %materials_padding = OpSpecConstantOp OpUMod %materials_alignment %materials_size_unaligned + %materials_size = OpSpecConstantOp OpIAdd %materials_size_unaligned %materials_padding ``` Modifications to the OpenGL Shading Language Specification, Version 4.60 @@ -155,22 +195,13 @@ Additions to Chapter 4 of the OpenGL Shading Language Specification With: - Except for the last declared member of a shader storage block (see - section “Interface Blocks”), a resource or sampler heap block, or a - descriptor heap declaration (without set and binding qualifiers), the - size of an array must be declared (explicitly sized) before it is - indexed with anything other than a constant integral expression. - - Add: - - Any resourceheap or samplerheap block may be declared without an - explicit size. - In this case, the effective array size is inferred at run-time from - the size of the data store backing the heap. - Such run-time-sized arrays may be indexed with general integer - expressions. - However, it is a compile-time error to pass them as an argument to a - function or index them with a negative constant expression. + Except for the last declared member of a shader storage, resource + heap, or sampler heap block (see section “Interface Blocks” and “Heap + Blocks”), or a descriptor heap declaration (without set and binding + qualifiers), the size of an array must be declared (explicitly sized) + before it is indexed with anything other than a constant integral + expression. + Modify Section 4.3, Storage Qualifiers @@ -190,38 +221,121 @@ Additions to Chapter 4 of the OpenGL Shading Language Specification application. |=== - Add a new section 4.3.10, Heap Variables + Add a new section 4.3.10, Heap Blocks The `resourceheap` and `samplerheap` qualifiers are used to declare global interface blocks whose values are stored in the data store of a resource or sampler heap, respectively, bound through the API. Heap variables are read-only, with the underlying storage shared among all active shader invocations. - Arrays of blocks, including unsized arrays, are allowed. + Arrays of blocks are not allowed. `resourceheap` blocks may contain plain-old-data variables, buffer and uniform blocks, image*, texture*, and accelerationStructure* declarations, and buffer references. Structures or arrays containing these types are also allowed. These types may not be nested inside buffer or uniform blocks. - All `resourceheap` blocks are aliases of one another. + All `resourceheap` blocks are aliased on top of the same heap, but may + be placed at different offsets using `heap_offset`. `samplerheap` blocks may contain plain-old-data variables and sampler* declarations. Structures or arrays containing these types are also allowed. - All `samplerheap` blocks are aliases of one another. + All `samplerheap` blocks are aliased on top of the same heap, but may + be placed at different offsets using `heap_offset`. Modify Section 4.4, Layout Qualifiers Add to the table of layout qualifiers: - | Layout | Qualifier | Individual | Block | Block | Allowed | - | Qualifier | Only | Variable | | Member | Interfaces | - |------------------------------------------------------------------------------| - | descriptor_stride = | | | X | | resourceheap | - | | | | | | /samplerheap | - |------------------------------------------------------------------------------| + |----------------------------------------------------------------------------------| + | Layout | Qualifier | Individual | Block | Block | Allowed | + | Qualifier | Only | Variable | | Member | Interfaces | + |----------------------------------------------------------------------------------| + | descriptor_stride = | | | | X | resourceheap | + | | | | | | /samplerheap | + |----------------------------------------------------------------------------------| + | heap_offset = | | | X | | resourceheap | + | | | | | | /samplerheap | + |----------------------------------------------------------------------------------| + | buffer_reference | X | | | buffer | resourceheap | + | | | | | block only | /samplerheap | + |----------------------------------------------------------------------------------| + | buffer_reference = | X | | | buffer | resourceheap | + | | | | | block only | /samplerheap | + |----------------------------------------------------------------------------------| + | row_major | X | | | matrix | resourceheap | + | column_major | | | | only | /samplerheap | + |----------------------------------------------------------------------------------| + | offset = | | | | X | resourceheap | + | | | | | | /samplerheap | + |----------------------------------------------------------------------------------| + | shared | X | | | buffer or | resourceheap | + | packed | | | | uniform | /samplerheap | + | std140 | | | | blocks | | + | std430 | | | | only | | + | scalar | | | | | | + |----------------------------------------------------------------------------------| + + Modify Section 4.4.5, Uniform and Shader Storage Block Layout Qualifiers + + Add to the end of the section: + + When targeting Vulkan, any uniform or shader storage block declared + inside a `resourceheap` block is read as a descriptor from the + resource heap, with its elements read from that descriptor. + Subsequent members of the resourceheap block are offset by the size + of the descriptor in the client API, unless otherwise specified by + `descriptor_stride`. + + Modify Section 4.4.6, Opaque Uniform Layout Qualifiers + + Add to the end of the section: + + When targeting Vulkan, any image*, texture*, and + accelerationStructure* variable inside a `resourceheap` block is read + as a descriptor from the resource heap, and any sampler* variable + inside a `samplerheap` block is read as a descriptor from the sampler + heap. + Subsequent members of the resourceheap or samplerheap block are + offset by the size of the descriptor in the client API, unless + otherwise specified by `descriptor_stride`. + + Add Section 4.4.10, Resource and Sampler Heap Layout Qualifiers + + Resource and sampler heap blocks are only available when targeting + Vulkan. + + Resource and sampler heap blocks can be declared with the following + layout qualifiers: + + _layout-qualifier-id_: + *heap_offset* = _layout-qualifier-value_ + *heap_offset* = __variable_identifier__ + + The `heap_offset` qualifier specifies an offset in bytes to be added + to any heap access, enabling shaders to access different regions of + a heap in different ways through multiple declarations. + + Unlike other layout qualifiers, this allows the offset to be + specified as either a literal or any global read-only variable value, + such that the offset can come through things like push constants. + There is no guarantee made about when the variable is read, so care + should be taken to avoid data races if the value is sourced from a + buffer. + + It is a compile-time error if a variable is specified that can be + written to during the lifetime of the shader. + + Members of such heap blocks can be qualified with the `offset=`, + `row_major`, `column_major`, `buffer_reference`, and + `buffer_reference_align` qualifiers in the same manner as if they + were declared in a buffer block. + + `buffer` and `uniform` blocks declared inside a heap block can be + qualified with `shared`, `packed`, `std430`, `std140`, and `scalar` + qualifiers just as if they were declared outside of a resource heap. Interactions with GL_KHR_ray_query and GL_KHR_ray_tracing @@ -229,12 +343,12 @@ Interactions with GL_KHR_ray_query and GL_KHR_ray_tracing acceleration structures cannot be specified as heap variables. When supported, acceleration structures can be declared in a - `resourceheap` block as follows: + `resourceheap` block: ```glsl resourceheap { accelerationStructureKHR myAccelerationStructure; - } myResourceHeapView[]; + } myResourceHeapView; ``` Interactions with GLSL_EXT_buffer_reference @@ -258,7 +372,7 @@ Interactions with GLSL_EXT_buffer_reference layout(buffer_reference) buffer { uint data; } inlineRef; - } myResourceHeapView[]; + } myResourceHeapView; layout(buffer_reference) buffer ForwardRefType { ... From 058b6f8e0754b22899e11826555aa7670f7c5456 Mon Sep 17 00:00:00 2001 From: "Hector, Tobias" Date: Thu, 22 Jan 2026 13:19:24 +0000 Subject: [PATCH 3/6] Add extension to readme --- README.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/README.adoc b/README.adoc index 979c602..3d9361c 100755 --- a/README.adoc +++ b/README.adoc @@ -108,3 +108,4 @@ that do not live in the Khronos registries for OpenGL or OpenGL ES. - link:{repo}/ext/GLSL_EXT_long_vector.txt[GL_EXT_long_vector] - link:{repo}/ext/GLSL_EXT_uniform_buffer_unsized_array.txt[GL_EXT_uniform_buffer_unsized_array] - link:{repo}/nv/GLSL_NV_push_constant_bank.txt[GL_NV_push_constant_bank] +- link:{repo}/ext/GLSL_EXT_structured_descriptor_heap.txt[GL_EXT_structured_descriptor_heap] From c600324e41db9ee47ce3fa1a84f844d59c2fe67f Mon Sep 17 00:00:00 2001 From: "Hector, Tobias" Date: Thu, 23 Apr 2026 11:12:27 +0100 Subject: [PATCH 4/6] Add "buffer type" declarations, replacing unworkable inline blocks Also allow buffer references in sampler heaps --- .../GLSL_EXT_structured_descriptor_heap.txt | 79 +++++++++++++------ 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt index 4a7177f..4933163 100644 --- a/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt +++ b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt @@ -55,6 +55,10 @@ Overview applied to each lookup, so that different regions of the heap can be used for different resource types. + There is also a new "buffer_type" qualifier for `uniform` and `buffer` + block declarations, allowing their types to be embedded in the resource + heap. + For example, the following code is now valid: ```glsl @@ -66,11 +70,13 @@ Overview uint buffersOffset; } myPushData; + layout(buffer_type, scalar) uniform MyUbo { + uint data; + }; + struct MaterialData { texture2D myTexture; - uniform { - uint data; - } myBuffer; + MyUbo myBuffer; vec4 data0; uint data1; }; @@ -79,15 +85,19 @@ Overview uint materialCount; MaterialData materials[]; } materialHeap; - + + layout(buffer_type, scalar) buffer MyFirstSsbo { + vec4 data; + }; + + layout(buffer_type, scalar) buffer MySecondSsbo { + uint data; + }; + layout (heap_offset = myPushData.buffersOffset) resourceheap BufferHeap { uint bufferCount; - layout (descriptor_stride = 128) buffer { - vec4 data; - } myFirstBuffer; - buffer { - uint data; - } myStorageBuffers[]; + layout (descriptor_size = 128) MyFirstSsbo myFirstBuffer; + buffer MySecondSsbo myStorageBuffers[]; } bufferHeap; samplerheap SamplerHeap { @@ -98,9 +108,10 @@ Overview Accessing parts of these heap blocks is performed similarly to buffer block access, with each element read from an appropriate offset into the heap. - Layout of data is always as if `scalar` layout were used for a buffer. + Layout of data in a resource heap is always as if `scalar` layout were + used for a buffer. The size of resource types in the heap is dependent on the client API, - though can be overridden with the "descriptor_stride" qualifier. + though can be overridden with the "descriptor_size" qualifier. Mapping to SPIR-V ----------------- @@ -110,7 +121,7 @@ Overview `OffsetIdEXT` decoration based on the result of `OpConstantSizeOfEXT` for various descriptor types, as their sizes are not known until client API compilation. - This does add some complexity to compilation as various sizes and + This does add some complexity to compilation, as various sizes and alignments must now be calculated when the shader is compiled in the client API. @@ -221,6 +232,24 @@ Additions to Chapter 4 of the OpenGL Shading Language Specification application. |=== + Add to the end of section 4.3.9 (Interface Blocks) + + Uniform and shader storage blocks can be declared with the "buffer_type" + layout qualifier, which alters their behavior to create an opaque buffer + type that describes a block (as if the block were a structure type). The + buffer type's name is the block name. There must be no instance name. + Set and binding layouts as well as qualifiers like coherent and volatile + don't apply to the buffer type, and can instead be applied to instances + of the buffer type. + + The buffer type can be used to declare block members in the + `resourceheap` interface, either directly or nested as part of a + `struct` type. + + The field selector ( . ) operator is used to access members through a + buffer type instance. This is the only operator allowed to operate on + buffer types. + Add a new section 4.3.10, Heap Blocks The `resourceheap` and `samplerheap` qualifiers are used to declare @@ -230,16 +259,15 @@ Additions to Chapter 4 of the OpenGL Shading Language Specification all active shader invocations. Arrays of blocks are not allowed. - `resourceheap` blocks may contain plain-old-data variables, buffer and - uniform blocks, image*, texture*, and accelerationStructure* - declarations, and buffer references. + `resourceheap` blocks may contain plain-old-data variables, buffer types, + image*, texture*, and accelerationStructure* declarations, and buffer + references. Structures or arrays containing these types are also allowed. - These types may not be nested inside buffer or uniform blocks. All `resourceheap` blocks are aliased on top of the same heap, but may be placed at different offsets using `heap_offset`. - `samplerheap` blocks may contain plain-old-data variables and sampler* - declarations. + `samplerheap` blocks may contain plain-old-data variables, sampler* + declarations, and buffer references. Structures or arrays containing these types are also allowed. All `samplerheap` blocks are aliased on top of the same heap, but may be placed at different offsets using `heap_offset`. @@ -253,7 +281,10 @@ Additions to Chapter 4 of the OpenGL Shading Language Specification | Layout | Qualifier | Individual | Block | Block | Allowed | | Qualifier | Only | Variable | | Member | Interfaces | |----------------------------------------------------------------------------------| - | descriptor_stride = | | | | X | resourceheap | + | buffer_type | X | | X | | uniform | + | | | | | | /buffer | + |----------------------------------------------------------------------------------| + | descriptor_size = | | | | X | resourceheap | | | | | | | /samplerheap | |----------------------------------------------------------------------------------| | heap_offset = | | | X | | resourceheap | @@ -279,6 +310,8 @@ Additions to Chapter 4 of the OpenGL Shading Language Specification |----------------------------------------------------------------------------------| Modify Section 4.4.5, Uniform and Shader Storage Block Layout Qualifiers + + Add "buffer_type" to the layout-qualifier-id grammar rule. Add to the end of the section: @@ -287,7 +320,7 @@ Additions to Chapter 4 of the OpenGL Shading Language Specification resource heap, with its elements read from that descriptor. Subsequent members of the resourceheap block are offset by the size of the descriptor in the client API, unless otherwise specified by - `descriptor_stride`. + `descriptor_size`. Modify Section 4.4.6, Opaque Uniform Layout Qualifiers @@ -300,7 +333,7 @@ Additions to Chapter 4 of the OpenGL Shading Language Specification heap. Subsequent members of the resourceheap or samplerheap block are offset by the size of the descriptor in the client API, unless - otherwise specified by `descriptor_stride`. + otherwise specified by `descriptor_size`. Add Section 4.4.10, Resource and Sampler Heap Layout Qualifiers @@ -385,4 +418,6 @@ Revision History Rev. Date Author Changes ---- ----------- -------- ------------------------------------------- + 2 23-Apr-2026 thector Add buffer types instead of inline blocks. + Allow buffer references in sampler heap. 1 17-Sep-2025 thector Initial revision. From 0c4b2ca162787d1641115a3fac1dc96cf08fd06e Mon Sep 17 00:00:00 2001 From: "Hector, Tobias" Date: Thu, 23 Apr 2026 17:02:00 +0100 Subject: [PATCH 5/6] Fix SPIR-V mapping typos --- .../GLSL_EXT_structured_descriptor_heap.txt | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt index 4933163..fd044e7 100644 --- a/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt +++ b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt @@ -146,35 +146,35 @@ Overview %materials_array_t = OpTypeRuntimeArray %materials_t // Member sizes/alignments - %texture_size = OpConstantSizeOfEXT %texture_t - %buffer_size = OpConstantSizeOfEXT %uniform_buffer_t - %vec4_size = OpConstant 16 - %vec4_alignment = OpConstant 4 // Only type with alignment != size known to the shader - %uint_size = OpConstant 4 + %texture_size = OpConstantSizeOfEXT %uint_t %texture_t + %buffer_size = OpConstantSizeOfEXT %uint_t %uniform_buffer_t + %vec4_size = OpConstant %uint_t 16 + %vec4_alignment = OpConstant %uint_t 4 // Only type with alignment != size known to the shader + %uint_size = OpConstant %uint_t 4 // MaterialData structure alignment %texture_bigger = OpSpecConstantOp OpUGreaterThan %boolean_t %texture_size %buffer_size %texture_buffer_align = OpSpecConstantOp OpSelect %uint_t %member0_bigger %texture_size %buffer_size - %plain_old_data_align = OpConstant 4 // We know the largest alignment of POD statically + %plain_old_data_align = OpConstant %uint_t 4 // We know the largest alignment of POD statically %texture_buffer_bigger = OpSpecConstantOp OpUGreaterThan %boolean_t %texture_buffer_size %plain_old_data_align %materials_alignment = OpSpecConstantOp OpSelect %uint_t %texture_buffer_bigger %texture_buffer_align %plain_old_data_align // Member offsets %offset_0 = OpConstant %uint_t 0 %offset_1_unaligned = OpSpecConstantOp OpIAdd %uint_t %offset_0 %texture_size - %offset_1_padding = OpSpecConstantOp OpUMod %buffer_size %offset_1_unaligned + %offset_1_padding = OpSpecConstantOp OpUMod %uint_t %offset_1_unaligned %buffer_size %offset_1 = OpSpecConstantOp OpIAdd %uint_t %offset_1_unaligned %offset_1_padding %offset_2_unaligned = OpSpecConstantOp OpIAdd %uint_t %offset_1 %buffer_size - %offset_2_padding = OpSpecConstantOp OpUMod %vec4_alignment %offset_2_unaligned + %offset_2_padding = OpSpecConstantOp OpUMod %uint_t %offset_2_unaligned %vec4_alignment %offset_2 = OpSpecConstantOp OpIAdd %uint_t %offset_2_unaligned %offset_2_padding %offset_3_unaligned = OpSpecConstantOp OpIAdd %uint_t %offset_2 %vec4_size - %offset_3_padding = OpSpecConstantOp OpUMod %uint_size %offset_3_unaligned + %offset_3_padding = OpSpecConstantOp OpUMod %uint_t %offset_3_unaligned %uint_size %offset_3 = OpSpecConstantOp OpIAdd %uint_t %offset_3_unaligned %offset_3_padding // Size of the MaterialData type %materials_size_unaligned = OpSpecConstantOp OpIAdd %uint_t %offset_3 %uint_size - %materials_padding = OpSpecConstantOp OpUMod %materials_alignment %materials_size_unaligned - %materials_size = OpSpecConstantOp OpIAdd %materials_size_unaligned %materials_padding + %materials_padding = OpSpecConstantOp OpUMod %uint_t %materials_size_unaligned %materials_alignment + %materials_size = OpSpecConstantOp OpIAdd %uint_t %materials_size_unaligned %materials_padding ``` Modifications to the OpenGL Shading Language Specification, Version 4.60 From 14f717dd9c3930f47be974aacefa42340e945a61 Mon Sep 17 00:00:00 2001 From: Tobski Date: Mon, 18 May 2026 12:16:49 +0100 Subject: [PATCH 6/6] Update extensions/ext/GLSL_EXT_structured_descriptor_heap.txt Co-authored-by: Spencer Fricke <115671160+spencer-lunarg@users.noreply.github.com> --- extensions/ext/GLSL_EXT_structured_descriptor_heap.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt index fd044e7..9cba15e 100644 --- a/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt +++ b/extensions/ext/GLSL_EXT_structured_descriptor_heap.txt @@ -130,7 +130,7 @@ Overview ```spir-v // Offset and Stride decorations - OpMemberDecorateIdEXT %materials_t OffsetIdEXT %offset_0 0 + OpMemberDecorateIdEXT %materials_t 0 OffsetIdEXT %offset_0 OpMemberDecorateIdEXT %materials_t OffsetIdEXT %offset_1 1 OpMemberDecorateIdEXT %materials_t OffsetIdEXT %offset_2 2 OpMemberDecorateIdEXT %materials_t OffsetIdEXT %offset_3 3