diff --git a/reference/opt/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp.vk b/reference/opt/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp.vk index 82ebb960..771d0496 100644 --- a/reference/opt/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp.vk +++ b/reference/opt/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp.vk @@ -3,7 +3,7 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer Block; -layout(buffer_reference, std430) buffer Block +layout(buffer_reference, buffer_reference_align = 4, std430) buffer Block { float v; }; diff --git a/reference/opt/shaders/vulkan/comp/buffer-reference-atomic.nocompat.vk.comp.vk b/reference/opt/shaders/vulkan/comp/buffer-reference-atomic.nocompat.vk.comp.vk new file mode 100644 index 00000000..f5907d3e --- /dev/null +++ b/reference/opt/shaders/vulkan/comp/buffer-reference-atomic.nocompat.vk.comp.vk @@ -0,0 +1,28 @@ +#version 450 +#extension GL_EXT_buffer_reference : require +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(buffer_reference) buffer Bar; +layout(buffer_reference) buffer Foo; +layout(buffer_reference, buffer_reference_align = 8, std430) buffer Bar +{ + uint a; + uint b; + Foo foo; +}; + +layout(buffer_reference, std430) buffer Foo +{ + uint v; +}; + +layout(push_constant, std430) uniform Push +{ + Bar bar; +} _13; + +void main() +{ + uint _24 = atomicAdd(_13.bar.b, 1u); +} + diff --git a/reference/opt/shaders/vulkan/comp/buffer-reference-base-alignment-promote.nocompat.vk.comp.vk b/reference/opt/shaders/vulkan/comp/buffer-reference-base-alignment-promote.nocompat.vk.comp.vk new file mode 100644 index 00000000..a5a66b19 --- /dev/null +++ b/reference/opt/shaders/vulkan/comp/buffer-reference-base-alignment-promote.nocompat.vk.comp.vk @@ -0,0 +1,28 @@ +#version 450 +#extension GL_EXT_buffer_reference : require +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(buffer_reference) buffer Bar; +layout(buffer_reference) buffer Foo; +layout(buffer_reference, buffer_reference_align = 8, std430) buffer Bar +{ + uint a; + uint b; + Foo foo; +}; + +layout(buffer_reference, std430) buffer Foo +{ + uint v; +}; + +layout(push_constant, std430) uniform Push +{ + Bar bar; +} _15; + +void main() +{ + uint _31 = atomicAdd(_15.bar.a, _15.bar.b); +} + diff --git a/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast-uvec2-2.nocompat.invalid.vk.comp.vk b/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast-uvec2-2.nocompat.invalid.vk.comp.vk index 53c3d21c..20a4f1b4 100644 --- a/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast-uvec2-2.nocompat.invalid.vk.comp.vk +++ b/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast-uvec2-2.nocompat.invalid.vk.comp.vk @@ -4,7 +4,7 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer PtrInt; -layout(buffer_reference, std430) buffer PtrInt +layout(buffer_reference, buffer_reference_align = 4, std430) buffer PtrInt { int value; }; diff --git a/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast-uvec2.nocompat.vk.comp.vk b/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast-uvec2.nocompat.vk.comp.vk index 3956304f..5cf6e2df 100644 --- a/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast-uvec2.nocompat.vk.comp.vk +++ b/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast-uvec2.nocompat.vk.comp.vk @@ -4,7 +4,7 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer PtrInt; -layout(buffer_reference, std430) buffer PtrInt +layout(buffer_reference, buffer_reference_align = 16, std430) buffer PtrInt { int value; }; diff --git a/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast.nocompat.vk.comp.vk b/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast.nocompat.vk.comp.vk index 5752f81b..8923d21d 100644 --- a/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast.nocompat.vk.comp.vk +++ b/reference/opt/shaders/vulkan/comp/buffer-reference-bitcast.nocompat.vk.comp.vk @@ -4,12 +4,12 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer PtrUint; layout(buffer_reference) buffer PtrInt; -layout(buffer_reference, std430) buffer PtrUint +layout(buffer_reference, buffer_reference_align = 4, std430) buffer PtrUint { uint value; }; -layout(buffer_reference, std430) buffer PtrInt +layout(buffer_reference, buffer_reference_align = 16, std430) buffer PtrInt { int value; }; diff --git a/reference/opt/shaders/vulkan/comp/buffer-reference-decorations.nocompat.vk.comp.vk b/reference/opt/shaders/vulkan/comp/buffer-reference-decorations.nocompat.vk.comp.vk index 5b3cf49e..b7e88062 100644 --- a/reference/opt/shaders/vulkan/comp/buffer-reference-decorations.nocompat.vk.comp.vk +++ b/reference/opt/shaders/vulkan/comp/buffer-reference-decorations.nocompat.vk.comp.vk @@ -5,17 +5,17 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer RO; layout(buffer_reference) buffer RW; layout(buffer_reference) buffer WO; -layout(buffer_reference, std430) readonly buffer RO +layout(buffer_reference, buffer_reference_align = 16, std430) readonly buffer RO { vec4 v[]; }; -layout(buffer_reference, std430) restrict buffer RW +layout(buffer_reference, buffer_reference_align = 16, std430) restrict buffer RW { vec4 v[]; }; -layout(buffer_reference, std430) coherent writeonly buffer WO +layout(buffer_reference, buffer_reference_align = 16, std430) coherent writeonly buffer WO { vec4 v[]; }; diff --git a/reference/opt/shaders/vulkan/comp/buffer-reference.nocompat.vk.comp.vk b/reference/opt/shaders/vulkan/comp/buffer-reference.nocompat.vk.comp.vk index b30330cf..de0964b1 100644 --- a/reference/opt/shaders/vulkan/comp/buffer-reference.nocompat.vk.comp.vk +++ b/reference/opt/shaders/vulkan/comp/buffer-reference.nocompat.vk.comp.vk @@ -4,7 +4,7 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer Node; -layout(buffer_reference, std430) buffer Node +layout(buffer_reference, buffer_reference_align = 16, std430) buffer Node { layout(offset = 0) int value; layout(offset = 16) Node next; diff --git a/reference/shaders-no-opt/asm/comp/buffer-reference-aliased-block-name.nocompat.vk.asm.comp.vk b/reference/shaders-no-opt/asm/comp/buffer-reference-aliased-block-name.nocompat.vk.asm.comp.vk index cabf8352..12581cc3 100644 --- a/reference/shaders-no-opt/asm/comp/buffer-reference-aliased-block-name.nocompat.vk.asm.comp.vk +++ b/reference/shaders-no-opt/asm/comp/buffer-reference-aliased-block-name.nocompat.vk.asm.comp.vk @@ -5,17 +5,17 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer Alias; layout(buffer_reference) buffer _6; layout(buffer_reference) buffer _7; -layout(buffer_reference, std430) readonly buffer Alias +layout(buffer_reference, buffer_reference_align = 16, std430) readonly buffer Alias { vec4 v[]; }; -layout(buffer_reference, std430) restrict buffer _6 +layout(buffer_reference, buffer_reference_align = 16, std430) restrict buffer _6 { vec4 v[]; }; -layout(buffer_reference, std430) coherent writeonly buffer _7 +layout(buffer_reference, buffer_reference_align = 16, std430) coherent writeonly buffer _7 { vec4 v[]; }; diff --git a/reference/shaders-no-opt/asm/comp/buffer-reference-pointer-to-pod-in-buffer.asm.nocompat.vk.comp.vk b/reference/shaders-no-opt/asm/comp/buffer-reference-pointer-to-pod-in-buffer.asm.nocompat.vk.comp.vk new file mode 100644 index 00000000..06e620d2 --- /dev/null +++ b/reference/shaders-no-opt/asm/comp/buffer-reference-pointer-to-pod-in-buffer.asm.nocompat.vk.comp.vk @@ -0,0 +1,19 @@ +#version 450 +#extension GL_EXT_buffer_reference : require +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(buffer_reference, buffer_reference_align = 8) buffer uvec4Pointer +{ + uvec4 value; +}; + +layout(push_constant, std430) uniform Push +{ + uvec4Pointer ptr; +} _4; + +void main() +{ + _4.ptr.value = uvec4(1u, 2u, 3u, 4u); +} + diff --git a/reference/shaders-no-opt/asm/comp/buffer-reference-pointer-to-unused-pod-in-buffer.asm.nocompat.vk.comp.vk b/reference/shaders-no-opt/asm/comp/buffer-reference-pointer-to-unused-pod-in-buffer.asm.nocompat.vk.comp.vk new file mode 100644 index 00000000..44427de8 --- /dev/null +++ b/reference/shaders-no-opt/asm/comp/buffer-reference-pointer-to-unused-pod-in-buffer.asm.nocompat.vk.comp.vk @@ -0,0 +1,13 @@ +#version 450 +#extension GL_EXT_buffer_reference : require +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(buffer_reference) buffer uvec4Pointer +{ + uvec4 value; +}; + +void main() +{ +} + diff --git a/reference/shaders-no-opt/asm/comp/buffer-reference-synthesized-pointer-2.asm.nocompat.vk.comp.vk b/reference/shaders-no-opt/asm/comp/buffer-reference-synthesized-pointer-2.asm.nocompat.vk.comp.vk index 02889319..432c0ad7 100644 --- a/reference/shaders-no-opt/asm/comp/buffer-reference-synthesized-pointer-2.asm.nocompat.vk.comp.vk +++ b/reference/shaders-no-opt/asm/comp/buffer-reference-synthesized-pointer-2.asm.nocompat.vk.comp.vk @@ -3,7 +3,7 @@ #extension GL_EXT_buffer_reference : require layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; -layout(buffer_reference) buffer uintPointer +layout(buffer_reference, buffer_reference_align = 4) buffer uintPointer { uint value; }; diff --git a/reference/shaders-no-opt/asm/comp/buffer-reference-synthesized-pointer.asm.nocompat.vk.comp.vk b/reference/shaders-no-opt/asm/comp/buffer-reference-synthesized-pointer.asm.nocompat.vk.comp.vk index 9553199b..95b97fca 100644 --- a/reference/shaders-no-opt/asm/comp/buffer-reference-synthesized-pointer.asm.nocompat.vk.comp.vk +++ b/reference/shaders-no-opt/asm/comp/buffer-reference-synthesized-pointer.asm.nocompat.vk.comp.vk @@ -3,7 +3,7 @@ #extension GL_EXT_buffer_reference : require layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; -layout(buffer_reference) buffer uint0_Pointer +layout(buffer_reference, buffer_reference_align = 4) buffer uint0_Pointer { uint value[]; }; diff --git a/reference/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp.vk b/reference/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp.vk index 82ebb960..771d0496 100644 --- a/reference/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp.vk +++ b/reference/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp.vk @@ -3,7 +3,7 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer Block; -layout(buffer_reference, std430) buffer Block +layout(buffer_reference, buffer_reference_align = 4, std430) buffer Block { float v; }; diff --git a/reference/shaders/vulkan/comp/buffer-reference-atomic.nocompat.vk.comp.vk b/reference/shaders/vulkan/comp/buffer-reference-atomic.nocompat.vk.comp.vk new file mode 100644 index 00000000..f5907d3e --- /dev/null +++ b/reference/shaders/vulkan/comp/buffer-reference-atomic.nocompat.vk.comp.vk @@ -0,0 +1,28 @@ +#version 450 +#extension GL_EXT_buffer_reference : require +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(buffer_reference) buffer Bar; +layout(buffer_reference) buffer Foo; +layout(buffer_reference, buffer_reference_align = 8, std430) buffer Bar +{ + uint a; + uint b; + Foo foo; +}; + +layout(buffer_reference, std430) buffer Foo +{ + uint v; +}; + +layout(push_constant, std430) uniform Push +{ + Bar bar; +} _13; + +void main() +{ + uint _24 = atomicAdd(_13.bar.b, 1u); +} + diff --git a/reference/shaders/vulkan/comp/buffer-reference-base-alignment-promote.nocompat.vk.comp.vk b/reference/shaders/vulkan/comp/buffer-reference-base-alignment-promote.nocompat.vk.comp.vk new file mode 100644 index 00000000..9cd3d3e5 --- /dev/null +++ b/reference/shaders/vulkan/comp/buffer-reference-base-alignment-promote.nocompat.vk.comp.vk @@ -0,0 +1,29 @@ +#version 450 +#extension GL_EXT_buffer_reference : require +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(buffer_reference) buffer Bar; +layout(buffer_reference) buffer Foo; +layout(buffer_reference, buffer_reference_align = 8, std430) buffer Bar +{ + uint a; + uint b; + Foo foo; +}; + +layout(buffer_reference, std430) buffer Foo +{ + uint v; +}; + +layout(push_constant, std430) uniform Push +{ + Bar bar; +} _15; + +void main() +{ + uint v = _15.bar.b; + uint _31 = atomicAdd(_15.bar.a, v); +} + diff --git a/reference/shaders/vulkan/comp/buffer-reference-bitcast-uvec2-2.nocompat.invalid.vk.comp.vk b/reference/shaders/vulkan/comp/buffer-reference-bitcast-uvec2-2.nocompat.invalid.vk.comp.vk index 53c3d21c..20a4f1b4 100644 --- a/reference/shaders/vulkan/comp/buffer-reference-bitcast-uvec2-2.nocompat.invalid.vk.comp.vk +++ b/reference/shaders/vulkan/comp/buffer-reference-bitcast-uvec2-2.nocompat.invalid.vk.comp.vk @@ -4,7 +4,7 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer PtrInt; -layout(buffer_reference, std430) buffer PtrInt +layout(buffer_reference, buffer_reference_align = 4, std430) buffer PtrInt { int value; }; diff --git a/reference/shaders/vulkan/comp/buffer-reference-bitcast-uvec2.nocompat.vk.comp.vk b/reference/shaders/vulkan/comp/buffer-reference-bitcast-uvec2.nocompat.vk.comp.vk index 3956304f..5cf6e2df 100644 --- a/reference/shaders/vulkan/comp/buffer-reference-bitcast-uvec2.nocompat.vk.comp.vk +++ b/reference/shaders/vulkan/comp/buffer-reference-bitcast-uvec2.nocompat.vk.comp.vk @@ -4,7 +4,7 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer PtrInt; -layout(buffer_reference, std430) buffer PtrInt +layout(buffer_reference, buffer_reference_align = 16, std430) buffer PtrInt { int value; }; diff --git a/reference/shaders/vulkan/comp/buffer-reference-bitcast.nocompat.vk.comp.vk b/reference/shaders/vulkan/comp/buffer-reference-bitcast.nocompat.vk.comp.vk index 5752f81b..8923d21d 100644 --- a/reference/shaders/vulkan/comp/buffer-reference-bitcast.nocompat.vk.comp.vk +++ b/reference/shaders/vulkan/comp/buffer-reference-bitcast.nocompat.vk.comp.vk @@ -4,12 +4,12 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer PtrUint; layout(buffer_reference) buffer PtrInt; -layout(buffer_reference, std430) buffer PtrUint +layout(buffer_reference, buffer_reference_align = 4, std430) buffer PtrUint { uint value; }; -layout(buffer_reference, std430) buffer PtrInt +layout(buffer_reference, buffer_reference_align = 16, std430) buffer PtrInt { int value; }; diff --git a/reference/shaders/vulkan/comp/buffer-reference-decorations.nocompat.vk.comp.vk b/reference/shaders/vulkan/comp/buffer-reference-decorations.nocompat.vk.comp.vk index 5b3cf49e..b7e88062 100644 --- a/reference/shaders/vulkan/comp/buffer-reference-decorations.nocompat.vk.comp.vk +++ b/reference/shaders/vulkan/comp/buffer-reference-decorations.nocompat.vk.comp.vk @@ -5,17 +5,17 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer RO; layout(buffer_reference) buffer RW; layout(buffer_reference) buffer WO; -layout(buffer_reference, std430) readonly buffer RO +layout(buffer_reference, buffer_reference_align = 16, std430) readonly buffer RO { vec4 v[]; }; -layout(buffer_reference, std430) restrict buffer RW +layout(buffer_reference, buffer_reference_align = 16, std430) restrict buffer RW { vec4 v[]; }; -layout(buffer_reference, std430) coherent writeonly buffer WO +layout(buffer_reference, buffer_reference_align = 16, std430) coherent writeonly buffer WO { vec4 v[]; }; diff --git a/reference/shaders/vulkan/comp/buffer-reference.nocompat.vk.comp.vk b/reference/shaders/vulkan/comp/buffer-reference.nocompat.vk.comp.vk index e2297411..19239278 100644 --- a/reference/shaders/vulkan/comp/buffer-reference.nocompat.vk.comp.vk +++ b/reference/shaders/vulkan/comp/buffer-reference.nocompat.vk.comp.vk @@ -4,7 +4,7 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; layout(buffer_reference) buffer Node; -layout(buffer_reference, std430) buffer Node +layout(buffer_reference, buffer_reference_align = 16, std430) buffer Node { layout(offset = 0) int value; layout(offset = 16) Node next; diff --git a/shaders-no-opt/asm/comp/buffer-reference-pointer-to-pod-in-buffer.asm.nocompat.vk.comp b/shaders-no-opt/asm/comp/buffer-reference-pointer-to-pod-in-buffer.asm.nocompat.vk.comp new file mode 100644 index 00000000..8fda30e1 --- /dev/null +++ b/shaders-no-opt/asm/comp/buffer-reference-pointer-to-pod-in-buffer.asm.nocompat.vk.comp @@ -0,0 +1,44 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 25 +; Schema: 0 + OpCapability Shader + OpCapability PhysicalStorageBufferAddresses + OpExtension "SPV_EXT_physical_storage_buffer" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel PhysicalStorageBuffer64 GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpSource GLSL 450 + OpSourceExtension "GL_EXT_buffer_reference" + OpName %main "main" + OpName %Push "Push" + OpMemberName %Push 0 "ptr" + OpName %_ "" + OpMemberDecorate %Push 0 Offset 0 + OpDecorate %Push Block + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v4uint = OpTypeVector %uint 4 +%_ptr_PhysicalStorageBuffer_uintPtr = OpTypePointer PhysicalStorageBuffer %v4uint + %Push = OpTypeStruct %_ptr_PhysicalStorageBuffer_uintPtr +%_ptr_PushConstant_Push = OpTypePointer PushConstant %Push + %_ = OpVariable %_ptr_PushConstant_Push PushConstant + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 +%_ptr_PushConstant__ptr_PhysicalStorageBuffer_uintPtr = OpTypePointer PushConstant %_ptr_PhysicalStorageBuffer_uintPtr + %uint_1 = OpConstant %uint 1 + %uint_2 = OpConstant %uint 2 + %uint_3 = OpConstant %uint 3 + %uint_4 = OpConstant %uint 4 + %22 = OpConstantComposite %v4uint %uint_1 %uint_2 %uint_3 %uint_4 +%_ptr_PhysicalStorageBuffer_v4uint = OpTypePointer PhysicalStorageBuffer %v4uint + %main = OpFunction %void None %3 + %5 = OpLabel + %16 = OpAccessChain %_ptr_PushConstant__ptr_PhysicalStorageBuffer_uintPtr %_ %int_0 + %17 = OpLoad %_ptr_PhysicalStorageBuffer_uintPtr %16 + OpStore %17 %22 Aligned 8 + OpReturn + OpFunctionEnd diff --git a/shaders-no-opt/asm/comp/buffer-reference-pointer-to-unused-pod-in-buffer.asm.nocompat.vk.comp b/shaders-no-opt/asm/comp/buffer-reference-pointer-to-unused-pod-in-buffer.asm.nocompat.vk.comp new file mode 100644 index 00000000..d7ca03f6 --- /dev/null +++ b/shaders-no-opt/asm/comp/buffer-reference-pointer-to-unused-pod-in-buffer.asm.nocompat.vk.comp @@ -0,0 +1,44 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 10 +; Bound: 25 +; Schema: 0 + OpCapability Shader + OpCapability PhysicalStorageBufferAddresses + OpExtension "SPV_EXT_physical_storage_buffer" + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel PhysicalStorageBuffer64 GLSL450 + OpEntryPoint GLCompute %main "main" + OpExecutionMode %main LocalSize 1 1 1 + OpSource GLSL 450 + OpSourceExtension "GL_EXT_buffer_reference" + OpName %main "main" + OpName %Push "Push" + OpMemberName %Push 0 "ptr" + OpName %_ "" + OpMemberDecorate %Push 0 Offset 0 + OpDecorate %Push Block + %void = OpTypeVoid + %3 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %v4uint = OpTypeVector %uint 4 +%_ptr_PhysicalStorageBuffer_uintPtr = OpTypePointer PhysicalStorageBuffer %v4uint + %Push = OpTypeStruct %_ptr_PhysicalStorageBuffer_uintPtr +%_ptr_PushConstant_Push = OpTypePointer PushConstant %Push + %_ = OpVariable %_ptr_PushConstant_Push PushConstant + %int = OpTypeInt 32 1 + %int_0 = OpConstant %int 0 +%_ptr_PushConstant__ptr_PhysicalStorageBuffer_uintPtr = OpTypePointer PushConstant %_ptr_PhysicalStorageBuffer_uintPtr + %uint_1 = OpConstant %uint 1 + %uint_2 = OpConstant %uint 2 + %uint_3 = OpConstant %uint 3 + %uint_4 = OpConstant %uint 4 + %22 = OpConstantComposite %v4uint %uint_1 %uint_2 %uint_3 %uint_4 +%_ptr_PhysicalStorageBuffer_v4uint = OpTypePointer PhysicalStorageBuffer %v4uint + %main = OpFunction %void None %3 + %5 = OpLabel + ;%16 = OpAccessChain %_ptr_PushConstant__ptr_PhysicalStorageBuffer_uintPtr %_ %int_0 + ;%17 = OpLoad %_ptr_PhysicalStorageBuffer_uintPtr %16 + ; OpStore %17 %22 Aligned 8 + OpReturn + OpFunctionEnd diff --git a/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp b/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp index a1da941f..f0421b29 100644 --- a/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp +++ b/shaders/vulkan/comp/array-of-buffer-reference.nocompat.vk.comp @@ -2,7 +2,7 @@ #extension GL_EXT_buffer_reference : require layout(local_size_x = 1) in; -layout(buffer_reference) buffer Block +layout(buffer_reference, buffer_reference_align = 4) buffer Block { float v; }; diff --git a/shaders/vulkan/comp/buffer-reference-atomic.nocompat.vk.comp b/shaders/vulkan/comp/buffer-reference-atomic.nocompat.vk.comp new file mode 100644 index 00000000..cf0a8e49 --- /dev/null +++ b/shaders/vulkan/comp/buffer-reference-atomic.nocompat.vk.comp @@ -0,0 +1,24 @@ +#version 450 +#extension GL_EXT_buffer_reference : require + +layout(buffer_reference) buffer Foo +{ + uint v; +}; + +layout(buffer_reference, buffer_reference_align = 8) buffer Bar +{ + uint a; + uint b; + Foo foo; +}; + +layout(push_constant) uniform Push +{ + Bar bar; +}; + +void main() +{ + atomicAdd(bar.b, 1u); +} diff --git a/shaders/vulkan/comp/buffer-reference-base-alignment-promote.nocompat.vk.comp b/shaders/vulkan/comp/buffer-reference-base-alignment-promote.nocompat.vk.comp new file mode 100644 index 00000000..41b44519 --- /dev/null +++ b/shaders/vulkan/comp/buffer-reference-base-alignment-promote.nocompat.vk.comp @@ -0,0 +1,25 @@ +#version 450 +#extension GL_EXT_buffer_reference : require + +layout(buffer_reference) buffer Foo +{ + uint v; +}; + +layout(buffer_reference, buffer_reference_align = 8) buffer Bar +{ + uint a; + uint b; + Foo foo; +}; + +layout(push_constant) uniform Push +{ + Bar bar; +}; + +void main() +{ + uint v = bar.b; + atomicAdd(bar.a, v); +} diff --git a/spirv_cross.cpp b/spirv_cross.cpp index 99b69ad9..07fdb946 100644 --- a/spirv_cross.cpp +++ b/spirv_cross.cpp @@ -4749,31 +4749,181 @@ Compiler::PhysicalStorageBufferPointerHandler::PhysicalStorageBufferPointerHandl { } -bool Compiler::PhysicalStorageBufferPointerHandler::handle(Op op, const uint32_t *args, uint32_t) +Compiler::PhysicalBlockMeta *Compiler::PhysicalStorageBufferPointerHandler::find_block_meta(uint32_t id) const { - if (op == OpConvertUToPtr || op == OpBitcast) + auto chain_itr = access_chain_to_physical_block.find(id); + if (chain_itr != access_chain_to_physical_block.end()) + return chain_itr->second; + else + return nullptr; +} + +void Compiler::PhysicalStorageBufferPointerHandler::mark_aligned_access(uint32_t id, const uint32_t *args, uint32_t length) +{ + uint32_t mask = *args; + args++; + length--; + if (length && (mask & MemoryAccessVolatileMask) != 0) { - auto &type = compiler.get(args[0]); - if (type.storage == StorageClassPhysicalStorageBufferEXT && type.pointer && type.pointer_depth == 1) + args++; + length--; + } + + if (length && (mask & MemoryAccessAlignedMask) != 0) + { + uint32_t alignment = *args; + auto *meta = find_block_meta(id); + + // This makes the assumption that the application does not rely on insane edge cases like: + // Bind buffer with ADDR = 8, use block offset of 8 bytes, load/store with 16 byte alignment. + // If we emit the buffer with alignment = 16 here, the first element at offset = 0 should + // actually have alignment of 8 bytes, but this is too theoretical and awkward to support. + // We could potentially keep track of any offset in the access chain, but it's + // practically impossible for high level compilers to emit code like that, + // so deducing overall alignment requirement based on maximum observed Alignment value is probably fine. + if (meta && alignment > meta->alignment) + meta->alignment = alignment; + } +} + +bool Compiler::PhysicalStorageBufferPointerHandler::type_is_bda_block_entry(uint32_t type_id) const +{ + auto &type = compiler.get(type_id); + return type.storage == StorageClassPhysicalStorageBufferEXT && type.pointer && + type.pointer_depth == 1 && !compiler.type_is_array_of_pointers(type); +} + +uint32_t Compiler::PhysicalStorageBufferPointerHandler::get_minimum_scalar_alignment(const SPIRType &type) const +{ + if (type.storage == spv::StorageClassPhysicalStorageBufferEXT) + return 8; + else if (type.basetype == SPIRType::Struct) + { + uint32_t alignment = 0; + for (auto &member_type : type.member_types) { - // If we need to cast to a pointer type which is not a block, we might need to synthesize ourselves - // a block type which wraps this POD type. - if (type.basetype != SPIRType::Struct) - types.insert(args[0]); + uint32_t member_align = get_minimum_scalar_alignment(compiler.get(member_type)); + if (member_align > alignment) + alignment = member_align; } + return alignment; + } + else + return type.width / 8; +} + +void Compiler::PhysicalStorageBufferPointerHandler::setup_meta_chain(uint32_t type_id, uint32_t var_id) +{ + if (type_is_bda_block_entry(type_id)) + { + auto &meta = physical_block_type_meta[type_id]; + access_chain_to_physical_block[var_id] = &meta; + + auto &type = compiler.get(type_id); + if (type.basetype != SPIRType::Struct) + non_block_types.insert(type_id); + + if (meta.alignment == 0) + meta.alignment = get_minimum_scalar_alignment(compiler.get_pointee_type(type)); + } +} + +bool Compiler::PhysicalStorageBufferPointerHandler::handle(Op op, const uint32_t *args, uint32_t length) +{ + // When a BDA pointer comes to life, we need to keep a mapping of SSA ID -> type ID for the pointer type. + // For every load and store, we'll need to be able to look up the type ID being accessed and mark any alignment + // requirements. + switch (op) + { + case OpConvertUToPtr: + case OpBitcast: + case OpCompositeExtract: + // Extract can begin a new chain if we had a struct or array of pointers as input. + // We don't begin chains before we have a pure scalar pointer. + setup_meta_chain(args[0], args[1]); + break; + + case OpAccessChain: + case OpInBoundsAccessChain: + case OpPtrAccessChain: + case OpCopyObject: + { + auto itr = access_chain_to_physical_block.find(args[2]); + if (itr != access_chain_to_physical_block.end()) + access_chain_to_physical_block[args[1]] = itr->second; + break; + } + + case OpLoad: + { + setup_meta_chain(args[0], args[1]); + if (length >= 4) + mark_aligned_access(args[2], args + 3, length - 3); + break; + } + + case OpStore: + { + if (length >= 3) + mark_aligned_access(args[0], args + 2, length - 2); + break; + } + + default: + break; } return true; } +uint32_t Compiler::PhysicalStorageBufferPointerHandler::get_base_non_block_type_id(uint32_t type_id) const +{ + auto *type = &compiler.get(type_id); + while (type->pointer && + type->storage == StorageClassPhysicalStorageBufferEXT && + !type_is_bda_block_entry(type_id)) + { + type_id = type->parent_type; + type = &compiler.get(type_id); + } + + assert(type_is_bda_block_entry(type_id)); + return type_id; +} + +void Compiler::PhysicalStorageBufferPointerHandler::analyze_non_block_types_from_block(const SPIRType &type) +{ + for (auto &member : type.member_types) + { + auto &subtype = compiler.get(member); + if (subtype.basetype != SPIRType::Struct && subtype.pointer && + subtype.storage == spv::StorageClassPhysicalStorageBufferEXT) + { + non_block_types.insert(get_base_non_block_type_id(member)); + } + else if (subtype.basetype == SPIRType::Struct && !subtype.pointer) + analyze_non_block_types_from_block(subtype); + } +} + void Compiler::analyze_non_block_pointer_types() { PhysicalStorageBufferPointerHandler handler(*this); traverse_all_reachable_opcodes(get(ir.default_entry_point), handler); - physical_storage_non_block_pointer_types.reserve(handler.types.size()); - for (auto type : handler.types) + + // Analyze any block declaration we have to make. It might contain + // physical pointers to POD types which we never used, and thus never added to the list. + // We'll need to add those pointer types to the set of types we declare. + ir.for_each_typed_id([&](uint32_t, SPIRType &type) { + if (has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock)) + handler.analyze_non_block_types_from_block(type); + }); + + physical_storage_non_block_pointer_types.reserve(handler.non_block_types.size()); + for (auto type : handler.non_block_types) physical_storage_non_block_pointer_types.push_back(type); sort(begin(physical_storage_non_block_pointer_types), end(physical_storage_non_block_pointer_types)); + physical_storage_type_to_alignment = move(handler.physical_block_type_meta); } bool Compiler::InterlockedResourceAccessPrepassHandler::handle(Op op, const uint32_t *, uint32_t) diff --git a/spirv_cross.hpp b/spirv_cross.hpp index 27308601..d8967963 100644 --- a/spirv_cross.hpp +++ b/spirv_cross.hpp @@ -1010,15 +1010,32 @@ protected: uint32_t write_count = 0; }; + struct PhysicalBlockMeta + { + uint32_t alignment = 0; + }; + struct PhysicalStorageBufferPointerHandler : OpcodeHandler { explicit PhysicalStorageBufferPointerHandler(Compiler &compiler_); bool handle(spv::Op op, const uint32_t *args, uint32_t length) override; Compiler &compiler; - std::unordered_set types; + + std::unordered_set non_block_types; + std::unordered_map physical_block_type_meta; + std::unordered_map access_chain_to_physical_block; + + void mark_aligned_access(uint32_t id, const uint32_t *args, uint32_t length); + PhysicalBlockMeta *find_block_meta(uint32_t id) const; + bool type_is_bda_block_entry(uint32_t type_id) const; + void setup_meta_chain(uint32_t type_id, uint32_t var_id); + uint32_t get_minimum_scalar_alignment(const SPIRType &type) const; + void analyze_non_block_types_from_block(const SPIRType &type); + uint32_t get_base_non_block_type_id(uint32_t type_id) const; }; void analyze_non_block_pointer_types(); SmallVector physical_storage_non_block_pointer_types; + std::unordered_map physical_storage_type_to_alignment; void analyze_variable_scope(SPIRFunction &function, AnalyzeVariableScopeAccessHandler &handler); void find_function_local_luts(SPIRFunction &function, const AnalyzeVariableScopeAccessHandler &handler, diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index 61acda6a..9578502c 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -2171,8 +2171,9 @@ void CompilerGLSL::emit_buffer_block_legacy(const SPIRVariable &var) statement(""); } -void CompilerGLSL::emit_buffer_reference_block(SPIRType &type, bool forward_declaration) +void CompilerGLSL::emit_buffer_reference_block(uint32_t type_id, bool forward_declaration) { + auto &type = get(type_id); string buffer_name; if (forward_declaration) @@ -2215,8 +2216,19 @@ void CompilerGLSL::emit_buffer_reference_block(SPIRType &type, bool forward_decl if (!forward_declaration) { + auto itr = physical_storage_type_to_alignment.find(type_id); + uint32_t alignment = 0; + if (itr != physical_storage_type_to_alignment.end()) + alignment = itr->second.alignment; + if (type.basetype == SPIRType::Struct) { + SmallVector attributes; + attributes.push_back("buffer_reference"); + if (alignment) + attributes.push_back(join("buffer_reference_align = ", alignment)); + attributes.push_back(buffer_to_packing_standard(type, true)); + auto flags = ir.get_buffer_block_type_flags(type); string decorations; if (flags.get(DecorationRestrict)) @@ -2227,9 +2239,11 @@ void CompilerGLSL::emit_buffer_reference_block(SPIRType &type, bool forward_decl decorations += " writeonly"; if (flags.get(DecorationNonWritable)) decorations += " readonly"; - statement("layout(buffer_reference, ", buffer_to_packing_standard(type, true), - ")", decorations, " buffer ", buffer_name); + + statement("layout(", merge(attributes), ")", decorations, " buffer ", buffer_name); } + else if (alignment) + statement("layout(buffer_reference, buffer_reference_align = ", alignment, ") buffer ", buffer_name); else statement("layout(buffer_reference) buffer ", buffer_name); @@ -3447,28 +3461,28 @@ void CompilerGLSL::emit_resources() { for (auto type : physical_storage_non_block_pointer_types) { - emit_buffer_reference_block(get(type), false); + emit_buffer_reference_block(type, false); } // Output buffer reference blocks. // Do this in two stages, one with forward declaration, // and one without. Buffer reference blocks can reference themselves // to support things like linked lists. - ir.for_each_typed_id([&](uint32_t, SPIRType &type) { - bool has_block_flags = has_decoration(type.self, DecorationBlock); - if (has_block_flags && type.pointer && type.pointer_depth == 1 && !type_is_array_of_pointers(type) && + ir.for_each_typed_id([&](uint32_t self, SPIRType &type) { + if (type.basetype == SPIRType::Struct && type.pointer && + type.pointer_depth == 1 && !type_is_array_of_pointers(type) && type.storage == StorageClassPhysicalStorageBufferEXT) { - emit_buffer_reference_block(type, true); + emit_buffer_reference_block(self, true); } }); - ir.for_each_typed_id([&](uint32_t, SPIRType &type) { - bool has_block_flags = has_decoration(type.self, DecorationBlock); - if (has_block_flags && type.pointer && type.pointer_depth == 1 && !type_is_array_of_pointers(type) && + ir.for_each_typed_id([&](uint32_t self, SPIRType &type) { + if (type.basetype == SPIRType::Struct && + type.pointer && type.pointer_depth == 1 && !type_is_array_of_pointers(type) && type.storage == StorageClassPhysicalStorageBufferEXT) { - emit_buffer_reference_block(type, false); + emit_buffer_reference_block(self, false); } }); } diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index 52839d69..52362442 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -592,7 +592,7 @@ protected: void emit_resources(); void emit_extension_workarounds(spv::ExecutionModel model); void emit_buffer_block_native(const SPIRVariable &var); - void emit_buffer_reference_block(SPIRType &type, bool forward_declaration); + void emit_buffer_reference_block(uint32_t type_id, bool forward_declaration); void emit_buffer_block_legacy(const SPIRVariable &var); void emit_buffer_block_flattened(const SPIRVariable &type); void fixup_implicit_builtin_block_names();