GL_EXT_buffer_reference
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp
index 6dc25ab..c7cab84 100644
--- a/SPIRV/GlslangToSpv.cpp
+++ b/SPIRV/GlslangToSpv.cpp
@@ -145,9 +145,9 @@
     spv::Id getInvertedSwizzleType(const glslang::TIntermTyped&);
     spv::Id createInvertedSwizzle(spv::Decoration precision, const glslang::TIntermTyped&, spv::Id parentResult);
     void convertSwizzle(const glslang::TIntermAggregate&, std::vector<unsigned>& swizzle);
-    spv::Id convertGlslangToSpvType(const glslang::TType& type);
+    spv::Id convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly = false);
     spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&,
-        bool lastBufferBlockMember);
+        bool lastBufferBlockMember, bool forwardReferenceOnly = false);
     bool filterMember(const glslang::TType& member);
     spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct,
                                           glslang::TLayoutPacking, const glslang::TQualifier&);
@@ -211,6 +211,15 @@
             builder.addExtension(ext);
     }
 
+    unsigned int getBufferReferenceAlignment(const glslang::TType &type) const {
+        if (type.getBasicType() == glslang::EbtReference) {
+            return type.getReferentType()->getQualifier().hasBufferReferenceAlign() ?
+                        (1u << type.getReferentType()->getQualifier().layoutBufferReferenceAlign) : 16u;
+        } else {
+            return 0;
+        }
+    }
+
     glslang::SpvOptions& options;
     spv::Function* shaderEntry;
     spv::Function* currentFunction;
@@ -237,6 +246,8 @@
     std::unordered_map<const glslang::TTypeList*, std::vector<int> > memberRemapper;
     std::stack<bool> breakForLoop;  // false means break for switch
     std::unordered_map<std::string, const glslang::TIntermSymbol*> counterOriginator;
+    // Map pointee types for EbtReference to their forward pointers
+    std::map<const glslang::TType *, spv::Id> forwardPointers;
 };
 
 //
@@ -1303,12 +1314,22 @@
             builder.addInclude(iItr->first, iItr->second);
     }
     stdBuiltins = builder.import("GLSL.std.450");
+
+    spv::AddressingModel addressingModel = spv::AddressingModelLogical;
+    spv::MemoryModel memoryModel = spv::MemoryModelGLSL450;
+
+    if (glslangIntermediate->usingPhysicalStorageBuffer()) {
+        addressingModel = spv::AddressingModelPhysicalStorageBuffer64EXT;
+        builder.addExtension(spv::E_SPV_EXT_physical_storage_buffer);
+        builder.addCapability(spv::CapabilityPhysicalStorageBufferAddressesEXT);
+    };
     if (glslangIntermediate->usingVulkanMemoryModel()) {
-        builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelVulkanKHR);
+        memoryModel = spv::MemoryModelVulkanKHR;
+        builder.addCapability(spv::CapabilityVulkanMemoryModelKHR);
         builder.addExtension(spv::E_SPV_KHR_vulkan_memory_model);
-    } else {
-        builder.setMemoryModel(spv::AddressingModelLogical, spv::MemoryModelGLSL450);
     }
+    builder.setMemoryModel(addressingModel, memoryModel);
+
     shaderEntry = builder.makeEntryPoint(glslangIntermediate->getEntryPointName().c_str());
     entryPoint = builder.addEntryPoint(executionModel, shaderEntry, glslangIntermediate->getEntryPointName().c_str());
 
@@ -1681,8 +1702,24 @@
                 // so short circuit the access-chain stuff with a swizzle.
                 std::vector<unsigned> swizzle;
                 swizzle.push_back(glslangIndex);
-                builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
+                int dummySize;
+                builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
+                                               TranslateCoherent(node->getLeft()->getType()),
+                                               glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
             } else {
+
+                // Load through a block reference is performed with a dot operator that
+                // is mapped to EOpIndexDirectStruct. When we get to the actual reference,
+                // do a load and reset the access chain.
+                if (node->getLeft()->getBasicType() == glslang::EbtReference &&
+                    !node->getLeft()->getType().isArray() &&
+                    node->getOp() == glslang::EOpIndexDirectStruct)
+                {
+                    spv::Id left = accessChainLoad(node->getLeft()->getType());
+                    builder.clearAccessChain();
+                    builder.setAccessChainLValue(left);
+                }
+
                 int spvIndex = glslangIndex;
                 if (node->getLeft()->getBasicType() == glslang::EbtBlock &&
                     node->getOp() == glslang::EOpIndexDirectStruct)
@@ -1695,7 +1732,7 @@
                 }
 
                 // normal case for indexing array or structure or block
-                builder.accessChainPush(builder.makeIntConstant(spvIndex), TranslateCoherent(node->getLeft()->getType()));
+                builder.accessChainPush(builder.makeIntConstant(spvIndex), TranslateCoherent(node->getLeft()->getType()), getBufferReferenceAlignment(node->getLeft()->getType()));
 
                 // Add capabilities here for accessing PointSize and clip/cull distance.
                 // We have deferred generation of associated capabilities until now.
@@ -1728,10 +1765,13 @@
             // restore the saved access chain
             builder.setAccessChain(partial);
 
-            if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector())
-                builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()));
-            else
-                builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()));
+            if (! node->getLeft()->getType().isArray() && node->getLeft()->getType().isVector()) {
+                int dummySize;
+                builder.accessChainPushComponent(index, convertGlslangToSpvType(node->getLeft()->getType()),
+                                                TranslateCoherent(node->getLeft()->getType()),
+                                                glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
+            } else
+                builder.accessChainPush(index, TranslateCoherent(node->getLeft()->getType()), getBufferReferenceAlignment(node->getLeft()->getType()));
         }
         return false;
     case glslang::EOpVectorSwizzle:
@@ -1739,7 +1779,10 @@
             node->getLeft()->traverse(this);
             std::vector<unsigned> swizzle;
             convertSwizzle(*node->getRight()->getAsAggregate(), swizzle);
-            builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()));
+            int dummySize;
+            builder.accessChainPushSwizzle(swizzle, convertGlslangToSpvType(node->getLeft()->getType()),
+                                           TranslateCoherent(node->getLeft()->getType()),
+                                           glslangIntermediate->getBaseAlignmentScalar(node->getLeft()->getType(), dummySize));
         }
         return false;
     case glslang::EOpMatrixSwizzle:
@@ -2178,6 +2221,7 @@
     case glslang::EOpConstructU64Vec4:
     case glslang::EOpConstructStruct:
     case glslang::EOpConstructTextureSampler:
+    case glslang::EOpConstructReference:
     {
         builder.setLine(node->getLoc().line, node->getLoc().getFilename());
         std::vector<spv::Id> arguments;
@@ -2829,6 +2873,7 @@
                 builder.addCapability(spv::CapabilityStorageUniform16);
             break;
         case spv::StorageClassStorageBuffer:
+        case spv::StorageClassPhysicalStorageBufferEXT:
             addPre13Extension(spv::E_SPV_KHR_16bit_storage);
             builder.addCapability(spv::CapabilityStorageUniformBufferBlock16);
             break;
@@ -2910,16 +2955,17 @@
 // Convert from a glslang type to an SPV type, by calling into a
 // recursive version of this function. This establishes the inherited
 // layout state rooted from the top-level type.
-spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type)
+spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type, bool forwardReferenceOnly)
 {
-    return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier(), false);
+    return convertGlslangToSpvType(type, getExplicitLayout(type), type.getQualifier(), false, forwardReferenceOnly);
 }
 
 // Do full recursive conversion of an arbitrary glslang type to a SPIR-V Id.
 // explicitLayout can be kept the same throughout the hierarchical recursive walk.
 // Mutually recursive with convertGlslangStructToSpvType().
 spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& type,
-    glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier, bool lastBufferBlockMember)
+    glslang::TLayoutPacking explicitLayout, const glslang::TQualifier& qualifier,
+    bool lastBufferBlockMember, bool forwardReferenceOnly)
 {
     spv::Id spvType = spv::NoResult;
 
@@ -3014,6 +3060,23 @@
             spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier);
         }
         break;
+    case glslang::EbtReference:
+        {
+            // Make the forward pointer, then recurse to convert the structure type, then
+            // patch up the forward pointer with a real pointer type.
+            if (forwardPointers.find(type.getReferentType()) == forwardPointers.end()) {
+                spv::Id forwardId = builder.makeForwardPointer(spv::StorageClassPhysicalStorageBufferEXT);
+                forwardPointers[type.getReferentType()] = forwardId;
+            }
+            spvType = forwardPointers[type.getReferentType()];
+            if (!forwardReferenceOnly) {
+                spv::Id referentType = convertGlslangToSpvType(*type.getReferentType());
+                builder.makePointerFromForwardPointer(spv::StorageClassPhysicalStorageBufferEXT,
+                                                      forwardPointers[type.getReferentType()],
+                                                      referentType);
+            }
+        }
+        break;
     default:
         assert(0);
         break;
@@ -3121,6 +3184,7 @@
     // Create a vector of struct types for SPIR-V to consume
     std::vector<spv::Id> spvMembers;
     int memberDelta = 0;  // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks
+    std::vector<std::pair<glslang::TType*, glslang::TQualifier> > deferredForwardPointers;
     for (int i = 0; i < (int)glslangMembers->size(); i++) {
         glslang::TType& glslangMember = *(*glslangMembers)[i].type;
         if (glslangMember.hiddenMember()) {
@@ -3144,8 +3208,19 @@
             // recurse
             bool lastBufferBlockMember = qualifier.storage == glslang::EvqBuffer &&
                                          i == (int)glslangMembers->size() - 1;
-            spvMembers.push_back(
-                convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember));
+
+            // Make forward pointers for any pointer members, and create a list of members to
+            // convert to spirv types after creating the struct.
+            if (glslangMember.getBasicType() == glslang::EbtReference) {
+                if (forwardPointers.find(glslangMember.getReferentType()) == forwardPointers.end()) {
+                    deferredForwardPointers.push_back(std::make_pair(&glslangMember, memberQualifier));
+                }
+                spvMembers.push_back(
+                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, true));
+            } else {
+                spvMembers.push_back(
+                    convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier, lastBufferBlockMember, false));
+            }
         }
     }
 
@@ -3157,6 +3232,11 @@
     // Decorate it
     decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType);
 
+    for (int i = 0; i < deferredForwardPointers.size(); ++i) {
+        auto it = deferredForwardPointers[i];
+        convertGlslangToSpvType(*it.first, explicitLayout, it.second, false);
+    }
+
     return spvType;
 }
 
@@ -3320,11 +3400,15 @@
     spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags;
     coherentFlags |= TranslateCoherent(type);
 
+    unsigned int alignment = builder.getAccessChain().alignment;
+    alignment |= getBufferReferenceAlignment(type);
+
     spv::Id loadedId = builder.accessChainLoad(TranslatePrecisionDecoration(type),
                                                TranslateNonUniformDecoration(type.getQualifier()),
                                                nominalTypeId,
                                                spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerAvailableKHRMask),
-                                               TranslateMemoryScope(coherentFlags));
+                                               TranslateMemoryScope(coherentFlags),
+                                               alignment);
 
     // Need to convert to abstract types when necessary
     if (type.getBasicType() == glslang::EbtBool) {
@@ -3383,9 +3467,12 @@
     spv::Builder::AccessChain::CoherentFlags coherentFlags = builder.getAccessChain().coherentFlags;
     coherentFlags |= TranslateCoherent(type);
 
+    unsigned int alignment = builder.getAccessChain().alignment;
+    alignment |= getBufferReferenceAlignment(type);
+
     builder.accessChainStore(rvalue,
                              spv::MemoryAccessMask(TranslateMemoryAccess(coherentFlags) & ~spv::MemoryAccessMakePointerVisibleKHRMask),
-                             TranslateMemoryScope(coherentFlags));
+                             TranslateMemoryScope(coherentFlags), alignment);
 }
 
 // For storing when types match at the glslang level, but not might match at the
@@ -3431,7 +3518,7 @@
             // set up the target storage
             builder.clearAccessChain();
             builder.setAccessChainLValue(lValue);
-            builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type));
+            builder.accessChainPush(builder.makeIntConstant(index), TranslateCoherent(type), getBufferReferenceAlignment(type));
 
             // store the member
             multiTypeStore(glslangElementType, elementRValue);
@@ -3451,7 +3538,7 @@
             // set up the target storage
             builder.clearAccessChain();
             builder.setAccessChainLValue(lValue);
-            builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type));
+            builder.accessChainPush(builder.makeIntConstant(m), TranslateCoherent(type), getBufferReferenceAlignment(type));
 
             // store the member
             multiTypeStore(glslangMemberType, memberRValue);
@@ -3638,11 +3725,22 @@
 // Make all the functions, skeletally, without actually visiting their bodies.
 void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions)
 {
-    const auto getParamDecorations = [](std::vector<spv::Decoration>& decorations, const glslang::TType& type, bool useVulkanMemoryModel) {
+    const auto getParamDecorations = [&](std::vector<spv::Decoration>& decorations, const glslang::TType& type, bool useVulkanMemoryModel) {
         spv::Decoration paramPrecision = TranslatePrecisionDecoration(type);
         if (paramPrecision != spv::NoPrecision)
             decorations.push_back(paramPrecision);
         TranslateMemoryDecoration(type.getQualifier(), decorations, useVulkanMemoryModel);
+        if (type.getBasicType() == glslang::EbtReference) {
+            // Original and non-writable params pass the pointer directly and
+            // use restrict/aliased, others are stored to a pointer in Function
+            // memory and use RestrictPointer/AliasedPointer.
+            if (originalParam(type.getQualifier().storage, type, false) ||
+                !writableParam(type.getQualifier().storage)) {
+                decorations.push_back(type.getQualifier().restrict ? spv::DecorationRestrict : spv::DecorationAliased);
+            } else {
+                decorations.push_back(type.getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
+            }
+        }
     };
 
     for (int f = 0; f < (int)glslFunctions.size(); ++f) {
@@ -4459,7 +4557,7 @@
             spv::Builder::AccessChain::CoherentFlags flags;
             flags.clear();
 
-            builder.accessChainPush(builder.makeIntConstant(i), flags);
+            builder.accessChainPush(builder.makeIntConstant(i), flags, 0);
             builder.accessChainStore(builder.createCompositeExtract(res, builder.getContainedTypeId(resType, i+1), i+1));
         }
         return builder.createCompositeExtract(res, resultType(), 0);
@@ -5330,6 +5428,9 @@
         unaryOp = spv::OpGroupNonUniformPartitionNV;
         break;
 #endif
+    case glslang::EOpConstructReference:
+        unaryOp = spv::OpBitcast;
+        break;
     default:
         return 0;
     }
@@ -5782,6 +5883,12 @@
         // For normal run-time conversion instruction, use OpBitcast.
         convOp = spv::OpBitcast;
         break;
+    case glslang::EOpConvUint64ToPtr:
+        convOp = spv::OpConvertUToPtr;
+        break;
+    case glslang::EOpConvPtrToUint64:
+        convOp = spv::OpConvertPtrToU;
+        break;
     default:
         break;
     }
@@ -7247,6 +7354,10 @@
                               symbol->getType().getQualifier().semanticName);
     }
 
+    if (symbol->getBasicType() == glslang::EbtReference) {
+        builder.addDecoration(id, symbol->getType().getQualifier().restrict ? spv::DecorationRestrictPointerEXT : spv::DecorationAliasedPointerEXT);
+    }
+
     return id;
 }
 
@@ -7375,7 +7486,7 @@
         glslang::TType vectorType(glslangType, 0);
         for (int col = 0; col < glslangType.getMatrixCols(); ++col)
             spvConsts.push_back(createSpvConstantFromConstUnionArray(vectorType, consts, nextConst, false));
-    } else if (glslangType.getStruct()) {
+    } else if (glslangType.isStruct()) {
         glslang::TVector<glslang::TTypeLoc>::const_iterator iter;
         for (iter = glslangType.getStruct()->begin(); iter != glslangType.getStruct()->end(); ++iter)
             spvConsts.push_back(createSpvConstantFromConstUnionArray(*iter->type, consts, nextConst, false));