Merge pull request #1807 from KhronosGroup/fix-1801
GLSL: Deal with buffer_reference_align.
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 82ebb96..771d049 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 0000000..f5907d3
--- /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 0000000..a5a66b1
--- /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 53c3d21..20a4f1b 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 3956304..5cf6e2d 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 5752f81..8923d21 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(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 5b3cf49..b7e8806 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(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 b30330c..de0964b 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 cabf835..12581cc 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(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 0000000..06e620d
--- /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 0000000..44427de
--- /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 0288931..432c0ad 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 9553199..95b97fc 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 82ebb96..771d049 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 0000000..f5907d3
--- /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 0000000..9cd3d3e
--- /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 53c3d21..20a4f1b 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 3956304..5cf6e2d 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 5752f81..8923d21 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(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 5b3cf49..b7e8806 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(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 e229741..1923927 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 0000000..8fda30e
--- /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 0000000..d7ca03f
--- /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 a1da941..f0421b2 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 0000000..cf0a8e4
--- /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 0000000..41b4451
--- /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 99b69ad..07fdb94 100644
--- a/spirv_cross.cpp
+++ b/spirv_cross.cpp
@@ -4749,31 +4749,181 @@
{
}
-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<SPIRType>(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<SPIRType>(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<SPIRType>(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<SPIRType>(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<SPIRType>(type_id);
+ while (type->pointer &&
+ type->storage == StorageClassPhysicalStorageBufferEXT &&
+ !type_is_bda_block_entry(type_id))
+ {
+ type_id = type->parent_type;
+ type = &compiler.get<SPIRType>(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<SPIRType>(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<SPIRFunction>(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<SPIRType>([&](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 2730860..d896796 100644
--- a/spirv_cross.hpp
+++ b/spirv_cross.hpp
@@ -1010,15 +1010,32 @@
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<uint32_t> types;
+
+ std::unordered_set<uint32_t> non_block_types;
+ std::unordered_map<uint32_t, PhysicalBlockMeta> physical_block_type_meta;
+ std::unordered_map<uint32_t, PhysicalBlockMeta *> 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<uint32_t> physical_storage_non_block_pointer_types;
+ std::unordered_map<uint32_t, PhysicalBlockMeta> 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 61acda6..9578502 100644
--- a/spirv_glsl.cpp
+++ b/spirv_glsl.cpp
@@ -2171,8 +2171,9 @@
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<SPIRType>(type_id);
string buffer_name;
if (forward_declaration)
@@ -2215,8 +2216,19 @@
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<std::string> 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 @@
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 @@
{
for (auto type : physical_storage_non_block_pointer_types)
{
- emit_buffer_reference_block(get<SPIRType>(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<SPIRType>([&](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<SPIRType>([&](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<SPIRType>([&](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<SPIRType>([&](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 52839d6..5236244 100644
--- a/spirv_glsl.hpp
+++ b/spirv_glsl.hpp
@@ -592,7 +592,7 @@
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();