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();