Merge pull request #1644 from jeffbolznv/buffer_reference

GL_EXT_buffer_reference
diff --git a/SPIRV/GLSL.ext.KHR.h b/SPIRV/GLSL.ext.KHR.h
index 16b0d9c..333442b 100644
--- a/SPIRV/GLSL.ext.KHR.h
+++ b/SPIRV/GLSL.ext.KHR.h
@@ -40,5 +40,6 @@
 static const char* const E_SPV_KHR_storage_buffer_storage_class = "SPV_KHR_storage_buffer_storage_class";
 static const char* const E_SPV_KHR_post_depth_coverage          = "SPV_KHR_post_depth_coverage";
 static const char* const E_SPV_KHR_vulkan_memory_model          = "SPV_KHR_vulkan_memory_model";
+static const char* const E_SPV_EXT_physical_storage_buffer      = "SPV_EXT_physical_storage_buffer";
 
 #endif  // #ifndef GLSLextKHR_H
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));
diff --git a/SPIRV/SpvBuilder.cpp b/SPIRV/SpvBuilder.cpp
index 9ba3158..3375ec4 100755
--- a/SPIRV/SpvBuilder.cpp
+++ b/SPIRV/SpvBuilder.cpp
@@ -194,6 +194,40 @@
     return type->getResultId();
 }
 
+Id Builder::makeForwardPointer(StorageClass storageClass)
+{
+    // Caching/uniquifying doesn't work here, because we don't know the
+    // pointee type and there can be multiple forward pointers of the same
+    // storage type. Somebody higher up in the stack must keep track.
+    Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeForwardPointer);
+    type->addImmediateOperand(storageClass);
+    constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+    module.mapInstruction(type);
+
+    return type->getResultId();
+}
+
+Id Builder::makePointerFromForwardPointer(StorageClass storageClass, Id forwardPointerType, Id pointee)
+{
+    // try to find it
+    Instruction* type;
+    for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
+        type = groupedTypes[OpTypePointer][t];
+        if (type->getImmediateOperand(0) == (unsigned)storageClass &&
+            type->getIdOperand(1) == pointee)
+            return type->getResultId();
+    }
+
+    type = new Instruction(forwardPointerType, NoType, OpTypePointer);
+    type->addImmediateOperand(storageClass);
+    type->addIdOperand(pointee);
+    groupedTypes[OpTypePointer].push_back(type);
+    constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
+    module.mapInstruction(type);
+
+    return type->getResultId();
+}
+
 Id Builder::makeIntegerType(int width, bool hasSign)
 {
     // try to find it
@@ -576,6 +610,7 @@
     case OpTypeBool:
     case OpTypeInt:
     case OpTypeFloat:
+    case OpTypePointer:
         return 1;
     case OpTypeVector:
     case OpTypeMatrix:
@@ -669,17 +704,36 @@
                 return true;
         }
         return false;
+    case OpTypePointer:
+        return false;
     case OpTypeVector:
     case OpTypeMatrix:
     case OpTypeArray:
     case OpTypeRuntimeArray:
-    case OpTypePointer:
         return containsType(getContainedTypeId(typeId), typeOp, width);
     default:
         return typeClass == typeOp;
     }
 }
 
+// return true if the type is a pointer to PhysicalStorageBufferEXT or an
+// array of such pointers. These require restrict/aliased decorations.
+bool Builder::containsPhysicalStorageBufferOrArray(Id typeId) const
+{
+    const Instruction& instr = *module.getInstruction(typeId);
+
+    Op typeClass = instr.getOpCode();
+    switch (typeClass)
+    {
+    case OpTypePointer:
+        return getTypeStorageClass(typeId) == StorageClassPhysicalStorageBufferEXT;
+    case OpTypeArray:
+        return containsPhysicalStorageBufferOrArray(getContainedTypeId(typeId));
+    default:
+        return false;
+    }
+}
+
 // See if a scalar constant of this type has already been created, so it
 // can be reused rather than duplicated.  (Required by the specification).
 Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value)
@@ -1252,15 +1306,39 @@
   return inst->getResultId();
 }
 
+// av/vis/nonprivate are unnecessary and illegal for some storage classes.
+spv::MemoryAccessMask Builder::sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const
+{
+    switch (sc) {
+    case spv::StorageClassUniform:
+    case spv::StorageClassWorkgroup:
+    case spv::StorageClassStorageBuffer:
+    case spv::StorageClassPhysicalStorageBufferEXT:
+        break;
+    default:
+        memoryAccess = spv::MemoryAccessMask(memoryAccess & 
+                        ~(spv::MemoryAccessMakePointerAvailableKHRMask |
+                          spv::MemoryAccessMakePointerVisibleKHRMask |
+                          spv::MemoryAccessNonPrivatePointerKHRMask));
+        break;
+    }
+    return memoryAccess;
+}
+
 // Comments in header
-void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
+void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
 {
     Instruction* store = new Instruction(OpStore);
     store->addIdOperand(lValue);
     store->addIdOperand(rValue);
 
+    memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
+
     if (memoryAccess != MemoryAccessMaskNone) {
         store->addImmediateOperand(memoryAccess);
+        if (memoryAccess & spv::MemoryAccessAlignedMask) {
+            store->addImmediateOperand(alignment);
+        }
         if (memoryAccess & spv::MemoryAccessMakePointerAvailableKHRMask) {
             store->addIdOperand(makeUintConstant(scope));
         }
@@ -1270,13 +1348,18 @@
 }
 
 // Comments in header
-Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
+Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
 {
     Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
     load->addIdOperand(lValue);
 
+    memoryAccess = sanitizeMemoryAccessForStorageClass(memoryAccess, getStorageClass(lValue));
+
     if (memoryAccess != MemoryAccessMaskNone) {
         load->addImmediateOperand(memoryAccess);
+        if (memoryAccess & spv::MemoryAccessAlignedMask) {
+            load->addImmediateOperand(alignment);
+        }
         if (memoryAccess & spv::MemoryAccessMakePointerVisibleKHRMask) {
             load->addIdOperand(makeUintConstant(scope));
         }
@@ -2118,7 +2201,8 @@
     // Go through the source arguments, each one could have either
     // a single or multiple components to contribute.
     for (unsigned int i = 0; i < sources.size(); ++i) {
-        if (isScalar(sources[i]))
+
+        if (isScalar(sources[i]) || isPointer(sources[i]))
             latchResult(sources[i]);
         else if (isVector(sources[i]))
             accumulateVectorConstituents(sources[i]);
@@ -2433,11 +2517,15 @@
     accessChain.preSwizzleBaseType = NoType;
     accessChain.isRValue = false;
     accessChain.coherentFlags.clear();
+    accessChain.alignment = 0;
 }
 
 // Comments in header
-void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType)
+void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
 {
+    accessChain.coherentFlags |= coherentFlags;
+    accessChain.alignment |= alignment;
+
     // swizzles can be stacked in GLSL, but simplified to a single
     // one here; the base type doesn't change
     if (accessChain.preSwizzleBaseType == NoType)
@@ -2459,7 +2547,7 @@
 }
 
 // Comments in header
-void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
+void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
 {
     assert(accessChain.isRValue == false);
 
@@ -2477,11 +2565,17 @@
         source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
     }
 
-    createStore(source, base, memoryAccess, scope);
+    // take LSB of alignment
+    alignment = alignment & ~(alignment & (alignment-1));
+    if (getStorageClass(base) == StorageClassPhysicalStorageBufferEXT) {
+        memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
+    }
+
+    createStore(source, base, memoryAccess, scope, alignment);
 }
 
 // Comments in header
-Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
+Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope, unsigned int alignment)
 {
     Id id;
 
@@ -2524,8 +2618,15 @@
             id = accessChain.base;  // no precision, it was set when this was defined
     } else {
         transferAccessChainSwizzle(true);
+
+        // take LSB of alignment
+        alignment = alignment & ~(alignment & (alignment-1));
+        if (getStorageClass(accessChain.base) == StorageClassPhysicalStorageBufferEXT) {
+            memoryAccess = (spv::MemoryAccessMask)(memoryAccess | spv::MemoryAccessAlignedMask);
+        }
+
         // load through the access chain
-        id = createLoad(collapseAccessChain(), memoryAccess, scope);
+        id = createLoad(collapseAccessChain(), memoryAccess, scope, alignment);
         setPrecision(id, precision);
         addDecoration(id, nonUniform);
     }
diff --git a/SPIRV/SpvBuilder.h b/SPIRV/SpvBuilder.h
index 3af6ace..edeac1b 100755
--- a/SPIRV/SpvBuilder.h
+++ b/SPIRV/SpvBuilder.h
@@ -138,7 +138,9 @@
     // For creating new types (will return old type if the requested one was already made).
     Id makeVoidType();
     Id makeBoolType();
-    Id makePointer(StorageClass, Id type);
+    Id makePointer(StorageClass, Id pointee);
+    Id makeForwardPointer(StorageClass);
+    Id makePointerFromForwardPointer(StorageClass, Id forwardPointerType, Id pointee);
     Id makeIntegerType(int width, bool hasSign);   // generic
     Id makeIntType(int width) { return makeIntegerType(width, true); }
     Id makeUintType(int width) { return makeIntegerType(width, false); }
@@ -194,6 +196,7 @@
     bool isSamplerType(Id typeId)      const { return getTypeClass(typeId) == OpTypeSampler; }
     bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
     bool containsType(Id typeId, Op typeOp, unsigned int width) const;
+    bool containsPhysicalStorageBufferOrArray(Id typeId) const;
 
     bool isConstantOpCode(Op opcode) const;
     bool isSpecConstantOpCode(Op opcode) const;
@@ -300,10 +303,10 @@
     Id createUndefined(Id type);
 
     // Store into an Id and return the l-value
-    void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax);
+    void createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // Load from an Id and return it
-    Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax);
+    Id createLoad(Id lValue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // Create an OpAccessChain instruction
     Id createAccessChain(StorageClass, Id base, const std::vector<Id>& offsets);
@@ -535,6 +538,7 @@
         Id component;                  // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
         Id preSwizzleBaseType;         // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
         bool isRValue;                 // true if 'base' is an r-value, otherwise, base is an l-value
+        unsigned int alignment;        // bitwise OR of alignment values passed in. Accumulates worst alignment. Only tracks base and (optional) component selection alignment.
 
         // Accumulate whether anything in the chain of structures has coherent decorations.
         struct CoherentFlags {
@@ -601,31 +605,34 @@
     }
 
     // push offset onto the end of the chain
-    void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags)
+    void accessChainPush(Id offset, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
     {
         accessChain.indexChain.push_back(offset);
         accessChain.coherentFlags |= coherentFlags;
+        accessChain.alignment |= alignment;
     }
 
     // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
-    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType);
+    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment);
 
     // push a dynamic component selection onto the access chain, only applicable with a
     // non-trivial swizzle or no swizzle
-    void accessChainPushComponent(Id component, Id preSwizzleBaseType)
+    void accessChainPushComponent(Id component, Id preSwizzleBaseType, AccessChain::CoherentFlags coherentFlags, unsigned int alignment)
     {
         if (accessChain.swizzle.size() != 1) {
             accessChain.component = component;
             if (accessChain.preSwizzleBaseType == NoType)
                 accessChain.preSwizzleBaseType = preSwizzleBaseType;
         }
+        accessChain.coherentFlags |= coherentFlags;
+        accessChain.alignment |= alignment;
     }
 
     // use accessChain and swizzle to store value
-    void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax);
+    void accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // use accessChain and swizzle to load an r-value
-    Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax);
+    Id accessChainLoad(Decoration precision, Decoration nonUniform, Id ResultType, spv::MemoryAccessMask memoryAccess = spv::MemoryAccessMaskNone, spv::Scope scope = spv::ScopeMax, unsigned int alignment = 0);
 
     // get the direct pointer for an l-value
     Id accessChainGetLValue();
@@ -639,7 +646,7 @@
     void postProcess();
 
     // Hook to visit each instruction in a block in a function
-    void postProcess(const Instruction&);
+    void postProcess(Instruction&);
     // Hook to visit each instruction in a reachable block in a function.
     void postProcessReachable(const Instruction&);
     // Hook to visit each non-32-bit sized float/int operation in a block.
@@ -675,6 +682,7 @@
     void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector<unsigned int>&) const;
     void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
     void dumpModuleProcesses(std::vector<unsigned int>&) const;
+    spv::MemoryAccessMask sanitizeMemoryAccessForStorageClass(spv::MemoryAccessMask memoryAccess, StorageClass sc) const;
 
     unsigned int spvVersion;     // the version of SPIR-V to emit in the header
     SourceLanguage source;
diff --git a/SPIRV/SpvPostProcess.cpp b/SPIRV/SpvPostProcess.cpp
index 5187530..04d594c 100755
--- a/SPIRV/SpvPostProcess.cpp
+++ b/SPIRV/SpvPostProcess.cpp
@@ -87,6 +87,7 @@
             StorageClass storageClass = getStorageClass(inst.getIdOperand(0));
             if (width == 8) {
                 switch (storageClass) {
+                case StorageClassPhysicalStorageBufferEXT:
                 case StorageClassUniform:
                 case StorageClassStorageBuffer:
                 case StorageClassPushConstant:
@@ -97,6 +98,7 @@
                 }
             } else if (width == 16) {
                 switch (storageClass) {
+                case StorageClassPhysicalStorageBufferEXT:
                 case StorageClassUniform:
                 case StorageClassStorageBuffer:
                 case StorageClassPushConstant:
@@ -151,7 +153,7 @@
 }
 
 // Called for each instruction that resides in a block.
-void Builder::postProcess(const Instruction& inst)
+void Builder::postProcess(Instruction& inst)
 {
     // Add capabilities based simply on the opcode.
     switch (inst.getOpCode()) {
@@ -190,6 +192,88 @@
         break;
 #endif
 
+    case OpLoad:
+    case OpStore:
+        {
+            // For any load/store to a PhysicalStorageBufferEXT, walk the accesschain
+            // index list to compute the misalignment. The pre-existing alignment value
+            // (set via Builder::AccessChain::alignment) only accounts for the base of
+            // the reference type and any scalar component selection in the accesschain,
+            // and this function computes the rest from the SPIR-V Offset decorations.
+            Instruction *accessChain = module.getInstruction(inst.getIdOperand(0));
+            if (accessChain->getOpCode() == OpAccessChain) {
+                Instruction *base = module.getInstruction(accessChain->getIdOperand(0));
+                // Get the type of the base of the access chain. It must be a pointer type.
+                Id typeId = base->getTypeId();
+                Instruction *type = module.getInstruction(typeId);
+                assert(type->getOpCode() == OpTypePointer);
+                if (type->getImmediateOperand(0) != StorageClassPhysicalStorageBufferEXT) {
+                    break;
+                }
+                // Get the pointee type.
+                typeId = type->getIdOperand(1);
+                type = module.getInstruction(typeId);
+                // Walk the index list for the access chain. For each index, find any
+                // misalignment that can apply when accessing the member/element via
+                // Offset/ArrayStride/MatrixStride decorations, and bitwise OR them all
+                // together.
+                int alignment = 0;
+                for (int i = 1; i < accessChain->getNumOperands(); ++i) {
+                    Instruction *idx = module.getInstruction(accessChain->getIdOperand(i));
+                    if (type->getOpCode() == OpTypeStruct) {
+                        assert(idx->getOpCode() == OpConstant);
+                        int c = idx->getImmediateOperand(0);
+
+                        const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
+                            if (decoration.get()->getOpCode() == OpMemberDecorate &&
+                                decoration.get()->getIdOperand(0) == typeId &&
+                                decoration.get()->getImmediateOperand(1) == c &&
+                                (decoration.get()->getImmediateOperand(2) == DecorationOffset ||
+                                 decoration.get()->getImmediateOperand(2) == DecorationMatrixStride)) {
+                                alignment |= decoration.get()->getImmediateOperand(3);
+                            }
+                        };
+                        std::for_each(decorations.begin(), decorations.end(), function);
+                        // get the next member type
+                        typeId = type->getIdOperand(c);
+                        type = module.getInstruction(typeId);
+                    } else if (type->getOpCode() == OpTypeArray ||
+                               type->getOpCode() == OpTypeRuntimeArray) {
+                        const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
+                            if (decoration.get()->getOpCode() == OpDecorate &&
+                                decoration.get()->getIdOperand(0) == typeId &&
+                                decoration.get()->getImmediateOperand(1) == DecorationArrayStride) {
+                                alignment |= decoration.get()->getImmediateOperand(2);
+                            }
+                        };
+                        std::for_each(decorations.begin(), decorations.end(), function);
+                        // Get the element type
+                        typeId = type->getIdOperand(0);
+                        type = module.getInstruction(typeId);
+                    } else {
+                        // Once we get to any non-aggregate type, we're done.
+                        break;
+                    }
+                }
+                assert(inst.getNumOperands() >= 3);
+                unsigned int memoryAccess = inst.getImmediateOperand((inst.getOpCode() == OpStore) ? 2 : 1);
+                assert(memoryAccess & MemoryAccessAlignedMask);
+                // Compute the index of the alignment operand.
+                int alignmentIdx = 2;
+                if (memoryAccess & MemoryAccessVolatileMask)
+                    alignmentIdx++;
+                if (inst.getOpCode() == OpStore)
+                    alignmentIdx++;
+                // Merge new and old (mis)alignment
+                alignment |= inst.getImmediateOperand(alignmentIdx);
+                // Pick the LSB
+                alignment = alignment & ~(alignment & (alignment-1));
+                // update the Aligned operand
+                inst.setImmediateOperand(alignmentIdx, alignment);
+            }
+            break;
+        }
+
     default:
         break;
     }
@@ -258,6 +342,47 @@
             Block* b = *bi;
             for (auto ii = b->getInstructions().cbegin(); ii != b->getInstructions().cend(); ii++)
                 postProcess(*ii->get());
+
+            // For all local variables that contain pointers to PhysicalStorageBufferEXT, check whether
+            // there is an existing restrict/aliased decoration. If we don't find one, add Aliased as the
+            // default.
+            for (auto vi = b->getLocalVariables().cbegin(); vi != b->getLocalVariables().cend(); vi++) {
+                const Instruction& inst = *vi->get();
+                Id resultId = inst.getResultId();
+                if (containsPhysicalStorageBufferOrArray(getDerefTypeId(resultId))) {
+                    bool foundDecoration = false;
+                    const auto function = [&](const std::unique_ptr<Instruction>& decoration) {
+                        if (decoration.get()->getIdOperand(0) == resultId &&
+                            decoration.get()->getOpCode() == OpDecorate &&
+                            (decoration.get()->getImmediateOperand(1) == spv::DecorationAliasedPointerEXT ||
+                             decoration.get()->getImmediateOperand(1) == spv::DecorationRestrictPointerEXT)) {
+                            foundDecoration = true;
+                        }
+                    };
+                    std::for_each(decorations.begin(), decorations.end(), function);
+                    if (!foundDecoration) {
+                        addDecoration(resultId, spv::DecorationAliasedPointerEXT);
+                    }
+                }
+            }
+        }
+    }
+
+    // Look for any 8/16 bit type in physical storage buffer class, and set the
+    // appropriate capability. This happens in createSpvVariable for other storage
+    // classes, but there isn't always a variable for physical storage buffer.
+    for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
+        Instruction* type = groupedTypes[OpTypePointer][t];
+        if (type->getImmediateOperand(0) == (unsigned)StorageClassPhysicalStorageBufferEXT) {
+            if (containsType(type->getIdOperand(1), OpTypeInt, 8)) {
+                addExtension(spv::E_SPV_KHR_8bit_storage);
+                addCapability(spv::CapabilityStorageBuffer8BitAccess);
+            }
+            if (containsType(type->getIdOperand(1), OpTypeInt, 16) ||
+                containsType(type->getIdOperand(1), OpTypeFloat, 16)) {
+                addExtension(spv::E_SPV_KHR_16bit_storage);
+                addCapability(spv::CapabilityStorageBuffer16BitAccess);
+            }
         }
     }
 }
diff --git a/SPIRV/disassemble.cpp b/SPIRV/disassemble.cpp
index 22c83ea..631173c 100644
--- a/SPIRV/disassemble.cpp
+++ b/SPIRV/disassemble.cpp
@@ -540,6 +540,14 @@
         case OperandMemoryAccess:
             outputMask(OperandMemoryAccess, stream[word++]);
             --numOperands;
+            // Aligned is the only memory access operand that uses an immediate
+            // value, and it is also the first operand that uses a value at all.
+            if (stream[word-1] & MemoryAccessAlignedMask) {
+                disassembleImmediates(1);
+                numOperands--;
+                if (numOperands)
+                    out << " ";
+            }
             disassembleIds(numOperands);
             return;
         default:
diff --git a/SPIRV/doc.cpp b/SPIRV/doc.cpp
index b0b01fb..bd6df10 100644
--- a/SPIRV/doc.cpp
+++ b/SPIRV/doc.cpp
@@ -124,6 +124,8 @@
     case 1:  return "Physical32";
     case 2:  return "Physical64";
 
+    case AddressingModelPhysicalStorageBuffer64EXT: return "PhysicalStorageBuffer64EXT";
+
     default: return "Bad";
     }
 }
@@ -220,6 +222,8 @@
     case StorageClassIncomingCallableDataNV:  return "IncomingCallableDataNV";
 #endif
 
+    case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT";
+
     default: return "Bad";
     }
 }
@@ -295,6 +299,8 @@
     case DecorationNonUniformEXT:           return "DecorationNonUniformEXT";
     case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE";
     case DecorationHlslSemanticGOOGLE:      return "DecorationHlslSemanticGOOGLE";
+    case DecorationRestrictPointerEXT:      return "DecorationRestrictPointerEXT";
+    case DecorationAliasedPointerEXT:       return "DecorationAliasedPointerEXT";
     }
 }
 
@@ -922,6 +928,8 @@
     case CapabilityVulkanMemoryModelKHR:                return "CapabilityVulkanMemoryModelKHR";
     case CapabilityVulkanMemoryModelDeviceScopeKHR:     return "CapabilityVulkanMemoryModelDeviceScopeKHR";
 
+    case CapabilityPhysicalStorageBufferAddressesEXT:   return "CapabilityPhysicalStorageBufferAddressesEXT";
+
     default: return "Bad";
     }
 }
diff --git a/SPIRV/spvIR.h b/SPIRV/spvIR.h
index 8263960..8c2d0b6 100755
--- a/SPIRV/spvIR.h
+++ b/SPIRV/spvIR.h
@@ -102,6 +102,11 @@
         operands.push_back(immediate);
         idOperand.push_back(false);
     }
+    void setImmediateOperand(unsigned idx, unsigned int immediate) {
+        assert(!idOperand[idx]);
+        operands[idx] = immediate;
+    }
+
     void addStringOperand(const char* str)
     {
         unsigned int word;
@@ -203,6 +208,7 @@
     const std::vector<std::unique_ptr<Instruction> >& getInstructions() const {
         return instructions;
     }
+    const std::vector<std::unique_ptr<Instruction> >& getLocalVariables() const { return localVariables; }
     void setUnreachable() { unreachable = true; }
     bool isUnreachable() const { return unreachable; }
     // Returns the block's merge instruction, if one exists (otherwise null).
diff --git a/Test/baseResults/spv.bufferhandle1.frag.out b/Test/baseResults/spv.bufferhandle1.frag.out
new file mode 100644
index 0000000..906cb51
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle1.frag.out
@@ -0,0 +1,104 @@
+spv.bufferhandle1.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 52
+
+                              Capability Shader
+                              Capability CapabilityVulkanMemoryModelKHR
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+                              Extension  "SPV_KHR_vulkan_memory_model"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT VulkanKHR
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 7  "t2"
+                              MemberName 7(t2) 0  "f"
+                              MemberName 7(t2) 1  "g"
+                              Name 13  "blockType"
+                              MemberName 13(blockType) 0  "a"
+                              MemberName 13(blockType) 1  "b"
+                              MemberName 13(blockType) 2  "c"
+                              MemberName 13(blockType) 3  "d"
+                              MemberName 13(blockType) 4  "e"
+                              MemberName 13(blockType) 5  "f"
+                              MemberName 13(blockType) 6  "g"
+                              Name 15  "t"
+                              Name 28  "j"
+                              MemberDecorate 7(t2) 0 Offset 0
+                              MemberDecorate 7(t2) 1 Offset 8
+                              Decorate 7(t2) Block
+                              Decorate 11 ArrayStride 4
+                              MemberDecorate 13(blockType) 0 Offset 0
+                              MemberDecorate 13(blockType) 1 Offset 4
+                              MemberDecorate 13(blockType) 2 Offset 8
+                              MemberDecorate 13(blockType) 3 Offset 12
+                              MemberDecorate 13(blockType) 4 Offset 16
+                              MemberDecorate 13(blockType) 5 Offset 32
+                              MemberDecorate 13(blockType) 6 Offset 48
+                              Decorate 13(blockType) Block
+                              Decorate 15(t) DescriptorSet 0
+                              Decorate 15(t) Binding 0
+                              Decorate 28(j) DecorationAliasedPointerEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+           7(t2):             TypeStruct 6 6
+               8:             TypeInt 32 1
+               9:             TypeInt 32 0
+              10:      9(int) Constant 2
+              11:             TypeArray 8(int) 10
+              12:             TypeVector 8(int) 4
+   13(blockType):             TypeStruct 8(int) 8(int) 8(int) 8(int) 8(int) 11 12(ivec4)
+               6:             TypePointer PhysicalStorageBufferEXT 13(blockType)
+              14:             TypePointer StorageBuffer 7(t2)
+           15(t):     14(ptr) Variable StorageBuffer
+              16:      8(int) Constant 0
+              17:             TypePointer StorageBuffer 6(ptr)
+              20:      8(int) Constant 1
+              23:             TypePointer PhysicalStorageBufferEXT 8(int)
+              27:             TypePointer Function 6(ptr)
+              32:      8(int) Constant 3
+              34:      8(int) Constant 2
+              40:      8(int) Constant 5
+              46:      8(int) Constant 6
+              47:      9(int) Constant 1
+              50:      9(int) Constant 5
+         4(main):           2 Function None 3
+               5:             Label
+           28(j):     27(ptr) Variable Function
+              18:     17(ptr) AccessChain 15(t) 16
+              19:      6(ptr) Load 18
+              21:     17(ptr) AccessChain 15(t) 20
+              22:      6(ptr) Load 21
+              24:     23(ptr) AccessChain 22 16
+              25:      8(int) Load 24 Aligned 16
+              26:     23(ptr) AccessChain 19 20
+                              Store 26 25 Aligned 4
+              29:     17(ptr) AccessChain 15(t) 16
+              30:      6(ptr) Load 29
+                              Store 28(j) 30
+              31:      6(ptr) Load 28(j)
+              33:      6(ptr) Load 28(j)
+              35:     23(ptr) AccessChain 33 34
+              36:      8(int) Load 35 Aligned 8
+              37:     23(ptr) AccessChain 31 32
+                              Store 37 36 Aligned 4
+              38:      6(ptr) Load 28(j)
+              39:      6(ptr) Load 28(j)
+              41:     23(ptr) AccessChain 39 40 20
+              42:      8(int) Load 41 Aligned 4
+              43:     23(ptr) AccessChain 38 32
+                              Store 43 42 Aligned 4
+              44:      6(ptr) Load 28(j)
+              45:      6(ptr) Load 28(j)
+              48:     23(ptr) AccessChain 45 46 47
+              49:      8(int) Load 48 Aligned MakePointerVisibleKHR NonPrivatePointerKHR 4 50
+              51:     23(ptr) AccessChain 44 32
+                              Store 51 49 Aligned 4
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle10.frag.out b/Test/baseResults/spv.bufferhandle10.frag.out
new file mode 100644
index 0000000..bfaa2d8
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle10.frag.out
@@ -0,0 +1,73 @@
+spv.bufferhandle10.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 34
+
+                              Capability Shader
+                              Capability CapabilityVulkanMemoryModelKHR
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+                              Extension  "SPV_KHR_vulkan_memory_model"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT VulkanKHR
+                              EntryPoint Fragment 4  "main" 19
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_ARB_gpu_shader_int64"
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 7  "t2"
+                              MemberName 7(t2) 0  "f"
+                              Name 10  "blockType"
+                              MemberName 10(blockType) 0  "x"
+                              Name 12  "t"
+                              Name 19  "i"
+                              Name 28  "b"
+                              MemberDecorate 7(t2) 0 Offset 0
+                              Decorate 7(t2) Block
+                              Decorate 9 ArrayStride 4
+                              MemberDecorate 10(blockType) 0 Offset 0
+                              Decorate 10(blockType) Block
+                              Decorate 12(t) DescriptorSet 0
+                              Decorate 12(t) Binding 0
+                              Decorate 19(i) Flat
+                              Decorate 19(i) Location 0
+                              Decorate 28(b) DecorationAliasedPointerEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+           7(t2):             TypeStruct 6
+               8:             TypeInt 32 0
+               9:             TypeRuntimeArray 8(int)
+   10(blockType):             TypeStruct 9
+               6:             TypePointer PhysicalStorageBufferEXT 10(blockType)
+              11:             TypePointer StorageBuffer 7(t2)
+           12(t):     11(ptr) Variable StorageBuffer
+              13:             TypeInt 32 1
+              14:     13(int) Constant 0
+              15:             TypePointer StorageBuffer 6(ptr)
+              18:             TypePointer Input 8(int)
+           19(i):     18(ptr) Variable Input
+              21:             TypePointer PhysicalStorageBufferEXT 8(int)
+              23:      8(int) Constant 1
+              24:      8(int) Constant 5
+              25:      8(int) Constant 0
+              27:             TypePointer Function 6(ptr)
+              32:      8(int) Constant 2
+         4(main):           2 Function None 3
+               5:             Label
+           28(b):     27(ptr) Variable Function
+              16:     15(ptr) AccessChain 12(t) 14
+              17:      6(ptr) Load 16
+              20:      8(int) Load 19(i)
+              22:     21(ptr) AccessChain 17 14 20
+              26:      8(int) AtomicIAdd 22 24 25 23
+              29:     15(ptr) AccessChain 12(t) 14
+              30:      6(ptr) Load 29
+                              Store 28(b) 30
+              31:      6(ptr) Load 28(b)
+              33:     21(ptr) AccessChain 31 14 14
+                              Store 33 32 Aligned MakePointerAvailableKHR NonPrivatePointerKHR 4 24
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle11.frag.out b/Test/baseResults/spv.bufferhandle11.frag.out
new file mode 100644
index 0000000..0764a00
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle11.frag.out
@@ -0,0 +1,118 @@
+spv.bufferhandle11.frag
+WARNING: 0:6: '' : all default precisions are highp; use precision statements to quiet warning, e.g.:
+         "precision mediump int; precision highp float;" 
+
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 60
+
+                              Capability Shader
+                              Capability CapabilityStorageBuffer8BitAccess
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_8bit_storage"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              SourceExtension  "GL_EXT_shader_16bit_storage"
+                              SourceExtension  "GL_EXT_shader_8bit_storage"
+                              Name 4  "main"
+                              Name 12  "compare_uint8_t(u1;u1;"
+                              Name 10  "a"
+                              Name 11  "b"
+                              Name 20  "allOk"
+                              Name 26  "PC"
+                              MemberName 26(PC) 0  "block"
+                              Name 28  "Block"
+                              MemberName 28(Block) 0  "var"
+                              Name 30  ""
+                              Name 41  "param"
+                              Name 42  "param"
+                              Name 48  "AcBlock"
+                              MemberName 48(AcBlock) 0  "ac_numPassed"
+                              Name 50  ""
+                              MemberDecorate 26(PC) 0 Offset 0
+                              Decorate 26(PC) Block
+                              MemberDecorate 28(Block) 0 Offset 0
+                              Decorate 28(Block) Block
+                              MemberDecorate 48(AcBlock) 0 Offset 0
+                              Decorate 48(AcBlock) Block
+                              Decorate 50 DescriptorSet 0
+                              Decorate 50 Binding 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 0
+               7:             TypePointer Function 6(int)
+               8:             TypeBool
+               9:             TypeFunction 8(bool) 7(ptr) 7(ptr)
+              19:             TypePointer Function 8(bool)
+              21:     8(bool) ConstantTrue
+                              TypeForwardPointer 25 PhysicalStorageBufferEXT
+          26(PC):             TypeStruct 25
+              27:             TypeInt 8 0
+       28(Block):             TypeStruct 27(int8_t)
+              25:             TypePointer PhysicalStorageBufferEXT 28(Block)
+              29:             TypePointer PushConstant 26(PC)
+              30:     29(ptr) Variable PushConstant
+              31:             TypeInt 32 1
+              32:     31(int) Constant 0
+              33:             TypePointer PushConstant 25(ptr)
+              36:             TypePointer PhysicalStorageBufferEXT 27(int8_t)
+              40:      6(int) Constant 7
+     48(AcBlock):             TypeStruct 6(int)
+              49:             TypePointer StorageBuffer 48(AcBlock)
+              50:     49(ptr) Variable StorageBuffer
+              51:             TypePointer StorageBuffer 6(int)
+              54:     31(int) Constant 1
+              58:  27(int8_t) Constant 9
+         4(main):           2 Function None 3
+               5:             Label
+       20(allOk):     19(ptr) Variable Function
+       41(param):      7(ptr) Variable Function
+       42(param):      7(ptr) Variable Function
+                              Store 20(allOk) 21
+              22:     8(bool) Load 20(allOk)
+                              SelectionMerge 24 None
+                              BranchConditional 22 23 24
+              23:               Label
+              34:     33(ptr)   AccessChain 30 32
+              35:     25(ptr)   Load 34
+              37:     36(ptr)   AccessChain 35 32
+              38:  27(int8_t)   Load 37 Aligned 16
+              39:      6(int)   UConvert 38
+                                Store 41(param) 39
+                                Store 42(param) 40
+              43:     8(bool)   FunctionCall 12(compare_uint8_t(u1;u1;) 41(param) 42(param)
+                                Branch 24
+              24:             Label
+              44:     8(bool) Phi 22 5 43 23
+                              Store 20(allOk) 44
+              45:     8(bool) Load 20(allOk)
+                              SelectionMerge 47 None
+                              BranchConditional 45 46 47
+              46:               Label
+              52:     51(ptr)   AccessChain 50 32
+              53:      6(int)   Load 52
+              55:      6(int)   IAdd 53 54
+                                Store 52 55
+                                Branch 47
+              47:             Label
+              56:     33(ptr) AccessChain 30 32
+              57:     25(ptr) Load 56
+              59:     36(ptr) AccessChain 57 32
+                              Store 59 58 Aligned 16
+                              Return
+                              FunctionEnd
+12(compare_uint8_t(u1;u1;):     8(bool) Function None 9
+           10(a):      7(ptr) FunctionParameter
+           11(b):      7(ptr) FunctionParameter
+              13:             Label
+              14:      6(int) Load 10(a)
+              15:      6(int) Load 11(b)
+              16:     8(bool) IEqual 14 15
+                              ReturnValue 16
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle12.frag.out b/Test/baseResults/spv.bufferhandle12.frag.out
new file mode 100644
index 0000000..38b390f
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle12.frag.out
@@ -0,0 +1,306 @@
+spv.bufferhandle12.frag
+WARNING: 0:6: '' : all default precisions are highp; use precision statements to quiet warning, e.g.:
+         "precision mediump int; precision highp float;" 
+
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 183
+
+                              Capability Shader
+                              Capability StorageUniformBufferBlock16
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_16bit_storage"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              SourceExtension  "GL_EXT_shader_16bit_storage"
+                              SourceExtension  "GL_EXT_shader_8bit_storage"
+                              Name 4  "main"
+                              Name 12  "compare_float(f1;f1;"
+                              Name 10  "a"
+                              Name 11  "b"
+                              Name 19  "compare_vec3(vf3;vf3;"
+                              Name 17  "a"
+                              Name 18  "b"
+                              Name 26  "compare_mat2x3(mf23;mf23;"
+                              Name 24  "a"
+                              Name 25  "b"
+                              Name 34  "compare_ivec2(vi2;vi2;"
+                              Name 32  "a"
+                              Name 33  "b"
+                              Name 42  "compare_uvec3(vu3;vu3;"
+                              Name 40  "a"
+                              Name 41  "b"
+                              Name 46  "compare_float16_t(f1;f1;"
+                              Name 44  "a"
+                              Name 45  "b"
+                              Name 56  "param"
+                              Name 60  "param"
+                              Name 66  "param"
+                              Name 70  "param"
+                              Name 77  "param"
+                              Name 81  "param"
+                              Name 89  "param"
+                              Name 92  "param"
+                              Name 99  "param"
+                              Name 102  "param"
+                              Name 131  "allOk"
+                              Name 139  "PC"
+                              MemberName 139(PC) 0  "blockB"
+                              MemberName 139(PC) 1  "blockC"
+                              MemberName 139(PC) 2  "blockD"
+                              Name 141  "BlockB"
+                              MemberName 141(BlockB) 0  "a"
+                              MemberName 141(BlockB) 1  "b"
+                              Name 142  "BlockC"
+                              MemberName 142(BlockC) 0  "c"
+                              Name 143  "BlockD"
+                              MemberName 143(BlockD) 0  "d"
+                              Name 145  ""
+                              Name 157  "param"
+                              Name 161  "param"
+                              Name 167  "AcBlock"
+                              MemberName 167(AcBlock) 0  "ac_numPassed"
+                              Name 169  ""
+                              MemberDecorate 139(PC) 0 Offset 0
+                              MemberDecorate 139(PC) 1 Offset 8
+                              MemberDecorate 139(PC) 2 Offset 16
+                              Decorate 139(PC) Block
+                              MemberDecorate 141(BlockB) 0 Offset 0
+                              MemberDecorate 141(BlockB) 1 Offset 8
+                              Decorate 141(BlockB) Block
+                              MemberDecorate 142(BlockC) 0 ColMajor
+                              MemberDecorate 142(BlockC) 0 RelaxedPrecision
+                              MemberDecorate 142(BlockC) 0 Offset 0
+                              MemberDecorate 142(BlockC) 0 MatrixStride 16
+                              Decorate 142(BlockC) Block
+                              MemberDecorate 143(BlockD) 0 RelaxedPrecision
+                              MemberDecorate 143(BlockD) 0 Offset 0
+                              Decorate 143(BlockD) Block
+                              Decorate 160 RelaxedPrecision
+                              MemberDecorate 167(AcBlock) 0 Offset 0
+                              Decorate 167(AcBlock) Block
+                              Decorate 169 DescriptorSet 0
+                              Decorate 169 Binding 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypePointer Function 6(float)
+               8:             TypeBool
+               9:             TypeFunction 8(bool) 7(ptr) 7(ptr)
+              14:             TypeVector 6(float) 3
+              15:             TypePointer Function 14(fvec3)
+              16:             TypeFunction 8(bool) 15(ptr) 15(ptr)
+              21:             TypeMatrix 14(fvec3) 2
+              22:             TypePointer Function 21
+              23:             TypeFunction 8(bool) 22(ptr) 22(ptr)
+              28:             TypeInt 32 1
+              29:             TypeVector 28(int) 2
+              30:             TypePointer Function 29(ivec2)
+              31:             TypeFunction 8(bool) 30(ptr) 30(ptr)
+              36:             TypeInt 32 0
+              37:             TypeVector 36(int) 3
+              38:             TypePointer Function 37(ivec3)
+              39:             TypeFunction 8(bool) 38(ptr) 38(ptr)
+              52:    6(float) Constant 1028443341
+              57:     36(int) Constant 0
+              67:     36(int) Constant 1
+              78:     36(int) Constant 2
+              88:     28(int) Constant 0
+              98:     28(int) Constant 1
+             111:             TypeVector 8(bool) 2
+             118:             TypeVector 8(bool) 3
+             130:             TypePointer Function 8(bool)
+             132:     8(bool) ConstantTrue
+                              TypeForwardPointer 136 PhysicalStorageBufferEXT
+                              TypeForwardPointer 137 PhysicalStorageBufferEXT
+                              TypeForwardPointer 138 PhysicalStorageBufferEXT
+         139(PC):             TypeStruct 136 137 138
+             140:             TypeFloat 16
+     141(BlockB):             TypeStruct 140(float16_t) 29(ivec2)
+             136:             TypePointer PhysicalStorageBufferEXT 141(BlockB)
+     142(BlockC):             TypeStruct 21
+             137:             TypePointer PhysicalStorageBufferEXT 142(BlockC)
+     143(BlockD):             TypeStruct 37(ivec3)
+             138:             TypePointer PhysicalStorageBufferEXT 143(BlockD)
+             144:             TypePointer PushConstant 139(PC)
+             145:    144(ptr) Variable PushConstant
+             146:             TypePointer PushConstant 137(ptr)
+             149:    6(float) Constant 3231711232
+             150:    6(float) Constant 1065353216
+             151:    6(float) Constant 3235905536
+             152:   14(fvec3) ConstantComposite 149 150 151
+             153:    6(float) Constant 1073741824
+             154:    6(float) Constant 1090519040
+             155:   14(fvec3) ConstantComposite 150 153 154
+             156:          21 ConstantComposite 152 155
+             158:             TypePointer PhysicalStorageBufferEXT 21
+    167(AcBlock):             TypeStruct 36(int)
+             168:             TypePointer StorageBuffer 167(AcBlock)
+             169:    168(ptr) Variable StorageBuffer
+             170:             TypePointer StorageBuffer 36(int)
+             174:     28(int) Constant 2
+             175:             TypePointer PushConstant 138(ptr)
+             178:     36(int) Constant 8
+             179:     36(int) Constant 5
+             180:   37(ivec3) ConstantComposite 178 67 179
+             181:             TypePointer PhysicalStorageBufferEXT 37(ivec3)
+         4(main):           2 Function None 3
+               5:             Label
+      131(allOk):    130(ptr) Variable Function
+      157(param):     22(ptr) Variable Function
+      161(param):     22(ptr) Variable Function
+                              Store 131(allOk) 132
+             133:     8(bool) Load 131(allOk)
+                              SelectionMerge 135 None
+                              BranchConditional 133 134 135
+             134:               Label
+             147:    146(ptr)   AccessChain 145 98
+             148:    137(ptr)   Load 147
+             159:    158(ptr)   AccessChain 148 88
+             160:          21   Load 159 Aligned 16
+                                Store 157(param) 160
+                                Store 161(param) 156
+             162:     8(bool)   FunctionCall 26(compare_mat2x3(mf23;mf23;) 157(param) 161(param)
+                                Branch 135
+             135:             Label
+             163:     8(bool) Phi 133 5 162 134
+                              Store 131(allOk) 163
+             164:     8(bool) Load 131(allOk)
+                              SelectionMerge 166 None
+                              BranchConditional 164 165 166
+             165:               Label
+             171:    170(ptr)   AccessChain 169 88
+             172:     36(int)   Load 171
+             173:     36(int)   IAdd 172 98
+                                Store 171 173
+                                Branch 166
+             166:             Label
+             176:    175(ptr) AccessChain 145 174
+             177:    138(ptr) Load 176
+             182:    181(ptr) AccessChain 177 88
+                              Store 182 180 Aligned 16
+                              Return
+                              FunctionEnd
+12(compare_float(f1;f1;):     8(bool) Function None 9
+           10(a):      7(ptr) FunctionParameter
+           11(b):      7(ptr) FunctionParameter
+              13:             Label
+              48:    6(float) Load 10(a)
+              49:    6(float) Load 11(b)
+              50:    6(float) FSub 48 49
+              51:    6(float) ExtInst 1(GLSL.std.450) 4(FAbs) 50
+              53:     8(bool) FOrdLessThan 51 52
+                              ReturnValue 53
+                              FunctionEnd
+19(compare_vec3(vf3;vf3;):     8(bool) Function None 16
+           17(a):     15(ptr) FunctionParameter
+           18(b):     15(ptr) FunctionParameter
+              20:             Label
+       56(param):      7(ptr) Variable Function
+       60(param):      7(ptr) Variable Function
+       66(param):      7(ptr) Variable Function
+       70(param):      7(ptr) Variable Function
+       77(param):      7(ptr) Variable Function
+       81(param):      7(ptr) Variable Function
+              58:      7(ptr) AccessChain 17(a) 57
+              59:    6(float) Load 58
+                              Store 56(param) 59
+              61:      7(ptr) AccessChain 18(b) 57
+              62:    6(float) Load 61
+                              Store 60(param) 62
+              63:     8(bool) FunctionCall 12(compare_float(f1;f1;) 56(param) 60(param)
+                              SelectionMerge 65 None
+                              BranchConditional 63 64 65
+              64:               Label
+              68:      7(ptr)   AccessChain 17(a) 67
+              69:    6(float)   Load 68
+                                Store 66(param) 69
+              71:      7(ptr)   AccessChain 18(b) 67
+              72:    6(float)   Load 71
+                                Store 70(param) 72
+              73:     8(bool)   FunctionCall 12(compare_float(f1;f1;) 66(param) 70(param)
+                                Branch 65
+              65:             Label
+              74:     8(bool) Phi 63 20 73 64
+                              SelectionMerge 76 None
+                              BranchConditional 74 75 76
+              75:               Label
+              79:      7(ptr)   AccessChain 17(a) 78
+              80:    6(float)   Load 79
+                                Store 77(param) 80
+              82:      7(ptr)   AccessChain 18(b) 78
+              83:    6(float)   Load 82
+                                Store 81(param) 83
+              84:     8(bool)   FunctionCall 12(compare_float(f1;f1;) 77(param) 81(param)
+                                Branch 76
+              76:             Label
+              85:     8(bool) Phi 74 65 84 75
+                              ReturnValue 85
+                              FunctionEnd
+26(compare_mat2x3(mf23;mf23;):     8(bool) Function None 23
+           24(a):     22(ptr) FunctionParameter
+           25(b):     22(ptr) FunctionParameter
+              27:             Label
+       89(param):     15(ptr) Variable Function
+       92(param):     15(ptr) Variable Function
+       99(param):     15(ptr) Variable Function
+      102(param):     15(ptr) Variable Function
+              90:     15(ptr) AccessChain 24(a) 88
+              91:   14(fvec3) Load 90
+                              Store 89(param) 91
+              93:     15(ptr) AccessChain 25(b) 88
+              94:   14(fvec3) Load 93
+                              Store 92(param) 94
+              95:     8(bool) FunctionCall 19(compare_vec3(vf3;vf3;) 89(param) 92(param)
+                              SelectionMerge 97 None
+                              BranchConditional 95 96 97
+              96:               Label
+             100:     15(ptr)   AccessChain 24(a) 98
+             101:   14(fvec3)   Load 100
+                                Store 99(param) 101
+             103:     15(ptr)   AccessChain 25(b) 98
+             104:   14(fvec3)   Load 103
+                                Store 102(param) 104
+             105:     8(bool)   FunctionCall 19(compare_vec3(vf3;vf3;) 99(param) 102(param)
+                                Branch 97
+              97:             Label
+             106:     8(bool) Phi 95 27 105 96
+                              ReturnValue 106
+                              FunctionEnd
+34(compare_ivec2(vi2;vi2;):     8(bool) Function None 31
+           32(a):     30(ptr) FunctionParameter
+           33(b):     30(ptr) FunctionParameter
+              35:             Label
+             109:   29(ivec2) Load 32(a)
+             110:   29(ivec2) Load 33(b)
+             112:  111(bvec2) IEqual 109 110
+             113:     8(bool) All 112
+                              ReturnValue 113
+                              FunctionEnd
+42(compare_uvec3(vu3;vu3;):     8(bool) Function None 39
+           40(a):     38(ptr) FunctionParameter
+           41(b):     38(ptr) FunctionParameter
+              43:             Label
+             116:   37(ivec3) Load 40(a)
+             117:   37(ivec3) Load 41(b)
+             119:  118(bvec3) IEqual 116 117
+             120:     8(bool) All 119
+                              ReturnValue 120
+                              FunctionEnd
+46(compare_float16_t(f1;f1;):     8(bool) Function None 9
+           44(a):      7(ptr) FunctionParameter
+           45(b):      7(ptr) FunctionParameter
+              47:             Label
+             123:    6(float) Load 44(a)
+             124:    6(float) Load 45(b)
+             125:    6(float) FSub 123 124
+             126:    6(float) ExtInst 1(GLSL.std.450) 4(FAbs) 125
+             127:     8(bool) FOrdLessThan 126 52
+                              ReturnValue 127
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle13.frag.out b/Test/baseResults/spv.bufferhandle13.frag.out
new file mode 100644
index 0000000..1438086
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle13.frag.out
@@ -0,0 +1,118 @@
+spv.bufferhandle13.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 58
+
+                              Capability Shader
+                              Capability CapabilityVulkanMemoryModelKHR
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+                              Extension  "SPV_KHR_vulkan_memory_model"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT VulkanKHR
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 8  "t4"
+                              MemberName 8(t4) 0  "j"
+                              Name 11  "f1(1;"
+                              Name 10  "y"
+                              Name 16  "f2(1;"
+                              Name 15  "y"
+                              Name 19  "f3(1;"
+                              Name 18  "y"
+                              Name 22  "f4(1;"
+                              Name 21  "y"
+                              Name 34  "a"
+                              Name 35  "t5"
+                              MemberName 35(t5) 0  "m"
+                              Name 37  "s5"
+                              Name 42  "b"
+                              Name 47  "param"
+                              Name 52  "param"
+                              Name 56  "g1"
+                              Name 57  "g2"
+                              MemberDecorate 8(t4) 0 Offset 0
+                              Decorate 8(t4) Block
+                              Decorate 10(y) Aliased
+                              Decorate 15(y) DecorationAliasedPointerEXT
+                              Decorate 18(y) Restrict
+                              Decorate 18(y) Restrict
+                              Decorate 21(y) Restrict
+                              Decorate 21(y) DecorationRestrictPointerEXT
+                              Decorate 34(a) DecorationAliasedPointerEXT
+                              MemberDecorate 35(t5) 0 Offset 0
+                              Decorate 35(t5) Block
+                              Decorate 37(s5) DescriptorSet 0
+                              Decorate 37(s5) Binding 0
+                              Decorate 42(b) DecorationRestrictPointerEXT
+                              Decorate 56(g1) DecorationAliasedPointerEXT
+                              Decorate 57(g2) DecorationRestrictPointerEXT
+                              Decorate 47(param) DecorationAliasedPointerEXT
+                              Decorate 52(param) DecorationAliasedPointerEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+               7:             TypeInt 32 1
+           8(t4):             TypeStruct 7(int)
+               6:             TypePointer PhysicalStorageBufferEXT 8(t4)
+               9:             TypeFunction 6(ptr) 6(ptr)
+              13:             TypePointer Function 6(ptr)
+              14:             TypeFunction 6(ptr) 13(ptr)
+          35(t5):             TypeStruct 6(ptr)
+              36:             TypePointer StorageBuffer 35(t5)
+          37(s5):     36(ptr) Variable StorageBuffer
+              38:      7(int) Constant 0
+              39:             TypePointer StorageBuffer 6(ptr)
+              55:             TypePointer Private 6(ptr)
+          56(g1):     55(ptr) Variable Private
+         4(main):           2 Function None 3
+               5:             Label
+           34(a):     13(ptr) Variable Function
+           42(b):     13(ptr) Variable Function
+       47(param):     13(ptr) Variable Function
+       52(param):     13(ptr) Variable Function
+          57(g2):     13(ptr) Variable Function
+              40:     39(ptr) AccessChain 37(s5) 38
+              41:      6(ptr) Load 40
+                              Store 34(a) 41
+              43:     39(ptr) AccessChain 37(s5) 38
+              44:      6(ptr) Load 43
+                              Store 42(b) 44
+              45:      6(ptr) Load 34(a)
+              46:      6(ptr) FunctionCall 11(f1(1;) 45
+              48:      6(ptr) Load 34(a)
+                              Store 47(param) 48
+              49:      6(ptr) FunctionCall 16(f2(1;) 47(param)
+              50:      6(ptr) Load 34(a)
+              51:      6(ptr) FunctionCall 19(f3(1;) 50
+              53:      6(ptr) Load 34(a)
+                              Store 52(param) 53
+              54:      6(ptr) FunctionCall 22(f4(1;) 52(param)
+                              Return
+                              FunctionEnd
+       11(f1(1;):      6(ptr) Function None 9
+           10(y):      6(ptr) FunctionParameter
+              12:             Label
+                              ReturnValue 10(y)
+                              FunctionEnd
+       16(f2(1;):      6(ptr) Function None 14
+           15(y):     13(ptr) FunctionParameter
+              17:             Label
+              26:      6(ptr) Load 15(y)
+                              ReturnValue 26
+                              FunctionEnd
+       19(f3(1;):      6(ptr) Function None 9
+           18(y):      6(ptr) FunctionParameter
+              20:             Label
+                              ReturnValue 18(y)
+                              FunctionEnd
+       22(f4(1;):      6(ptr) Function None 14
+           21(y):     13(ptr) FunctionParameter
+              23:             Label
+              31:      6(ptr) Load 21(y)
+                              ReturnValue 31
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle14.frag.out b/Test/baseResults/spv.bufferhandle14.frag.out
new file mode 100644
index 0000000..d8c2726
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle14.frag.out
@@ -0,0 +1,109 @@
+spv.bufferhandle14.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 46
+
+                              Capability Shader
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 8  "T1"
+                              MemberName 8(T1) 0  "i"
+                              MemberName 8(T1) 1  "j"
+                              MemberName 8(T1) 2  "k"
+                              Name 10  "t1"
+                              Name 20  "T2"
+                              MemberName 20(T2) 0  "i"
+                              MemberName 20(T2) 1  "j"
+                              MemberName 20(T2) 2  "k"
+                              Name 22  "t2"
+                              Name 29  "T3"
+                              MemberName 29(T3) 0  "i"
+                              MemberName 29(T3) 1  "j"
+                              MemberName 29(T3) 2  "k"
+                              Name 31  "t3"
+                              Name 38  "T4"
+                              MemberName 38(T4) 0  "i"
+                              MemberName 38(T4) 1  "j"
+                              MemberName 38(T4) 2  "k"
+                              Name 40  "t4"
+                              MemberDecorate 8(T1) 0 Offset 0
+                              MemberDecorate 8(T1) 1 Offset 4
+                              MemberDecorate 8(T1) 2 Offset 8
+                              Decorate 8(T1) Block
+                              Decorate 10(t1) DecorationAliasedPointerEXT
+                              MemberDecorate 20(T2) 0 Offset 0
+                              MemberDecorate 20(T2) 1 Offset 4
+                              MemberDecorate 20(T2) 2 Offset 8
+                              Decorate 20(T2) Block
+                              Decorate 22(t2) DecorationAliasedPointerEXT
+                              MemberDecorate 29(T3) 0 Offset 0
+                              MemberDecorate 29(T3) 1 Offset 4
+                              MemberDecorate 29(T3) 2 Offset 8
+                              Decorate 29(T3) Block
+                              Decorate 31(t3) DecorationAliasedPointerEXT
+                              MemberDecorate 38(T4) 0 Offset 0
+                              MemberDecorate 38(T4) 1 Offset 4
+                              MemberDecorate 38(T4) 2 Offset 8
+                              Decorate 38(T4) Block
+                              Decorate 40(t4) DecorationAliasedPointerEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+               7:             TypeInt 32 1
+           8(T1):             TypeStruct 7(int) 7(int) 7(int)
+               6:             TypePointer PhysicalStorageBufferEXT 8(T1)
+               9:             TypePointer Function 6(ptr)
+              12:      7(int) Constant 0
+              14:      7(int) Constant 2
+              15:             TypePointer PhysicalStorageBufferEXT 7(int)
+                              TypeForwardPointer 19 PhysicalStorageBufferEXT
+          20(T2):             TypeStruct 7(int) 7(int) 7(int)
+              19:             TypePointer PhysicalStorageBufferEXT 20(T2)
+              21:             TypePointer Function 19(ptr)
+                              TypeForwardPointer 28 PhysicalStorageBufferEXT
+          29(T3):             TypeStruct 7(int) 7(int) 7(int)
+              28:             TypePointer PhysicalStorageBufferEXT 29(T3)
+              30:             TypePointer Function 28(ptr)
+                              TypeForwardPointer 37 PhysicalStorageBufferEXT
+          38(T4):             TypeStruct 7(int) 7(int) 7(int)
+              37:             TypePointer PhysicalStorageBufferEXT 38(T4)
+              39:             TypePointer Function 37(ptr)
+         4(main):           2 Function None 3
+               5:             Label
+          10(t1):      9(ptr) Variable Function
+          22(t2):     21(ptr) Variable Function
+          31(t3):     30(ptr) Variable Function
+          40(t4):     39(ptr) Variable Function
+              11:      6(ptr) Load 10(t1)
+              13:      6(ptr) Load 10(t1)
+              16:     15(ptr) AccessChain 13 14
+              17:      7(int) Load 16 Aligned 4
+              18:     15(ptr) AccessChain 11 12
+                              Store 18 17 Aligned 4
+              23:     19(ptr) Load 22(t2)
+              24:     19(ptr) Load 22(t2)
+              25:     15(ptr) AccessChain 24 14
+              26:      7(int) Load 25 Aligned 8
+              27:     15(ptr) AccessChain 23 12
+                              Store 27 26 Aligned 8
+              32:     28(ptr) Load 31(t3)
+              33:     28(ptr) Load 31(t3)
+              34:     15(ptr) AccessChain 33 14
+              35:      7(int) Load 34 Aligned 8
+              36:     15(ptr) AccessChain 32 12
+                              Store 36 35 Aligned 16
+              41:     37(ptr) Load 40(t4)
+              42:     37(ptr) Load 40(t4)
+              43:     15(ptr) AccessChain 42 14
+              44:      7(int) Load 43 Aligned 8
+              45:     15(ptr) AccessChain 41 12
+                              Store 45 44 Aligned 32
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle15.frag.out b/Test/baseResults/spv.bufferhandle15.frag.out
new file mode 100644
index 0000000..a4a434d
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle15.frag.out
@@ -0,0 +1,130 @@
+spv.bufferhandle15.frag
+WARNING: 0:16: '' : all default precisions are highp; use precision statements to quiet warning, e.g.:
+         "precision mediump int; precision highp float;" 
+
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 60
+
+                              Capability Shader
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main" 37
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              SourceExtension  "GL_EXT_scalar_block_layout"
+                              Name 4  "main"
+                              Name 9  "y"
+                              Name 13  "T4"
+                              MemberName 13(T4) 0  "t1"
+                              MemberName 13(T4) 1  "t2"
+                              MemberName 13(T4) 2  "t3"
+                              Name 15  "T1"
+                              MemberName 15(T1) 0  "x"
+                              Name 22  "T2"
+                              MemberName 22(T2) 0  "x"
+                              Name 28  "S"
+                              MemberName 28(S) 0  "a"
+                              MemberName 28(S) 1  "b"
+                              MemberName 28(S) 2  "c"
+                              Name 29  "T3"
+                              MemberName 29(T3) 0  "s"
+                              Name 31  "t4"
+                              Name 37  "i"
+                              Name 52  "z"
+                              MemberDecorate 13(T4) 0 Offset 0
+                              MemberDecorate 13(T4) 1 Offset 8
+                              MemberDecorate 13(T4) 2 Offset 16
+                              Decorate 13(T4) Block
+                              Decorate 14 ArrayStride 12
+                              MemberDecorate 15(T1) 0 Offset 0
+                              Decorate 15(T1) Block
+                              Decorate 18 ArrayStride 12
+                              Decorate 20 ArrayStride 24
+                              Decorate 21 ArrayStride 96
+                              MemberDecorate 22(T2) 0 Offset 0
+                              Decorate 22(T2) Block
+                              Decorate 26 ArrayStride 36
+                              MemberDecorate 28(S) 0 Offset 0
+                              MemberDecorate 28(S) 1 ColMajor
+                              MemberDecorate 28(S) 1 RelaxedPrecision
+                              MemberDecorate 28(S) 1 Offset 12
+                              MemberDecorate 28(S) 1 MatrixStride 12
+                              MemberDecorate 28(S) 2 Offset 156
+                              MemberDecorate 29(T3) 0 Offset 0
+                              Decorate 29(T3) Block
+                              Decorate 31(t4) DescriptorSet 0
+                              Decorate 31(t4) Binding 0
+                              Decorate 37(i) Flat
+                              Decorate 37(i) Location 0
+                              Decorate 59 RelaxedPrecision
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 3
+               8:             TypePointer Function 7(fvec3)
+                              TypeForwardPointer 10 PhysicalStorageBufferEXT
+                              TypeForwardPointer 11 PhysicalStorageBufferEXT
+                              TypeForwardPointer 12 PhysicalStorageBufferEXT
+          13(T4):             TypeStruct 10 11 12
+              14:             TypeRuntimeArray 7(fvec3)
+          15(T1):             TypeStruct 14
+              10:             TypePointer PhysicalStorageBufferEXT 15(T1)
+              16:             TypeInt 32 0
+              17:     16(int) Constant 2
+              18:             TypeArray 7(fvec3) 17
+              19:     16(int) Constant 4
+              20:             TypeArray 18 19
+              21:             TypeRuntimeArray 20
+          22(T2):             TypeStruct 21
+              11:             TypePointer PhysicalStorageBufferEXT 22(T2)
+              23:             TypeInt 32 1
+              24:             TypeVector 23(int) 3
+              25:             TypeMatrix 7(fvec3) 3
+              26:             TypeArray 25 19
+              27:             TypeVector 6(float) 4
+           28(S):             TypeStruct 24(ivec3) 26 27(fvec4)
+          29(T3):             TypeStruct 28(S)
+              12:             TypePointer PhysicalStorageBufferEXT 29(T3)
+              30:             TypePointer StorageBuffer 13(T4)
+          31(t4):     30(ptr) Variable StorageBuffer
+              32:     23(int) Constant 0
+              33:             TypePointer StorageBuffer 10(ptr)
+              36:             TypePointer Input 23(int)
+           37(i):     36(ptr) Variable Input
+              39:             TypePointer PhysicalStorageBufferEXT 7(fvec3)
+              42:     23(int) Constant 1
+              43:             TypePointer StorageBuffer 11(ptr)
+              51:             TypePointer Function 25
+              53:     23(int) Constant 2
+              54:             TypePointer StorageBuffer 12(ptr)
+              57:             TypePointer PhysicalStorageBufferEXT 25
+         4(main):           2 Function None 3
+               5:             Label
+            9(y):      8(ptr) Variable Function
+           52(z):     51(ptr) Variable Function
+              34:     33(ptr) AccessChain 31(t4) 32
+              35:     10(ptr) Load 34
+              38:     23(int) Load 37(i)
+              40:     39(ptr) AccessChain 35 32 38
+              41:    7(fvec3) Load 40 Aligned 4
+                              Store 9(y) 41
+              44:     43(ptr) AccessChain 31(t4) 42
+              45:     11(ptr) Load 44
+              46:     23(int) Load 37(i)
+              47:     23(int) Load 37(i)
+              48:     23(int) Load 37(i)
+              49:     39(ptr) AccessChain 45 32 46 47 48
+              50:    7(fvec3) Load 49 Aligned 4
+                              Store 9(y) 50
+              55:     54(ptr) AccessChain 31(t4) 53
+              56:     12(ptr) Load 55
+              58:     57(ptr) AccessChain 56 32 42 32
+              59:          25 Load 58 Aligned 4
+                              Store 52(z) 59
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle2.frag.out b/Test/baseResults/spv.bufferhandle2.frag.out
new file mode 100644
index 0000000..fbcf16c
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle2.frag.out
@@ -0,0 +1,94 @@
+spv.bufferhandle2.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 45
+
+                              Capability Shader
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 8  "blockType"
+                              MemberName 8(blockType) 0  "a"
+                              MemberName 8(blockType) 1  "b"
+                              MemberName 8(blockType) 2  "c"
+                              MemberName 8(blockType) 3  "d"
+                              MemberName 8(blockType) 4  "e"
+                              Name 13  "b1"
+                              Name 14  "t2"
+                              MemberName 14(t2) 0  "f"
+                              MemberName 14(t2) 1  "g"
+                              Name 16  "t"
+                              Name 34  "b2"
+                              Name 37  "b3"
+                              MemberDecorate 8(blockType) 0 Offset 0
+                              MemberDecorate 8(blockType) 1 Offset 4
+                              MemberDecorate 8(blockType) 2 Offset 8
+                              MemberDecorate 8(blockType) 3 Offset 12
+                              MemberDecorate 8(blockType) 4 Offset 16
+                              Decorate 8(blockType) Block
+                              Decorate 13(b1) DecorationAliasedPointerEXT
+                              MemberDecorate 14(t2) 0 Offset 0
+                              MemberDecorate 14(t2) 1 Offset 8
+                              Decorate 14(t2) Block
+                              Decorate 16(t) DescriptorSet 0
+                              Decorate 16(t) Binding 0
+                              Decorate 34(b2) DecorationAliasedPointerEXT
+                              Decorate 37(b3) DecorationAliasedPointerEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+               7:             TypeInt 32 1
+    8(blockType):             TypeStruct 7(int) 7(int) 7(int) 7(int) 7(int)
+               6:             TypePointer PhysicalStorageBufferEXT 8(blockType)
+               9:             TypeInt 32 0
+              10:      9(int) Constant 2
+              11:             TypeArray 6(ptr) 10
+              12:             TypePointer Function 11
+          14(t2):             TypeStruct 6(ptr) 6(ptr)
+              15:             TypePointer StorageBuffer 14(t2)
+           16(t):     15(ptr) Variable StorageBuffer
+              17:      7(int) Constant 0
+              18:             TypePointer StorageBuffer 6(ptr)
+              21:      7(int) Constant 1
+              25:             TypePointer Function 6(ptr)
+              30:             TypePointer PhysicalStorageBufferEXT 7(int)
+         4(main):           2 Function None 3
+               5:             Label
+          13(b1):     12(ptr) Variable Function
+          34(b2):     25(ptr) Variable Function
+          37(b3):     25(ptr) Variable Function
+              19:     18(ptr) AccessChain 16(t) 17
+              20:      6(ptr) Load 19
+              22:     18(ptr) AccessChain 16(t) 21
+              23:      6(ptr) Load 22
+              24:          11 CompositeConstruct 20 23
+                              Store 13(b1) 24
+              26:     25(ptr) AccessChain 13(b1) 17
+              27:      6(ptr) Load 26
+              28:     25(ptr) AccessChain 13(b1) 21
+              29:      6(ptr) Load 28
+              31:     30(ptr) AccessChain 29 21
+              32:      7(int) Load 31 Aligned 4
+              33:     30(ptr) AccessChain 27 17
+                              Store 33 32 Aligned 16
+              35:     18(ptr) AccessChain 16(t) 17
+              36:      6(ptr) Load 35
+                              Store 34(b2) 36
+              38:     18(ptr) AccessChain 16(t) 21
+              39:      6(ptr) Load 38
+                              Store 37(b3) 39
+              40:      6(ptr) Load 34(b2)
+              41:      6(ptr) Load 37(b3)
+              42:     30(ptr) AccessChain 41 21
+              43:      7(int) Load 42 Aligned 4
+              44:     30(ptr) AccessChain 40 17
+                              Store 44 43 Aligned 16
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle3.frag.out b/Test/baseResults/spv.bufferhandle3.frag.out
new file mode 100644
index 0000000..a2cb85f
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle3.frag.out
@@ -0,0 +1,105 @@
+spv.bufferhandle3.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 50
+
+                              Capability Shader
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main" 42
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 9  "t4"
+                              MemberName 9(t4) 0  "j"
+                              MemberName 9(t4) 1  "k"
+                              Name 10  "t3"
+                              MemberName 10(t3) 0  "h"
+                              Name 14  "foo(1;"
+                              Name 13  "y"
+                              Name 19  "t5"
+                              MemberName 19(t5) 0  "m"
+                              Name 21  "s5"
+                              Name 23  "param"
+                              Name 38  "t4"
+                              MemberName 38(t4) 0  "j"
+                              MemberName 38(t4) 1  "k"
+                              Name 40  "x"
+                              Name 42  "k"
+                              MemberDecorate 9(t4) 0 Offset 0
+                              MemberDecorate 9(t4) 1 Offset 8
+                              Decorate 9(t4) Block
+                              MemberDecorate 10(t3) 0 Offset 0
+                              Decorate 10(t3) Block
+                              Decorate 13(y) DecorationAliasedPointerEXT
+                              MemberDecorate 19(t5) 0 Offset 0
+                              Decorate 19(t5) Block
+                              Decorate 21(s5) DescriptorSet 0
+                              Decorate 21(s5) Binding 0
+                              MemberDecorate 38(t4) 0 Offset 0
+                              MemberDecorate 38(t4) 1 Offset 8
+                              Decorate 38(t4) Block
+                              Decorate 40(x) DescriptorSet 1
+                              Decorate 40(x) Binding 2
+                              Decorate 42(k) Flat
+                              Decorate 42(k) DecorationAliasedPointerEXT
+                              Decorate 23(param) DecorationAliasedPointerEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+               7:             TypeInt 32 1
+                              TypeForwardPointer 8 PhysicalStorageBufferEXT
+           9(t4):             TypeStruct 7(int) 8
+          10(t3):             TypeStruct 7(int)
+               8:             TypePointer PhysicalStorageBufferEXT 10(t3)
+               6:             TypePointer PhysicalStorageBufferEXT 9(t4)
+              11:             TypePointer Function 6(ptr)
+              12:             TypeFunction 6(ptr) 11(ptr)
+          19(t5):             TypeStruct 6(ptr)
+              20:             TypePointer StorageBuffer 19(t5)
+          21(s5):     20(ptr) Variable StorageBuffer
+              22:      7(int) Constant 0
+              24:             TypePointer StorageBuffer 6(ptr)
+              30:      7(int) Constant 1
+              31:             TypePointer PhysicalStorageBufferEXT 8(ptr)
+              34:             TypePointer PhysicalStorageBufferEXT 7(int)
+          38(t4):             TypeStruct 7(int) 8(ptr)
+              39:             TypePointer StorageBuffer 38(t4)
+           40(x):     39(ptr) Variable StorageBuffer
+              41:             TypePointer Input 6(ptr)
+           42(k):     41(ptr) Variable Input
+              48:             TypePointer StorageBuffer 7(int)
+         4(main):           2 Function None 3
+               5:             Label
+       23(param):     11(ptr) Variable Function
+              25:     24(ptr) AccessChain 21(s5) 22
+              26:      6(ptr) Load 25
+                              Store 23(param) 26
+              27:      6(ptr) FunctionCall 14(foo(1;) 23(param)
+              28:     24(ptr) AccessChain 21(s5) 22
+              29:      6(ptr) Load 28
+              32:     31(ptr) AccessChain 29 30
+              33:      8(ptr) Load 32 Aligned 8
+              35:     34(ptr) AccessChain 33 22
+              36:      7(int) Load 35 Aligned 16
+              37:     34(ptr) AccessChain 27 22
+                              Store 37 36 Aligned 16
+              43:      6(ptr) Load 42(k)
+              44:     31(ptr) AccessChain 43 30
+              45:      8(ptr) Load 44 Aligned 8
+              46:     34(ptr) AccessChain 45 22
+              47:      7(int) Load 46 Aligned 16
+              49:     48(ptr) AccessChain 40(x) 22
+                              Store 49 47
+                              Return
+                              FunctionEnd
+      14(foo(1;):      6(ptr) Function None 12
+           13(y):     11(ptr) FunctionParameter
+              15:             Label
+              16:      6(ptr) Load 13(y)
+                              ReturnValue 16
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle4.frag.out b/Test/baseResults/spv.bufferhandle4.frag.out
new file mode 100644
index 0000000..08de871
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle4.frag.out
@@ -0,0 +1,118 @@
+spv.bufferhandle4.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 61
+
+                              Capability Shader
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 8  "t4"
+                              MemberName 8(t4) 0  "j"
+                              MemberName 8(t4) 1  "k"
+                              Name 10  "t3"
+                              MemberName 10(t3) 0  "h"
+                              MemberName 10(t3) 1  "i"
+                              Name 11  "t4"
+                              MemberName 11(t4) 0  "j"
+                              MemberName 11(t4) 1  "k"
+                              Name 13  "x"
+                              Name 19  "t5"
+                              MemberName 19(t5) 0  "m"
+                              Name 21  "s5"
+                              Name 43  "b"
+                              MemberDecorate 8(t4) 0 Offset 0
+                              MemberDecorate 8(t4) 1 Offset 8
+                              Decorate 8(t4) Block
+                              MemberDecorate 10(t3) 0 Offset 0
+                              MemberDecorate 10(t3) 1 Offset 8
+                              Decorate 10(t3) Block
+                              MemberDecorate 11(t4) 0 Offset 0
+                              MemberDecorate 11(t4) 1 Offset 8
+                              Decorate 11(t4) Block
+                              Decorate 13(x) DescriptorSet 1
+                              Decorate 13(x) Binding 2
+                              MemberDecorate 19(t5) 0 Offset 0
+                              Decorate 19(t5) Block
+                              Decorate 21(s5) DescriptorSet 0
+                              Decorate 21(s5) Binding 0
+                              Decorate 47 DecorationAliasedPointerEXT
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+                              TypeForwardPointer 7 PhysicalStorageBufferEXT
+           8(t4):             TypeStruct 6(int) 7
+                              TypeForwardPointer 9 PhysicalStorageBufferEXT
+          10(t3):             TypeStruct 6(int) 9
+          11(t4):             TypeStruct 6(int) 7
+               9:             TypePointer PhysicalStorageBufferEXT 11(t4)
+               7:             TypePointer PhysicalStorageBufferEXT 10(t3)
+              12:             TypePointer StorageBuffer 8(t4)
+           13(x):     12(ptr) Variable StorageBuffer
+              14:      6(int) Constant 1
+              15:             TypePointer StorageBuffer 7(ptr)
+              18:      6(int) Constant 0
+          19(t5):             TypeStruct 9(ptr)
+              20:             TypePointer StorageBuffer 19(t5)
+          21(s5):     20(ptr) Variable StorageBuffer
+              22:             TypePointer StorageBuffer 9(ptr)
+              25:             TypePointer PhysicalStorageBufferEXT 7(ptr)
+              28:             TypePointer PhysicalStorageBufferEXT 9(ptr)
+              37:             TypePointer PhysicalStorageBufferEXT 6(int)
+              41:             TypeBool
+              42:             TypePointer Function 41(bool)
+              44:    41(bool) ConstantTrue
+              46:             TypePointer Function 9(ptr)
+         4(main):           2 Function None 3
+               5:             Label
+           43(b):     42(ptr) Variable Function
+              47:     46(ptr) Variable Function
+              16:     15(ptr) AccessChain 13(x) 14
+              17:      7(ptr) Load 16
+              23:     22(ptr) AccessChain 21(s5) 18
+              24:      9(ptr) Load 23
+              26:     25(ptr) AccessChain 24 14
+              27:      7(ptr) Load 26 Aligned 8
+              29:     28(ptr) AccessChain 27 14
+              30:      9(ptr) Load 29 Aligned 8
+              31:     25(ptr) AccessChain 30 14
+              32:      7(ptr) Load 31 Aligned 8
+              33:     28(ptr) AccessChain 32 14
+              34:      9(ptr) Load 33 Aligned 8
+              35:     25(ptr) AccessChain 34 14
+              36:      7(ptr) Load 35 Aligned 8
+              38:     37(ptr) AccessChain 36 18
+              39:      6(int) Load 38 Aligned 16
+              40:     37(ptr) AccessChain 17 18
+                              Store 40 39 Aligned 16
+                              Store 43(b) 44
+              45:    41(bool) Load 43(b)
+                              SelectionMerge 49 None
+                              BranchConditional 45 48 52
+              48:               Label
+              50:     22(ptr)   AccessChain 21(s5) 18
+              51:      9(ptr)   Load 50
+                                Store 47 51
+                                Branch 49
+              52:               Label
+              53:     22(ptr)   AccessChain 21(s5) 18
+              54:      9(ptr)   Load 53
+              55:     25(ptr)   AccessChain 54 14
+              56:      7(ptr)   Load 55 Aligned 8
+              57:     28(ptr)   AccessChain 56 14
+              58:      9(ptr)   Load 57 Aligned 8
+                                Store 47 58
+                                Branch 49
+              49:             Label
+              59:      9(ptr) Load 47
+              60:     22(ptr) AccessChain 21(s5) 18
+                              Store 60 59
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle5.frag.out b/Test/baseResults/spv.bufferhandle5.frag.out
new file mode 100644
index 0000000..3656408
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle5.frag.out
@@ -0,0 +1,52 @@
+spv.bufferhandle5.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 22
+
+                              Capability Shader
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 8  "t4"
+                              MemberName 8(t4) 0  "j"
+                              MemberName 8(t4) 1  "k"
+                              Name 9  "t3"
+                              MemberName 9(t3) 0  "h"
+                              Name 11  "x"
+                              MemberDecorate 8(t4) 0 Offset 0
+                              MemberDecorate 8(t4) 1 Offset 8
+                              Decorate 8(t4) Block
+                              MemberDecorate 9(t3) 0 Offset 0
+                              Decorate 9(t3) Block
+                              Decorate 11(x) DescriptorSet 1
+                              Decorate 11(x) Binding 2
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+                              TypeForwardPointer 7 PhysicalStorageBufferEXT
+           8(t4):             TypeStruct 6(int) 7
+           9(t3):             TypeStruct 6(int)
+               7:             TypePointer PhysicalStorageBufferEXT 9(t3)
+              10:             TypePointer Uniform 8(t4)
+           11(x):     10(ptr) Variable Uniform
+              12:      6(int) Constant 1
+              13:             TypePointer Uniform 7(ptr)
+              16:      6(int) Constant 0
+              17:             TypePointer Uniform 6(int)
+              20:             TypePointer PhysicalStorageBufferEXT 6(int)
+         4(main):           2 Function None 3
+               5:             Label
+              14:     13(ptr) AccessChain 11(x) 12
+              15:      7(ptr) Load 14
+              18:     17(ptr) AccessChain 11(x) 16
+              19:      6(int) Load 18
+              21:     20(ptr) AccessChain 15 16
+                              Store 21 19 Aligned 16
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle6.frag.out b/Test/baseResults/spv.bufferhandle6.frag.out
new file mode 100644
index 0000000..54db3cf
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle6.frag.out
@@ -0,0 +1,238 @@
+spv.bufferhandle6.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 165
+
+                              Capability Shader
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main" 154
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 8  "accum"
+                              Name 15  "T1"
+                              MemberName 15(T1) 0  "a"
+                              MemberName 15(T1) 1  "b"
+                              MemberName 15(T1) 2  "c"
+                              MemberName 15(T1) 3  "d"
+                              Name 18  "T1"
+                              MemberName 18(T1) 0  "a"
+                              MemberName 18(T1) 1  "b"
+                              MemberName 18(T1) 2  "c"
+                              MemberName 18(T1) 3  "d"
+                              Name 21  "x"
+                              Name 30  "Block"
+                              MemberName 30(Block) 0  "identity"
+                              Name 32  "pc"
+                              Name 136  "color"
+                              Name 149  "image0_0"
+                              Name 154  "gl_FragCoord"
+                              Decorate 12 ArrayStride 4
+                              Decorate 14 ArrayStride 8
+                              MemberDecorate 15(T1) 0 Offset 0
+                              MemberDecorate 15(T1) 1 Offset 32
+                              MemberDecorate 15(T1) 2 Offset 48
+                              MemberDecorate 15(T1) 3 Offset 80
+                              Decorate 15(T1) Block
+                              Decorate 16 ArrayStride 4
+                              Decorate 17 ArrayStride 8
+                              MemberDecorate 18(T1) 0 Offset 0
+                              MemberDecorate 18(T1) 1 Offset 32
+                              MemberDecorate 18(T1) 2 Offset 48
+                              MemberDecorate 18(T1) 3 Offset 80
+                              Decorate 18(T1) Block
+                              Decorate 19 ArrayStride 8
+                              Decorate 21(x) DescriptorSet 3
+                              Decorate 21(x) Binding 1
+                              Decorate 29 ArrayStride 4
+                              MemberDecorate 30(Block) 0 Offset 0
+                              Decorate 30(Block) Block
+                              Decorate 149(image0_0) DescriptorSet 3
+                              Decorate 149(image0_0) Binding 0
+                              Decorate 154(gl_FragCoord) BuiltIn FragCoord
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:             TypePointer Function 6(int)
+               9:      6(int) Constant 0
+              10:             TypeInt 32 0
+              11:     10(int) Constant 2
+              12:             TypeArray 6(int) 11
+                              TypeForwardPointer 13 PhysicalStorageBufferEXT
+              14:             TypeArray 13 11
+          15(T1):             TypeStruct 12 6(int) 14 13
+              16:             TypeArray 6(int) 11
+              17:             TypeArray 13 11
+          18(T1):             TypeStruct 16 6(int) 17 13
+              13:             TypePointer PhysicalStorageBufferEXT 18(T1)
+              19:             TypeArray 13(ptr) 11
+              20:             TypePointer StorageBuffer 15(T1)
+           21(x):     20(ptr) Variable StorageBuffer
+              22:             TypePointer StorageBuffer 6(int)
+              28:     10(int) Constant 32
+              29:             TypeArray 6(int) 28
+       30(Block):             TypeStruct 29
+              31:             TypePointer PushConstant 30(Block)
+          32(pc):     31(ptr) Variable PushConstant
+              33:      6(int) Constant 1
+              34:             TypePointer PushConstant 6(int)
+              44:      6(int) Constant 2
+              48:             TypePointer StorageBuffer 13(ptr)
+              51:             TypePointer PhysicalStorageBufferEXT 6(int)
+              54:      6(int) Constant 3
+              64:      6(int) Constant 4
+              72:      6(int) Constant 5
+              82:      6(int) Constant 6
+              94:      6(int) Constant 7
+             104:      6(int) Constant 8
+             112:      6(int) Constant 9
+             122:      6(int) Constant 10
+             130:      6(int) Constant 11
+             134:             TypeVector 10(int) 4
+             135:             TypePointer Function 134(ivec4)
+             138:             TypeBool
+             140:     10(int) Constant 0
+             141:  134(ivec4) ConstantComposite 140 140 140 140
+             142:     10(int) Constant 1
+             143:  134(ivec4) ConstantComposite 142 140 140 142
+             144:             TypeVector 138(bool) 4
+             147:             TypeImage 10(int) 2D nonsampled format:R32ui
+             148:             TypePointer UniformConstant 147
+   149(image0_0):    148(ptr) Variable UniformConstant
+             151:             TypeFloat 32
+             152:             TypeVector 151(float) 4
+             153:             TypePointer Input 152(fvec4)
+154(gl_FragCoord):    153(ptr) Variable Input
+             155:             TypePointer Input 151(float)
+             162:             TypeVector 6(int) 2
+         4(main):           2 Function None 3
+               5:             Label
+        8(accum):      7(ptr) Variable Function
+      136(color):    135(ptr) Variable Function
+                              Store 8(accum) 9
+              23:     22(ptr) AccessChain 21(x) 9 9
+              24:      6(int) Load 23
+              25:      6(int) ISub 24 9
+              26:      6(int) Load 8(accum)
+              27:      6(int) BitwiseOr 26 25
+                              Store 8(accum) 27
+              35:     34(ptr) AccessChain 32(pc) 9 33
+              36:      6(int) Load 35
+              37:     22(ptr) AccessChain 21(x) 9 36
+              38:      6(int) Load 37
+              39:      6(int) ISub 38 33
+              40:      6(int) Load 8(accum)
+              41:      6(int) BitwiseOr 40 39
+                              Store 8(accum) 41
+              42:     22(ptr) AccessChain 21(x) 33
+              43:      6(int) Load 42
+              45:      6(int) ISub 43 44
+              46:      6(int) Load 8(accum)
+              47:      6(int) BitwiseOr 46 45
+                              Store 8(accum) 47
+              49:     48(ptr) AccessChain 21(x) 44 9
+              50:     13(ptr) Load 49
+              52:     51(ptr) AccessChain 50 9 9
+              53:      6(int) Load 52 Aligned 4
+              55:      6(int) ISub 53 54
+              56:      6(int) Load 8(accum)
+              57:      6(int) BitwiseOr 56 55
+                              Store 8(accum) 57
+              58:     48(ptr) AccessChain 21(x) 44 9
+              59:     13(ptr) Load 58
+              60:     34(ptr) AccessChain 32(pc) 9 33
+              61:      6(int) Load 60
+              62:     51(ptr) AccessChain 59 9 61
+              63:      6(int) Load 62 Aligned 4
+              65:      6(int) ISub 63 64
+              66:      6(int) Load 8(accum)
+              67:      6(int) BitwiseOr 66 65
+                              Store 8(accum) 67
+              68:     48(ptr) AccessChain 21(x) 44 9
+              69:     13(ptr) Load 68
+              70:     51(ptr) AccessChain 69 33
+              71:      6(int) Load 70 Aligned 16
+              73:      6(int) ISub 71 72
+              74:      6(int) Load 8(accum)
+              75:      6(int) BitwiseOr 74 73
+                              Store 8(accum) 75
+              76:     34(ptr) AccessChain 32(pc) 9 33
+              77:      6(int) Load 76
+              78:     48(ptr) AccessChain 21(x) 44 77
+              79:     13(ptr) Load 78
+              80:     51(ptr) AccessChain 79 9 9
+              81:      6(int) Load 80 Aligned 4
+              83:      6(int) ISub 81 82
+              84:      6(int) Load 8(accum)
+              85:      6(int) BitwiseOr 84 83
+                              Store 8(accum) 85
+              86:     34(ptr) AccessChain 32(pc) 9 33
+              87:      6(int) Load 86
+              88:     48(ptr) AccessChain 21(x) 44 87
+              89:     13(ptr) Load 88
+              90:     34(ptr) AccessChain 32(pc) 9 33
+              91:      6(int) Load 90
+              92:     51(ptr) AccessChain 89 9 91
+              93:      6(int) Load 92 Aligned 4
+              95:      6(int) ISub 93 94
+              96:      6(int) Load 8(accum)
+              97:      6(int) BitwiseOr 96 95
+                              Store 8(accum) 97
+              98:     34(ptr) AccessChain 32(pc) 9 33
+              99:      6(int) Load 98
+             100:     48(ptr) AccessChain 21(x) 44 99
+             101:     13(ptr) Load 100
+             102:     51(ptr) AccessChain 101 33
+             103:      6(int) Load 102 Aligned 16
+             105:      6(int) ISub 103 104
+             106:      6(int) Load 8(accum)
+             107:      6(int) BitwiseOr 106 105
+                              Store 8(accum) 107
+             108:     48(ptr) AccessChain 21(x) 54
+             109:     13(ptr) Load 108
+             110:     51(ptr) AccessChain 109 9 9
+             111:      6(int) Load 110 Aligned 4
+             113:      6(int) ISub 111 112
+             114:      6(int) Load 8(accum)
+             115:      6(int) BitwiseOr 114 113
+                              Store 8(accum) 115
+             116:     48(ptr) AccessChain 21(x) 54
+             117:     13(ptr) Load 116
+             118:     34(ptr) AccessChain 32(pc) 9 33
+             119:      6(int) Load 118
+             120:     51(ptr) AccessChain 117 9 119
+             121:      6(int) Load 120 Aligned 4
+             123:      6(int) ISub 121 122
+             124:      6(int) Load 8(accum)
+             125:      6(int) BitwiseOr 124 123
+                              Store 8(accum) 125
+             126:     48(ptr) AccessChain 21(x) 54
+             127:     13(ptr) Load 126
+             128:     51(ptr) AccessChain 127 33
+             129:      6(int) Load 128 Aligned 16
+             131:      6(int) ISub 129 130
+             132:      6(int) Load 8(accum)
+             133:      6(int) BitwiseOr 132 131
+                              Store 8(accum) 133
+             137:      6(int) Load 8(accum)
+             139:   138(bool) INotEqual 137 9
+             145:  144(bvec4) CompositeConstruct 139 139 139 139
+             146:  134(ivec4) Select 145 141 143
+                              Store 136(color) 146
+             150:         147 Load 149(image0_0)
+             156:    155(ptr) AccessChain 154(gl_FragCoord) 140
+             157:  151(float) Load 156
+             158:      6(int) ConvertFToS 157
+             159:    155(ptr) AccessChain 154(gl_FragCoord) 142
+             160:  151(float) Load 159
+             161:      6(int) ConvertFToS 160
+             163:  162(ivec2) CompositeConstruct 158 161
+             164:  134(ivec4) Load 136(color)
+                              ImageWrite 150 163 164
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle7.frag.out b/Test/baseResults/spv.bufferhandle7.frag.out
new file mode 100644
index 0000000..4a52596
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle7.frag.out
@@ -0,0 +1,77 @@
+spv.bufferhandle7.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 24
+
+                              Capability Shader
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 7  "t2"
+                              MemberName 7(t2) 0  "f"
+                              MemberName 7(t2) 1  "g"
+                              Name 9  "blockType"
+                              MemberName 9(blockType) 0  "a"
+                              MemberName 9(blockType) 1  "b"
+                              MemberName 9(blockType) 2  "c"
+                              MemberName 9(blockType) 3  "d"
+                              MemberName 9(blockType) 4  "e"
+                              Name 11  "t"
+                              Name 14  "t3"
+                              MemberName 14(t3) 0  "f"
+                              Name 15  "t2"
+                              MemberName 15(t2) 0  "f"
+                              MemberName 15(t2) 1  "g"
+                              Name 17  "u"
+                              MemberDecorate 7(t2) 0 Offset 0
+                              MemberDecorate 7(t2) 1 Offset 8
+                              Decorate 7(t2) Block
+                              MemberDecorate 9(blockType) 0 Offset 0
+                              MemberDecorate 9(blockType) 1 Offset 4
+                              MemberDecorate 9(blockType) 2 Offset 8
+                              MemberDecorate 9(blockType) 3 Offset 12
+                              MemberDecorate 9(blockType) 4 Offset 16
+                              Decorate 9(blockType) Block
+                              Decorate 11(t) DescriptorSet 0
+                              Decorate 11(t) Binding 0
+                              MemberDecorate 14(t3) 0 Offset 0
+                              Decorate 14(t3) Block
+                              MemberDecorate 15(t2) 0 Offset 0
+                              MemberDecorate 15(t2) 1 Offset 8
+                              Decorate 15(t2) Block
+                              Decorate 17(u) DescriptorSet 0
+                              Decorate 17(u) Binding 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+           7(t2):             TypeStruct 6 6
+               8:             TypeInt 32 1
+    9(blockType):             TypeStruct 8(int) 8(int) 8(int) 8(int) 8(int)
+               6:             TypePointer PhysicalStorageBufferEXT 9(blockType)
+              10:             TypePointer StorageBuffer 7(t2)
+           11(t):     10(ptr) Variable StorageBuffer
+              12:      8(int) Constant 0
+                              TypeForwardPointer 13 PhysicalStorageBufferEXT
+          14(t3):             TypeStruct 13
+          15(t2):             TypeStruct 6(ptr) 6(ptr)
+              13:             TypePointer PhysicalStorageBufferEXT 15(t2)
+              16:             TypePointer StorageBuffer 14(t3)
+           17(u):     16(ptr) Variable StorageBuffer
+              18:             TypePointer StorageBuffer 13(ptr)
+              22:             TypePointer StorageBuffer 6(ptr)
+         4(main):           2 Function None 3
+               5:             Label
+              19:     18(ptr) AccessChain 17(u) 12
+              20:     13(ptr) Load 19
+              21:      6(ptr) Bitcast 20
+              23:     22(ptr) AccessChain 11(t) 12
+                              Store 23 21
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle8.frag.out b/Test/baseResults/spv.bufferhandle8.frag.out
new file mode 100644
index 0000000..168da81
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle8.frag.out
@@ -0,0 +1,89 @@
+spv.bufferhandle8.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 27
+
+                              Capability Shader
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main"
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 8  "Blah"
+                              MemberName 8(Blah) 0  "t1"
+                              MemberName 8(Blah) 1  "t2"
+                              Name 10  "T1"
+                              MemberName 10(T1) 0  "x"
+                              Name 11  "T2"
+                              MemberName 11(T2) 0  "x"
+                              Name 13  "T3"
+                              MemberName 13(T3) 0  "Bindings"
+                              Name 15  "t3"
+                              Name 23  "t2"
+                              MemberName 23(t2) 0  "f"
+                              MemberName 23(t2) 1  "g"
+                              Name 24  "blockType"
+                              MemberName 24(blockType) 0  "a"
+                              MemberName 24(blockType) 1  "b"
+                              MemberName 24(blockType) 2  "c"
+                              MemberName 24(blockType) 3  "d"
+                              MemberName 24(blockType) 4  "e"
+                              Name 26  "t"
+                              MemberDecorate 8(Blah) 0 Offset 0
+                              MemberDecorate 8(Blah) 1 Offset 8
+                              MemberDecorate 10(T1) 0 Offset 0
+                              Decorate 10(T1) Block
+                              MemberDecorate 11(T2) 0 Offset 0
+                              Decorate 11(T2) Block
+                              Decorate 12 ArrayStride 16
+                              MemberDecorate 13(T3) 0 Offset 0
+                              Decorate 13(T3) Block
+                              Decorate 15(t3) DescriptorSet 0
+                              Decorate 15(t3) Binding 0
+                              MemberDecorate 23(t2) 0 Offset 0
+                              MemberDecorate 23(t2) 1 Offset 8
+                              Decorate 23(t2) Block
+                              MemberDecorate 24(blockType) 0 Offset 0
+                              MemberDecorate 24(blockType) 1 Offset 4
+                              MemberDecorate 24(blockType) 2 Offset 8
+                              MemberDecorate 24(blockType) 3 Offset 12
+                              MemberDecorate 24(blockType) 4 Offset 16
+                              Decorate 24(blockType) Block
+                              Decorate 26(t) DescriptorSet 0
+                              Decorate 26(t) Binding 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+                              TypeForwardPointer 7 PhysicalStorageBufferEXT
+         8(Blah):             TypeStruct 6 7
+               9:             TypeInt 32 1
+          10(T1):             TypeStruct 9(int)
+               6:             TypePointer PhysicalStorageBufferEXT 10(T1)
+          11(T2):             TypeStruct 9(int)
+               7:             TypePointer PhysicalStorageBufferEXT 11(T2)
+              12:             TypeRuntimeArray 8(Blah)
+          13(T3):             TypeStruct 12
+              14:             TypePointer StorageBuffer 13(T3)
+          15(t3):     14(ptr) Variable StorageBuffer
+              16:      9(int) Constant 0
+              17:      9(int) Constant 1
+              18:             TypePointer StorageBuffer 8(Blah)
+                              TypeForwardPointer 22 PhysicalStorageBufferEXT
+          23(t2):             TypeStruct 22 22
+   24(blockType):             TypeStruct 9(int) 9(int) 9(int) 9(int) 9(int)
+              22:             TypePointer PhysicalStorageBufferEXT 24(blockType)
+              25:             TypePointer StorageBuffer 23(t2)
+           26(t):     25(ptr) Variable StorageBuffer
+         4(main):           2 Function None 3
+               5:             Label
+              19:     18(ptr) AccessChain 15(t3) 16 17
+              20:     8(Blah) Load 19
+              21:     18(ptr) AccessChain 15(t3) 16 16
+                              Store 21 20
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle9.frag.out b/Test/baseResults/spv.bufferhandle9.frag.out
new file mode 100644
index 0000000..e74be8a
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle9.frag.out
@@ -0,0 +1,114 @@
+spv.bufferhandle9.frag
+// Module Version 10000
+// Generated by (magic number): 80007
+// Id's are bound by 56
+
+                              Capability Shader
+                              Capability Int64
+                              Capability CapabilityPhysicalStorageBufferAddressesEXT
+                              Extension  "SPV_EXT_physical_storage_buffer"
+                              Extension  "SPV_KHR_storage_buffer_storage_class"
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel PhysicalStorageBuffer64EXT GLSL450
+                              EntryPoint Fragment 4  "main" 16 19
+                              ExecutionMode 4 OriginUpperLeft
+                              Source GLSL 450
+                              SourceExtension  "GL_ARB_gpu_shader_int64"
+                              SourceExtension  "GL_EXT_buffer_reference"
+                              Name 4  "main"
+                              Name 8  "blockType"
+                              MemberName 8(blockType) 0  "a"
+                              MemberName 8(blockType) 1  "b"
+                              MemberName 8(blockType) 2  "c"
+                              MemberName 8(blockType) 3  "d"
+                              MemberName 8(blockType) 4  "e"
+                              Name 13  "b1"
+                              Name 16  "h"
+                              Name 19  "i"
+                              Name 34  "b2"
+                              Name 37  "b3"
+                              Name 46  "j"
+                              Name 53  "t2"
+                              MemberName 53(t2) 0  "f"
+                              MemberName 53(t2) 1  "g"
+                              Name 55  "t"
+                              MemberDecorate 8(blockType) 0 Offset 0
+                              MemberDecorate 8(blockType) 1 Offset 4
+                              MemberDecorate 8(blockType) 2 Offset 8
+                              MemberDecorate 8(blockType) 3 Offset 12
+                              MemberDecorate 8(blockType) 4 Offset 16
+                              Decorate 8(blockType) Block
+                              Decorate 13(b1) DecorationAliasedPointerEXT
+                              Decorate 16(h) Flat
+                              Decorate 19(i) Flat
+                              Decorate 34(b2) DecorationAliasedPointerEXT
+                              Decorate 37(b3) DecorationAliasedPointerEXT
+                              MemberDecorate 53(t2) 0 Offset 0
+                              MemberDecorate 53(t2) 1 Offset 8
+                              Decorate 53(t2) Block
+                              Decorate 55(t) DescriptorSet 0
+                              Decorate 55(t) Binding 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+                              TypeForwardPointer 6 PhysicalStorageBufferEXT
+               7:             TypeInt 32 1
+    8(blockType):             TypeStruct 7(int) 7(int) 7(int) 7(int) 7(int)
+               6:             TypePointer PhysicalStorageBufferEXT 8(blockType)
+               9:             TypeInt 32 0
+              10:      9(int) Constant 2
+              11:             TypeArray 6(ptr) 10
+              12:             TypePointer Function 11
+              14:             TypeInt 64 0
+              15:             TypePointer Input 14(int64_t)
+           16(h):     15(ptr) Variable Input
+           19(i):     15(ptr) Variable Input
+              23:      7(int) Constant 0
+              24:             TypePointer Function 6(ptr)
+              27:      7(int) Constant 1
+              30:             TypePointer PhysicalStorageBufferEXT 7(int)
+              45:             TypePointer Function 14(int64_t)
+              50: 14(int64_t) Constant 256 0
+          53(t2):             TypeStruct 6(ptr) 6(ptr)
+              54:             TypePointer StorageBuffer 53(t2)
+           55(t):     54(ptr) Variable StorageBuffer
+         4(main):           2 Function None 3
+               5:             Label
+          13(b1):     12(ptr) Variable Function
+          34(b2):     24(ptr) Variable Function
+          37(b3):     24(ptr) Variable Function
+           46(j):     45(ptr) Variable Function
+              17: 14(int64_t) Load 16(h)
+              18:      6(ptr) ConvertUToPtr 17
+              20: 14(int64_t) Load 19(i)
+              21:      6(ptr) ConvertUToPtr 20
+              22:          11 CompositeConstruct 18 21
+                              Store 13(b1) 22
+              25:     24(ptr) AccessChain 13(b1) 23
+              26:      6(ptr) Load 25
+              28:     24(ptr) AccessChain 13(b1) 27
+              29:      6(ptr) Load 28
+              31:     30(ptr) AccessChain 29 27
+              32:      7(int) Load 31 Aligned 4
+              33:     30(ptr) AccessChain 26 23
+                              Store 33 32 Aligned 16
+              35: 14(int64_t) Load 16(h)
+              36:      6(ptr) ConvertUToPtr 35
+                              Store 34(b2) 36
+              38: 14(int64_t) Load 19(i)
+              39:      6(ptr) ConvertUToPtr 38
+                              Store 37(b3) 39
+              40:      6(ptr) Load 34(b2)
+              41:      6(ptr) Load 37(b3)
+              42:     30(ptr) AccessChain 41 27
+              43:      7(int) Load 42 Aligned 4
+              44:     30(ptr) AccessChain 40 23
+                              Store 44 43 Aligned 16
+              47:      6(ptr) Load 34(b2)
+              48: 14(int64_t) ConvertPtrToU 47
+                              Store 46(j) 48
+              49: 14(int64_t) Load 46(j)
+              51: 14(int64_t) IAdd 49 50
+              52:      6(ptr) ConvertUToPtr 51
+                              Store 34(b2) 52
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/spv.bufferhandle_Error.frag.out b/Test/baseResults/spv.bufferhandle_Error.frag.out
new file mode 100644
index 0000000..a1ee9a4
--- /dev/null
+++ b/Test/baseResults/spv.bufferhandle_Error.frag.out
@@ -0,0 +1,25 @@
+spv.bufferhandle_Error.frag
+ERROR: 0:7: 'buffer_reference' : can only be used with buffer 
+ERROR: 0:9: 'buffer_reference' : cannot declare a default, can only be used on a block 
+ERROR: 0:10: 'buffer_reference' : can only be used with buffer 
+ERROR: 0:10: 'buffer_reference' : cannot declare a default, can only be used on a block 
+ERROR: 0:11: 'buffer_reference' : can only be used with buffer 
+ERROR: 0:11: 'buffer_reference' : cannot declare a default, can only be used on a block 
+ERROR: 0:12: 'buffer_reference' : can only be used with buffer 
+ERROR: 0:12: 'buffer_reference' : cannot declare a default, can only be used on a block 
+ERROR: 0:13: 'buffer_reference' : can only be used with buffer 
+ERROR: 0:13: 'buffer_reference' : can only be used with buffer 
+ERROR: 0:14: 'output block' : not supported in this stage: fragment
+ERROR: 0:14: 'buffer_reference' : can only be used with buffer 
+ERROR: 0:14: 'buffer_reference' : can only be used with buffer 
+ERROR: 0:30: 'length' :  array must be declared with a size before using this method
+ERROR: 0:31: 'length' :  array must be declared with a size before using this method
+ERROR: 0:35: '=' :  cannot convert from 'layout( column_major std430) buffer reference' to ' temp reference'
+ERROR: 0:40: 'assign' :  cannot convert from 'layout( column_major std430) buffer reference' to 'layout( column_major std430) buffer reference'
+ERROR: 0:41: 'assign' :  cannot convert from 'layout( column_major std430) buffer reference' to 'layout( column_major std430) buffer reference'
+ERROR: 0:42: 'assign' :  cannot convert from 'layout( column_major std430) buffer reference' to 'layout( column_major std430) buffer reference'
+ERROR: 0:45: '' :  syntax error, unexpected LEFT_BRACE, expecting COMMA or SEMICOLON
+ERROR: 20 compilation errors.  No code generated.
+
+
+SPIR-V is not generated for failed compile or link
diff --git a/Test/spv.bufferhandle1.frag b/Test/spv.bufferhandle1.frag
new file mode 100644
index 0000000..14acac1
--- /dev/null
+++ b/Test/spv.bufferhandle1.frag
@@ -0,0 +1,28 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+#pragma use_vulkan_memory_model

+

+layout(buffer_reference, std430) buffer blockType {

+    layout(offset = 0)  int a;

+    layout(offset = 4)  int b;

+    layout(offset = 8)  int c;

+    layout(offset = 12) int d;

+    layout(offset = 16) int e;

+    layout(offset = 32) int f[2];

+    coherent layout(offset = 48) ivec4 g;

+};

+

+layout(std430) buffer t2 {

+    blockType f;

+    blockType g;

+} t;

+

+void main() {

+    t.f.b = t.g.a;

+

+    blockType j = t.f;

+    j.d = j.c;

+    j.d = j.f[1];

+    j.d = j.g.y;

+}

diff --git a/Test/spv.bufferhandle10.frag b/Test/spv.bufferhandle10.frag
new file mode 100644
index 0000000..1d537e4
--- /dev/null
+++ b/Test/spv.bufferhandle10.frag
@@ -0,0 +1,23 @@
+#version 450

+

+#extension GL_ARB_gpu_shader_int64 : enable

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference, std430) buffer blockType {

+    uint x[];

+};

+

+layout(std430) buffer t2 {

+    blockType f;

+} t;

+

+layout(location = 0) flat in uint i;

+

+void main() {

+

+    atomicAdd(t.f.x[i], 1);

+

+    coherent blockType b = t.f;

+    b.x[0] = 2;

+

+}

diff --git a/Test/spv.bufferhandle11.frag b/Test/spv.bufferhandle11.frag
new file mode 100644
index 0000000..14d05dc
--- /dev/null
+++ b/Test/spv.bufferhandle11.frag
@@ -0,0 +1,26 @@
+#version 450

+#extension GL_EXT_shader_16bit_storage : enable

+#extension GL_EXT_shader_8bit_storage : enable

+#extension GL_EXT_buffer_reference : enable

+

+layout(std140, binding = 0) buffer AcBlock { highp uint ac_numPassed; };

+

+layout(std140, buffer_reference) buffer Block

+{

+	uint8_t var;

+};

+layout (push_constant, std430) uniform PC {

+	Block block;

+};

+

+bool compare_uint8_t  (highp uint a, highp uint b)    { return a == b; }

+

+void main (void)

+{

+	bool allOk = true;

+	allOk = allOk && compare_uint8_t(uint(block.var), 7u);

+	if (allOk)

+		ac_numPassed++;

+

+	block.var = uint8_t(9u);

+}
\ No newline at end of file
diff --git a/Test/spv.bufferhandle12.frag b/Test/spv.bufferhandle12.frag
new file mode 100644
index 0000000..cb7ec6a
--- /dev/null
+++ b/Test/spv.bufferhandle12.frag
@@ -0,0 +1,42 @@
+#version 450

+#extension GL_EXT_shader_16bit_storage : enable

+#extension GL_EXT_shader_8bit_storage : enable

+#extension GL_EXT_buffer_reference : enable

+

+layout(std140, binding = 0) buffer AcBlock { highp uint ac_numPassed; };

+

+layout(std430, column_major, buffer_reference) buffer BlockB

+{

+	float16_t a;

+	highp ivec2 b;

+};

+layout(std430, buffer_reference) buffer BlockC

+{

+	mediump mat2x3 c;

+};

+layout(std430, row_major, buffer_reference) buffer BlockD

+{

+	lowp uvec3 d;

+};

+layout (push_constant, std430) uniform PC {

+	BlockB blockB;

+	BlockC blockC;

+	BlockD blockD;

+};

+

+bool compare_float    (highp float a, highp float b)  { return abs(a - b) < 0.05; }

+bool compare_vec3     (highp vec3 a, highp vec3 b)    { return compare_float(a.x, b.x)&&compare_float(a.y, b.y)&&compare_float(a.z, b.z); }

+bool compare_mat2x3   (highp mat2x3 a, highp mat2x3 b){ return compare_vec3(a[0], b[0])&&compare_vec3(a[1], b[1]); }

+bool compare_ivec2    (highp ivec2 a, highp ivec2 b)  { return a == b; }

+bool compare_uvec3    (highp uvec3 a, highp uvec3 b)  { return a == b; }

+bool compare_float16_t(highp float a, highp float b)  { return abs(a - b) < 0.05; }

+

+void main (void)

+{

+	bool allOk = true;

+	allOk = allOk && compare_mat2x3(blockC.c, mat2x3(-5.0, 1.0, -7.0, 1.0, 2.0, 8.0));

+	if (allOk)

+		ac_numPassed++;

+

+	blockD.d = (uvec3(8u, 1u, 5u));

+}
\ No newline at end of file
diff --git a/Test/spv.bufferhandle13.frag b/Test/spv.bufferhandle13.frag
new file mode 100644
index 0000000..1538d90
--- /dev/null
+++ b/Test/spv.bufferhandle13.frag
@@ -0,0 +1,30 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+

+layout(set = 1, binding = 2, buffer_reference, std430) buffer t4 {

+    layout(offset = 0)  int j;

+};

+

+layout(std430) buffer t5 {

+    t4 m;

+} s5;

+

+t4 f1(const t4 y) { return y; }

+t4 f2(t4 y) { return y; }

+t4 f3(const restrict t4 y) { return y; }

+t4 f4(restrict t4 y) { return y; }

+

+t4 g1;

+restrict t4 g2;

+

+void main()

+{

+    t4 a = s5.m;

+    restrict t4 b = s5.m;

+

+    f1(a);

+    f2(a);

+    f3(a);

+    f4(a);

+}

diff --git a/Test/spv.bufferhandle14.frag b/Test/spv.bufferhandle14.frag
new file mode 100644
index 0000000..132af69
--- /dev/null
+++ b/Test/spv.bufferhandle14.frag
@@ -0,0 +1,40 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference, std430, buffer_reference_align = 4) buffer T1 {

+    int i;

+    int j;

+    int k;

+};

+

+layout(buffer_reference, std430, buffer_reference_align = 8) buffer T2 {

+    int i;

+    int j;

+    int k;

+};

+

+layout(buffer_reference, std430) buffer T3 {

+    int i;

+    int j;

+    int k;

+};

+

+layout(buffer_reference, std430, buffer_reference_align = 32) buffer T4 {

+    int i;

+    int j;

+    int k;

+};

+

+void main()

+{

+    T1 t1;

+    T2 t2;

+    T3 t3;

+    T4 t4;

+

+    t1.i = t1.k;

+    t2.i = t2.k;

+    t3.i = t3.k;

+    t4.i = t4.k;

+}

diff --git a/Test/spv.bufferhandle15.frag b/Test/spv.bufferhandle15.frag
new file mode 100644
index 0000000..ca64593
--- /dev/null
+++ b/Test/spv.bufferhandle15.frag
@@ -0,0 +1,38 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+#extension GL_EXT_scalar_block_layout : enable

+

+layout(buffer_reference, scalar) buffer T1 {

+    vec3 x[];

+};

+

+layout(buffer_reference, scalar) buffer T2 {

+	vec3 x[][4][2];

+};

+

+struct S

+{

+	highp ivec3 a;

+	mediump mat3 b[4];

+	highp vec4 c;

+};

+

+layout(buffer_reference, scalar) buffer T3 {

+    S s;

+};

+layout(std430) buffer T4 {

+    T1 t1;

+    T2 t2;

+    T3 t3;

+} t4;

+

+layout(location = 0) flat in int i;

+

+void main()

+{

+    vec3 y;

+    y = t4.t1.x[i];

+    y = t4.t2.x[i][i][i];

+    mat3 z = t4.t3.s.b[0];

+}

diff --git a/Test/spv.bufferhandle2.frag b/Test/spv.bufferhandle2.frag
new file mode 100644
index 0000000..497e550
--- /dev/null
+++ b/Test/spv.bufferhandle2.frag
@@ -0,0 +1,25 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference, std430) buffer blockType {

+    layout(offset = 0)  int a;

+    layout(offset = 4)  int b;

+    layout(offset = 8)  int c;

+    layout(offset = 12) int d;

+    layout(offset = 16) int e;

+};

+

+layout(std430) buffer t2 {

+    blockType f;

+    blockType g;

+} t;

+

+void main() {

+

+    blockType b1[2] = blockType[2](t.f, t.g);

+    b1[0].a = b1[1].b;

+    blockType b2 = t.f;

+    blockType b3 = t.g;

+    b2.a = b3.b;

+}

diff --git a/Test/spv.bufferhandle3.frag b/Test/spv.bufferhandle3.frag
new file mode 100644
index 0000000..6dddf20
--- /dev/null
+++ b/Test/spv.bufferhandle3.frag
@@ -0,0 +1,25 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference, std430) buffer t3 {

+    int h;

+};

+

+layout(set = 1, binding = 2, buffer_reference, std430) buffer t4 {

+    layout(offset = 0)  int j;

+    t3 k;

+} x;

+

+layout(std430) buffer t5 {

+    t4 m;

+} s5;

+

+flat in t4 k;

+

+t4 foo(t4 y) { return y; }

+

+void main() {

+    foo(s5.m).j = s5.m.k.h;

+    x.j = k.k.h;

+}

diff --git a/Test/spv.bufferhandle4.frag b/Test/spv.bufferhandle4.frag
new file mode 100644
index 0000000..16a02cb
--- /dev/null
+++ b/Test/spv.bufferhandle4.frag
@@ -0,0 +1,26 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference) buffer t4;

+

+layout(buffer_reference, std430) buffer t3 {

+    int h;

+    t4 i;

+};

+

+layout(set = 1, binding = 2, buffer_reference, std430) buffer t4 {

+    layout(offset = 0)  int j;

+    t3 k;

+} x;

+

+layout(std430) buffer t5 {

+    t4 m;

+} s5;

+

+void main() {

+    x.k.h = s5.m.k.i.k.i.k.h;

+

+    bool b = true;

+    s5.m = b ? s5.m : s5.m.k.i;

+}

diff --git a/Test/spv.bufferhandle5.frag b/Test/spv.bufferhandle5.frag
new file mode 100644
index 0000000..6ad5188
--- /dev/null
+++ b/Test/spv.bufferhandle5.frag
@@ -0,0 +1,16 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference, std140) buffer t3 {

+    int h;

+};

+

+layout(set = 1, binding = 2, std140) uniform t4 {

+    layout(offset = 0)  int j;

+    t3 k;

+} x;

+

+void main() {

+    x.k.h = x.j;

+}

diff --git a/Test/spv.bufferhandle6.frag b/Test/spv.bufferhandle6.frag
new file mode 100644
index 0000000..dcc30d0
--- /dev/null
+++ b/Test/spv.bufferhandle6.frag
@@ -0,0 +1,30 @@
+#version 450 core

+

+#extension GL_EXT_buffer_reference : enable

+layout (push_constant, std430) uniform Block { int identity[32]; } pc;

+layout(r32ui, set = 3, binding = 0) uniform uimage2D image0_0;

+layout(buffer_reference) buffer T1;

+layout(set = 3, binding = 1, buffer_reference) buffer T1 {

+   layout(offset = 0) int a[2]; // stride = 4 for std430, 16 for std140

+   layout(offset = 32) int b;

+   layout(offset = 48) T1  c[2]; // stride = 8 for std430, 16 for std140

+   layout(offset = 80) T1  d;

+} x;

+void main()

+{

+  int accum = 0, temp;

+   accum |= x.a[0] - 0;

+   accum |= x.a[pc.identity[1]] - 1;

+   accum |= x.b - 2;

+   accum |= x.c[0].a[0] - 3;

+   accum |= x.c[0].a[pc.identity[1]] - 4;

+   accum |= x.c[0].b - 5;

+   accum |= x.c[pc.identity[1]].a[0] - 6;

+   accum |= x.c[pc.identity[1]].a[pc.identity[1]] - 7;

+   accum |= x.c[pc.identity[1]].b - 8;

+   accum |= x.d.a[0] - 9;

+   accum |= x.d.a[pc.identity[1]] - 10;

+   accum |= x.d.b - 11;

+  uvec4 color = (accum != 0) ? uvec4(0,0,0,0) : uvec4(1,0,0,1);

+  imageStore(image0_0, ivec2(gl_FragCoord.x, gl_FragCoord.y), color);

+}
\ No newline at end of file
diff --git a/Test/spv.bufferhandle7.frag b/Test/spv.bufferhandle7.frag
new file mode 100644
index 0000000..dbc9b2f
--- /dev/null
+++ b/Test/spv.bufferhandle7.frag
@@ -0,0 +1,24 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference, std430) buffer blockType {

+    layout(offset = 0)  int a;

+    layout(offset = 4)  int b;

+    layout(offset = 8)  int c;

+    layout(offset = 12) int d;

+    layout(offset = 16) int e;

+};

+

+layout(std430, buffer_reference) buffer t2 {

+    blockType f;

+    blockType g;

+} t;

+

+layout(std430) buffer t3 {

+    t2 f;

+} u;

+

+void main() {

+    t.f = blockType(u.f);

+}

diff --git a/Test/spv.bufferhandle8.frag b/Test/spv.bufferhandle8.frag
new file mode 100644
index 0000000..1bc13c3
--- /dev/null
+++ b/Test/spv.bufferhandle8.frag
@@ -0,0 +1,32 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference, std430) buffer blockType {

+    layout(offset = 0)  int a;

+    layout(offset = 4)  int b;

+    layout(offset = 8)  int c;

+    layout(offset = 12) int d;

+    layout(offset = 16) int e;

+};

+

+layout(std430) buffer t2 {

+    blockType f;

+    blockType g;

+} t;

+

+layout(std430, buffer_reference) buffer T2 { int x; };

+layout(std430, buffer_reference) buffer T1 { int x; };

+

+struct Blah {

+    T1 t1;

+    T2 t2;

+};

+

+layout(set=0, binding=0) buffer T3 {

+  Blah Bindings[];

+} t3;

+

+void main() {

+    t3.Bindings[0] = t3.Bindings[1];

+}

diff --git a/Test/spv.bufferhandle9.frag b/Test/spv.bufferhandle9.frag
new file mode 100644
index 0000000..7c9f608
--- /dev/null
+++ b/Test/spv.bufferhandle9.frag
@@ -0,0 +1,30 @@
+#version 450

+

+#extension GL_ARB_gpu_shader_int64 : enable

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference, std430) buffer blockType {

+    layout(offset = 0)  int a;

+    layout(offset = 4)  int b;

+    layout(offset = 8)  int c;

+    layout(offset = 12) int d;

+    layout(offset = 16) int e;

+};

+

+layout(std430) buffer t2 {

+    blockType f;

+    blockType g;

+} t;

+

+flat in uint64_t h, i;

+

+void main() {

+

+    blockType b1[2] = blockType[2](blockType(h), blockType(i));

+    b1[0].a = b1[1].b;

+    blockType b2 = blockType(h);

+    blockType b3 = blockType(i);

+    b2.a = b3.b;

+    uint64_t j = uint64_t(b2);

+    b2 = blockType(j+256);

+}

diff --git a/Test/spv.bufferhandle_Error.frag b/Test/spv.bufferhandle_Error.frag
new file mode 100644
index 0000000..98cbac8
--- /dev/null
+++ b/Test/spv.bufferhandle_Error.frag
@@ -0,0 +1,45 @@
+#version 450

+

+#extension GL_EXT_buffer_reference : enable

+

+layout(buffer_reference) buffer bufType1 { int x; };

+layout(buffer_reference) buffer bufType2 { int x; };

+layout(buffer_reference) uniform bufType3 { int x; };

+

+layout(buffer_reference) buffer;

+layout(buffer_reference) uniform;

+layout(buffer_reference) in;

+layout(buffer_reference) out;

+layout(buffer_reference) in badin { float x; } badin2;

+layout(buffer_reference) out badout { float x; } badout2;

+

+layout(buffer_reference) buffer bufType5;

+

+layout(buffer_reference) buffer bufType6 { int x[]; };

+

+buffer bufType4 {

+    bufType1 b1;

+    bufType2 b2;

+    bufType3 b3;

+    bufType6 b6;

+} b4;

+

+void f()

+{

+    bufType6 b;

+    b.x.length();

+    b4.b6.x.length();

+}

+

+void main() {

+    bufType2 x1 = b4.b1;

+    bufType2 x2 = bufType2(b4.b1);

+    bufType2 x3 = bufType2(b4.b2);

+    bufType2 x4 = bufType2(b4.b3);

+

+    b4.b1 = b4.b2;

+    b4.b1 = b4.b3;

+    b4.b3 = b4.b2;

+}

+

+layout(buffer_reference) uniform bufType5 { int x; };

diff --git a/glslang/Include/BaseTypes.h b/glslang/Include/BaseTypes.h
index fabd613..1827c49 100644
--- a/glslang/Include/BaseTypes.h
+++ b/glslang/Include/BaseTypes.h
@@ -66,6 +66,8 @@
     EbtAccStructNV,
 #endif
 
+    EbtReference,
+
     // HLSL types that live only temporarily.
     EbtString,
 
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index 30fc8ce..eb57c3a 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -721,6 +721,7 @@
         clearUniformLayout();
 
         layoutPushConstant = false;
+        layoutBufferReference = false;
 #ifdef NV_EXTENSIONS
         layoutPassthrough = false;
         layoutViewportRelative = false;
@@ -729,6 +730,8 @@
         layoutShaderRecordNV = false;
 #endif
 
+        layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd;
+
         clearInterstageLayout();
 
         layoutSpecConstantId = layoutSpecConstantIdEnd;
@@ -763,7 +766,8 @@
 #ifdef NV_EXTENSIONS
                layoutShaderRecordNV ||
 #endif
-               layoutPushConstant;
+               layoutPushConstant ||
+               layoutBufferReference;
     }
     bool hasLayout() const
     {
@@ -808,9 +812,14 @@
                  unsigned int layoutSpecConstantId       : 11;
     static const unsigned int layoutSpecConstantIdEnd = 0x7FF;
 
+    // stored as log2 of the actual alignment value
+                 unsigned int layoutBufferReferenceAlign :  6;
+    static const unsigned int layoutBufferReferenceAlignEnd = 0x3F;
+
     TLayoutFormat layoutFormat                           :  8;
 
     bool layoutPushConstant;
+    bool layoutBufferReference;
 
 #ifdef NV_EXTENSIONS
     bool layoutPassthrough;
@@ -918,6 +927,10 @@
         // is just whether or not it was declared with an ID.
         return layoutSpecConstantId != layoutSpecConstantIdEnd;
     }
+    bool hasBufferReferenceAlign() const
+    {
+        return layoutBufferReferenceAlign != layoutBufferReferenceAlignEnd;
+    }
     bool isSpecConstant() const
     {
         // True if type is a specialization constant, whether or not it
@@ -1308,7 +1321,12 @@
                                     sampler.clear();
                                 qualifier = p.qualifier;
                                 if (p.userDef) {
-                                    structure = p.userDef->getWritableStruct();  // public type is short-lived; there are no sharing issues
+                                    if (p.userDef->basicType == EbtReference) {
+                                        basicType = EbtReference;
+                                        referentType = p.userDef->referentType;
+                                    } else {
+                                        structure = p.userDef->getWritableStruct();  // public type is short-lived; there are no sharing issues
+                                    }
                                     typeName = NewPoolTString(p.userDef->getTypeName().c_str());
                                 }
                             }
@@ -1377,6 +1395,17 @@
                                 sampler.clear();
                                 typeName = NewPoolTString(n.c_str());
                             }
+    // for block reference (first parameter must be EbtReference)
+    explicit TType(TBasicType t, const TType &p, const TString& n) :
+                            basicType(t), vectorSize(1), matrixCols(0), matrixRows(0), vector1(false),
+                            arraySizes(nullptr), structure(nullptr), fieldName(nullptr), typeName(nullptr)
+                            {
+                                assert(t == EbtReference);
+                                typeName = NewPoolTString(n.c_str());
+                                qualifier.clear();
+                                qualifier.storage = p.qualifier.storage;
+                                referentType = p.clone();
+                            }
     virtual ~TType() {}
 
     // Not for use across pool pops; it will cause multiple instances of TType to point to the same information.
@@ -1392,9 +1421,13 @@
         matrixRows = copyOf.matrixRows;
         vector1 = copyOf.vector1;
         arraySizes = copyOf.arraySizes;  // copying the pointer only, not the contents
-        structure = copyOf.structure;
         fieldName = copyOf.fieldName;
         typeName = copyOf.typeName;
+        if (isStruct()) {
+            structure = copyOf.structure;
+        } else {
+            referentType = copyOf.referentType;
+        }
     }
 
     // Make complete copy of the whole type graph rooted at 'copyOf'.
@@ -1457,6 +1490,7 @@
     virtual int getImplicitArraySize() const { return arraySizes->getImplicitSize(); }
     virtual const TArraySizes* getArraySizes() const { return arraySizes; }
     virtual       TArraySizes* getArraySizes()       { return arraySizes; }
+    virtual TType* getReferentType() const { return referentType; }
 
     virtual bool isScalar() const { return ! isVector() && ! isMatrix() && ! isStruct() && ! isArray(); }
     virtual bool isScalarOrVec1() const { return isScalar() || vector1; }
@@ -1468,7 +1502,7 @@
     virtual bool isArrayVariablyIndexed() const { assert(isArray()); return arraySizes->isVariablyIndexed(); }
     virtual void setArrayVariablyIndexed() { assert(isArray()); arraySizes->setVariablyIndexed(); }
     virtual void updateImplicitArraySize(int size) { assert(isArray()); arraySizes->updateImplicitSize(size); }
-    virtual bool isStruct() const { return structure != nullptr; }
+    virtual bool isStruct() const { return basicType == EbtStruct || basicType == EbtBlock; }
     virtual bool isFloatingDomain() const { return basicType == EbtFloat || basicType == EbtDouble || basicType == EbtFloat16; }
     virtual bool isIntegerDomain() const
     {
@@ -1509,7 +1543,7 @@
 
         const auto hasa = [predicate](const TTypeLoc& tl) { return tl.type->contains(predicate); };
 
-        return structure && std::any_of(structure->begin(), structure->end(), hasa);
+        return isStruct() && std::any_of(structure->begin(), structure->end(), hasa);
     }
 
     // Recursively checks if the type contains the given basic type
@@ -1688,6 +1722,7 @@
 #ifdef NV_EXTENSIONS
         case EbtAccStructNV:       return "accelerationStructureNV";
 #endif
+        case EbtReference:         return "reference";
         default:                   return "unknown type";
         }
     }
@@ -1773,6 +1808,12 @@
                 }
                 if (qualifier.layoutPushConstant)
                     appendStr(" push_constant");
+                if (qualifier.layoutBufferReference)
+                    appendStr(" buffer_reference");
+                if (qualifier.hasBufferReferenceAlign()) {
+                    appendStr(" buffer_reference_align=");
+                    appendUint(1u << qualifier.layoutBufferReferenceAlign);
+                }
 
 #ifdef NV_EXTENSIONS
                 if (qualifier.layoutPassthrough)
@@ -1892,7 +1933,7 @@
         }
 
         // Add struct/block members
-        if (structure) {
+        if (isStruct()) {
             appendStr("{");
             for (size_t i = 0; i < structure->size(); ++i) {
                 if (! (*structure)[i].type->hiddenMember()) {
@@ -1920,9 +1961,9 @@
     const char* getStorageQualifierString() const { return GetStorageQualifierString(qualifier.storage); }
     const char* getBuiltInVariableString() const { return GetBuiltInVariableString(qualifier.builtIn); }
     const char* getPrecisionQualifierString() const { return GetPrecisionQualifierString(qualifier.precision); }
-    const TTypeList* getStruct() const { return structure; }
-    void setStruct(TTypeList* s) { structure = s; }
-    TTypeList* getWritableStruct() const { return structure; }  // This should only be used when known to not be sharing with other threads
+    const TTypeList* getStruct() const { assert(isStruct()); return structure; }
+    void setStruct(TTypeList* s) { assert(isStruct()); structure = s; }
+    TTypeList* getWritableStruct() const { assert(isStruct()); return structure; }  // This should only be used when known to not be sharing with other threads
 
     int computeNumComponents() const
     {
@@ -1961,11 +2002,12 @@
     bool sameStructType(const TType& right) const
     {
         // Most commonly, they are both nullptr, or the same pointer to the same actual structure
-        if (structure == right.structure)
+        if ((!isStruct() && !right.isStruct()) ||
+            isStruct() && right.isStruct() && structure == right.structure)
             return true;
 
         // Both being nullptr was caught above, now they both have to be structures of the same number of elements
-        if (structure == nullptr || right.structure == nullptr ||
+        if (!isStruct() || !right.isStruct() ||
             structure->size() != right.structure->size())
             return false;
 
@@ -1985,6 +2027,23 @@
         return true;
     }
 
+    bool sameReferenceType(const TType& right) const
+    {
+        if ((basicType == EbtReference) != (right.basicType == EbtReference))
+            return false;
+
+        if ((basicType != EbtReference) && (right.basicType != EbtReference))
+            return true;
+
+        assert(referentType != nullptr);
+        assert(right.referentType != nullptr);
+
+        if (referentType == right.referentType)
+            return true;
+
+        return *referentType == *right.referentType;
+    }
+
     // See if two types match, in all aspects except arrayness
     bool sameElementType(const TType& right) const
     {
@@ -2013,7 +2072,8 @@
                matrixCols == right.matrixCols &&
                matrixRows == right.matrixRows &&
                   vector1 == right.vector1    &&
-               sameStructType(right);
+               sameStructType(right)          &&
+               sameReferenceType(right);
     }
 
     // See if two types match in all ways (just the actual type, not qualification)
@@ -2044,7 +2104,7 @@
             *arraySizes = *copyOf.arraySizes;
         }
 
-        if (copyOf.structure) {
+        if (copyOf.isStruct() && copyOf.structure) {
             auto prevCopy = copiedMap.find(copyOf.structure);
             if (prevCopy != copiedMap.end())
                 structure = prevCopy->second;
@@ -2082,7 +2142,12 @@
     TQualifier qualifier;
 
     TArraySizes* arraySizes;    // nullptr unless an array; can be shared across types
-    TTypeList* structure;       // nullptr unless this is a struct; can be shared across types
+    // A type can't be both a structure (EbtStruct/EbtBlock) and a reference (EbtReference), so
+    // conserve space by making these a union
+    union {
+        TTypeList* structure;       // invalid unless this is a struct; can be shared across types
+        TType *referentType;        // invalid unless this is an EbtReference
+    };
     TString *fieldName;         // for structure field names
     TString *typeName;          // for structure type name
     TSampler sampler;
diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h
index 2725007..4b6bcb7 100644
--- a/glslang/Include/intermediate.h
+++ b/glslang/Include/intermediate.h
@@ -269,6 +269,10 @@
     EOpConvDoubleToFloat16,
     EOpConvDoubleToFloat,
 
+    // uint64_t <-> pointer
+    EOpConvUint64ToPtr,
+    EOpConvPtrToUint64,
+
     //
     // binary operations
     //
@@ -732,6 +736,7 @@
     EOpConstructStruct,
     EOpConstructTextureSampler,
     EOpConstructNonuniform,     // expected to be transformed away, not present in final AST
+    EOpConstructReference,
     EOpConstructGuardEnd,
 
     //
diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp
index a3ca56c..32b38a0 100755
--- a/glslang/MachineIndependent/Intermediate.cpp
+++ b/glslang/MachineIndependent/Intermediate.cpp
@@ -984,6 +984,14 @@
     case EOpSequence:
     case EOpConstructStruct:
 
+        if (type.getBasicType() == EbtReference || node->getType().getBasicType() == EbtReference) {
+            // types must match to assign a reference
+            if (type == node->getType())
+                return node;
+            else
+                return nullptr;
+        }
+
         if (type.getBasicType() == node->getType().getBasicType())
             return node;
 
@@ -2131,6 +2139,9 @@
             }
         }
         break;
+    case EbtReference:
+        op = EOpConstructReference;
+        break;
     default:
         break;
     }
diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp
index 7ddc27e..d16dc99 100755
--- a/glslang/MachineIndependent/ParseHelper.cpp
+++ b/glslang/MachineIndependent/ParseHelper.cpp
@@ -354,6 +354,11 @@
     if (variable->getType().getQualifier().isIo())
         intermediate.addIoAccessed(*string);
 
+    if (variable->getType().getBasicType() == EbtReference &&
+        variable->getType().getQualifier().isMemory()) {
+        intermediate.setUseVulkanMemoryModel();
+    }
+
     return node;
 }
 
@@ -811,8 +816,12 @@
             if (base->getType().getQualifier().isSpecConstant())
                 result->getWritableType().getQualifier().makeSpecConstant();
         }
-    } else if (base->getBasicType() == EbtStruct || base->getBasicType() == EbtBlock) {
-        const TTypeList* fields = base->getType().getStruct();
+    } else if (base->getBasicType() == EbtStruct ||
+               base->getBasicType() == EbtBlock ||
+               base->getBasicType() == EbtReference) {
+        const TTypeList* fields = base->getBasicType() == EbtReference ?
+                                                            base->getType().getReferentType()->getStruct() :
+                                                            base->getType().getStruct();
         bool fieldFound = false;
         int member;
         for (member = 0; member < (int)fields->size(); ++member) {
@@ -2386,6 +2395,10 @@
         }
     }
 
+    if (binaryNode && binaryNode->getOp() == EOpIndexDirectStruct &&
+        binaryNode->getLeft()->getBasicType() == EbtReference)
+        return false;
+
     // Let the base class check errors
     if (TParseContextBase::lValueErrorCheck(loc, op, node))
         return true;
@@ -3096,13 +3109,17 @@
     if (! symbolTable.atGlobalLevel())
         return;
 
-    if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) {
-        error(loc, "memory qualifiers cannot be used on this type", "", "");
-    } else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) {
-        error(loc, "memory qualifiers cannot be used on this type", "", "");
+    if (!(publicType.userDef && publicType.userDef->getBasicType() == EbtReference)) {
+        if (qualifier.isMemoryQualifierImageAndSSBOOnly() && ! publicType.isImage() && publicType.qualifier.storage != EvqBuffer) {
+            error(loc, "memory qualifiers cannot be used on this type", "", "");
+        } else if (qualifier.isMemory() && (publicType.basicType != EbtSampler) && !publicType.qualifier.isUniformOrBuffer()) {
+            error(loc, "memory qualifiers cannot be used on this type", "", "");
+        }
     }
 
-    if (qualifier.storage == EvqBuffer && publicType.basicType != EbtBlock)
+    if (qualifier.storage == EvqBuffer &&
+        publicType.basicType != EbtBlock &&
+        !qualifier.layoutBufferReference)
         error(loc, "buffers can be declared only as blocks", "buffer", "");
 
     if (qualifier.storage != EvqVaryingIn && qualifier.storage != EvqVaryingOut)
@@ -3760,6 +3777,21 @@
     if (isRuntimeLength(base))
         return;
 
+    // Check for last member of a bufferreference type, which is runtime sizeable
+    // but doesn't support runtime length
+    if (base.getType().getQualifier().storage == EvqBuffer) {
+        const TIntermBinary* binary = base.getAsBinaryNode();
+        if (binary != nullptr &&
+            binary->getOp() == EOpIndexDirectStruct &&
+            binary->getLeft()->getBasicType() == EbtReference) {
+
+            const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
+            const int memberCount = (int)binary->getLeft()->getType().getReferentType()->getStruct()->size();
+            if (index == memberCount - 1)
+                return;
+        }
+    }
+
     // check for additional things allowed by GL_EXT_nonuniform_qualifier
     if (base.getBasicType() == EbtSampler ||
             (base.getBasicType() == EbtBlock && base.getType().getQualifier().isUniformOrBuffer()))
@@ -3777,6 +3809,10 @@
         if (binary != nullptr && binary->getOp() == EOpIndexDirectStruct) {
             // is it the last member?
             const int index = binary->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst();
+
+            if (binary->getLeft()->getBasicType() == EbtReference)
+                return false;
+
             const int memberCount = (int)binary->getLeft()->getType().getStruct()->size();
             if (index == memberCount - 1)
                 return true;
@@ -4655,6 +4691,14 @@
         publicType.qualifier.layoutPushConstant = true;
         return;
     }
+    if (id == "buffer_reference") {
+        requireVulkan(loc, "buffer_reference");
+        requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference");
+        publicType.qualifier.layoutBufferReference = true;
+        intermediate.setUseStorageBuffer();
+        intermediate.setUsePhysicalStorageBuffer();
+        return;
+    }
     if (language == EShLangGeometry || language == EShLangTessEvaluation
 #ifdef NV_EXTENSIONS
         || language == EShLangMeshNV
@@ -5013,6 +5057,15 @@
     }
 #endif
 
+    if (id == "buffer_reference_align") {
+        requireExtensions(loc, 1, &E_GL_EXT_buffer_reference, "buffer_reference_align");
+        if (! IsPow2(value))
+            error(loc, "must be a power of 2", "buffer_reference_align", "");
+        else
+            publicType.qualifier.layoutBufferReferenceAlign = std::log2(value);
+        return;
+    }
+
     switch (language) {
     case EShLangVertex:
         break;
@@ -5177,6 +5230,9 @@
     if (src.hasAlign())
         dst.layoutAlign = src.layoutAlign;
 
+    if (src.hasBufferReferenceAlign())
+        dst.layoutBufferReferenceAlign = src.layoutBufferReferenceAlign;
+
     if (! inheritOnly) {
         if (src.hasLocation())
             dst.layoutLocation = src.layoutLocation;
@@ -5205,6 +5261,9 @@
         if (src.layoutPushConstant)
             dst.layoutPushConstant = true;
 
+        if (src.layoutBufferReference)
+            dst.layoutBufferReference = true;
+
 #ifdef NV_EXTENSIONS
         if (src.layoutPassthrough)
             dst.layoutPassthrough = true;
@@ -5452,7 +5511,8 @@
 #ifdef NV_EXTENSIONS
                        !qualifier.layoutShaderRecordNV &&
 #endif
-                       !qualifier.layoutAttachment)
+                       !qualifier.layoutAttachment &&
+                       !qualifier.layoutBufferReference)
                     error(loc, "uniform/buffer blocks require layout(binding=X)", "binding", "");
                 else if (spvVersion.vulkan > 0 && type.getBasicType() == EbtSampler)
                     error(loc, "sampler/texture/image requires layout(binding=X)", "binding", "");
@@ -5504,6 +5564,9 @@
     if (qualifier.layoutPushConstant && type.getBasicType() != EbtBlock)
         error(loc, "can only be used with a block", "push_constant", "");
 
+    if (qualifier.layoutBufferReference && type.getBasicType() != EbtBlock)
+        error(loc, "can only be used with a block", "buffer_reference", "");
+
 #ifdef NV_EXTENSIONS
     if (qualifier.layoutShaderRecordNV && type.getBasicType() != EbtBlock)
         error(loc, "can only be used with a block", "shaderRecordNV", "");
@@ -5644,6 +5707,10 @@
         if (qualifier.hasSet())
             error(loc, "cannot be used with push_constant", "set", "");
     }
+    if (qualifier.layoutBufferReference) {
+        if (qualifier.storage != EvqBuffer)
+            error(loc, "can only be used with buffer", "buffer_reference", "");
+    }
 #ifdef NV_EXTENSIONS
     if (qualifier.layoutShaderRecordNV) {
         if (qualifier.storage != EvqBuffer)
@@ -6051,7 +6118,7 @@
         return;
     }
 
-    if (publicType.qualifier.hasLayout())
+    if (publicType.qualifier.hasLayout() && !publicType.qualifier.layoutBufferReference)
         warn(loc, "useless application of layout qualifier", "layout", "");
 }
 
@@ -6659,10 +6726,15 @@
         basicOp = EOpConstructInt64;
         break;
 
+    case EOpConstructUint64:
+        if (type.isScalar() && node->getType().getBasicType() == EbtReference) {
+            TIntermUnary* newNode = intermediate.addUnaryNode(EOpConvPtrToUint64, node, node->getLoc(), type);
+            return newNode;
+        }
+        // fall through
     case EOpConstructU64Vec2:
     case EOpConstructU64Vec3:
     case EOpConstructU64Vec4:
-    case EOpConstructUint64:
         basicOp = EOpConstructUint64;
         break;
 
@@ -6678,6 +6750,19 @@
         return node;
         break;
 
+    case EOpConstructReference:
+        // construct reference from reference
+        if (node->getType().getBasicType() == EbtReference) {
+            newNode = intermediate.addUnaryNode(EOpConstructReference, node, node->getLoc(), type);
+            return newNode;
+        // construct reference from uint64
+        } else if (node->getType().isScalar() && node->getType().getBasicType() == EbtUint64) {
+            TIntermUnary* newNode = intermediate.addUnaryNode(EOpConvUint64ToPtr, node, node->getLoc(), type);
+            return newNode;
+        } else {
+            return nullptr;
+        }
+
     default:
         error(loc, "unsupported construction", "", "");
 
@@ -6922,31 +7007,57 @@
     else
         ioArrayCheck(loc, blockType, instanceName ? *instanceName : *blockName);
 
-    //
-    // Don't make a user-defined type out of block name; that will cause an error
-    // if the same block name gets reused in a different interface.
-    //
-    // "Block names have no other use within a shader
-    // beyond interface matching; it is a compile-time error to use a block name at global scope for anything
-    // other than as a block name (e.g., use of a block name for a global variable name or function name is
-    // currently reserved)."
-    //
-    // Use the symbol table to prevent normal reuse of the block's name, as a variable entry,
-    // whose type is EbtBlock, but without all the structure; that will come from the type
-    // the instances point to.
-    //
-    TType blockNameType(EbtBlock, blockType.getQualifier().storage);
-    TVariable* blockNameVar = new TVariable(blockName, blockNameType);
-    if (! symbolTable.insert(*blockNameVar)) {
-        TSymbol* existingName = symbolTable.find(*blockName);
-        if (existingName->getType().getBasicType() == EbtBlock) {
-            if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) {
-                error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString());
+    if (currentBlockQualifier.layoutBufferReference) {
+
+        if (currentBlockQualifier.storage != EvqBuffer)
+            error(loc, "can only be used with buffer", "buffer_reference", "");
+
+        // Create the block reference type. If it was forward-declared, detect that
+        // as a referent struct type with no members. Replace the referent type with
+        // blockType.
+        TType blockNameType(EbtReference, blockType, *blockName);
+        TVariable* blockNameVar = new TVariable(blockName, blockNameType, true);
+        if (! symbolTable.insert(*blockNameVar)) {
+            TSymbol* existingName = symbolTable.find(*blockName);
+            if (existingName->getType().getBasicType() == EbtReference &&
+                existingName->getType().getReferentType()->getStruct() &&
+                existingName->getType().getReferentType()->getStruct()->size() == 0 &&
+                existingName->getType().getQualifier().storage == blockType.getQualifier().storage) {
+                existingName->getType().getReferentType()->deepCopy(blockType);
+            } else {
+                error(loc, "block name cannot be redefined", blockName->c_str(), "");
+            }
+        }
+        if (!instanceName) {
+            return;
+        }
+    } else {
+        //
+        // Don't make a user-defined type out of block name; that will cause an error
+        // if the same block name gets reused in a different interface.
+        //
+        // "Block names have no other use within a shader
+        // beyond interface matching; it is a compile-time error to use a block name at global scope for anything
+        // other than as a block name (e.g., use of a block name for a global variable name or function name is
+        // currently reserved)."
+        //
+        // Use the symbol table to prevent normal reuse of the block's name, as a variable entry,
+        // whose type is EbtBlock, but without all the structure; that will come from the type
+        // the instances point to.
+        //
+        TType blockNameType(EbtBlock, blockType.getQualifier().storage);
+        TVariable* blockNameVar = new TVariable(blockName, blockNameType);
+        if (! symbolTable.insert(*blockNameVar)) {
+            TSymbol* existingName = symbolTable.find(*blockName);
+            if (existingName->getType().getBasicType() == EbtBlock) {
+                if (existingName->getType().getQualifier().storage == blockType.getQualifier().storage) {
+                    error(loc, "Cannot reuse block name within the same interface:", blockName->c_str(), blockType.getStorageQualifierString());
+                    return;
+                }
+            } else {
+                error(loc, "block name cannot redefine a non-block name", blockName->c_str(), "");
                 return;
             }
-        } else {
-            error(loc, "block name cannot redefine a non-block name", blockName->c_str(), "");
-            return;
         }
     }
 
@@ -7246,6 +7357,22 @@
 void TParseContext::addQualifierToExisting(const TSourceLoc& loc, TQualifier qualifier, const TString& identifier)
 {
     TSymbol* symbol = symbolTable.find(identifier);
+
+    // A forward declaration of a block reference looks to the grammar like adding
+    // a qualifier to an existing symbol. Detect this and create the block reference
+    // type with an empty type list, which will be filled in later in
+    // TParseContext::declareBlock.
+    if (!symbol && qualifier.layoutBufferReference) {
+        TTypeList typeList;
+        TType blockType(&typeList, identifier, qualifier);;
+        TType blockNameType(EbtReference, blockType, identifier);
+        TVariable* blockNameVar = new TVariable(&identifier, blockNameType, true);
+        if (! symbolTable.insert(*blockNameVar)) {
+            error(loc, "block name cannot redefine a non-block name", blockName->c_str(), "");
+        }
+        return;
+    }
+
     if (! symbol) {
         error(loc, "identifier not previously declared", identifier.c_str(), "");
         return;
@@ -7580,6 +7707,8 @@
         error(loc, "cannot declare a default, use a full declaration", "xfb_offset", "");
     if (qualifier.layoutPushConstant)
         error(loc, "cannot declare a default, can only be used on a block", "push_constant", "");
+    if (qualifier.layoutBufferReference)
+        error(loc, "cannot declare a default, can only be used on a block", "buffer_reference", "");
     if (qualifier.hasSpecConstantId())
         error(loc, "cannot declare a default, can only be used on a scalar", "constant_id", "");
 #ifdef NV_EXTENSIONS
diff --git a/glslang/MachineIndependent/Scan.cpp b/glslang/MachineIndependent/Scan.cpp
index 2247250..2ec26c6 100644
--- a/glslang/MachineIndependent/Scan.cpp
+++ b/glslang/MachineIndependent/Scan.cpp
@@ -776,7 +776,7 @@
         loc = ppToken.loc;
         parserToken->sType.lex.loc = loc;
         switch (token) {
-        case ';':  afterType = false;   return SEMICOLON;
+        case ';':  afterType = false; afterBuffer = false; return SEMICOLON;
         case ',':  afterType = false;   return COMMA;
         case ':':                       return COLON;
         case '=':  afterType = false;   return EQUAL;
@@ -798,7 +798,7 @@
         case '?':                       return QUESTION;
         case '[':                       return LEFT_BRACKET;
         case ']':                       return RIGHT_BRACKET;
-        case '{':  afterStruct = false; return LEFT_BRACE;
+        case '{':  afterStruct = false; afterBuffer = false; return LEFT_BRACE;
         case '}':                       return RIGHT_BRACE;
         case '\\':
             parseContext.error(loc, "illegal use of escape character", "\\", "");
@@ -945,6 +945,7 @@
         return keyword;
 
     case BUFFER:
+        afterBuffer = true;
         if ((parseContext.profile == EEsProfile && parseContext.version < 310) ||
             (parseContext.profile != EEsProfile && parseContext.version < 430))
             return identifierOrType();
@@ -1617,7 +1618,9 @@
     parserToken->sType.lex.symbol = parseContext.symbolTable.find(*parserToken->sType.lex.string);
     if ((afterType == false && afterStruct == false) && parserToken->sType.lex.symbol != nullptr) {
         if (const TVariable* variable = parserToken->sType.lex.symbol->getAsVariable()) {
-            if (variable->isUserType()) {
+            if (variable->isUserType() &&
+                // treat redeclaration of forward-declared buffer/uniform reference as an identifier
+                !(variable->getType().getBasicType() == EbtReference && afterBuffer)) {
                 afterType = true;
 
                 return TYPE_NAME;
diff --git a/glslang/MachineIndependent/ScanContext.h b/glslang/MachineIndependent/ScanContext.h
index 0cc7ea0..74b2b3c 100644
--- a/glslang/MachineIndependent/ScanContext.h
+++ b/glslang/MachineIndependent/ScanContext.h
@@ -53,7 +53,7 @@
     explicit TScanContext(TParseContextBase& pc) :
         parseContext(pc),
         afterType(false), afterStruct(false),
-        field(false) { }
+        field(false), afterBuffer(false) { }
     virtual ~TScanContext() { }
 
     static void fillInKeywordMap();
@@ -81,6 +81,7 @@
     bool afterType;           // true if we've recognized a type, so can only be looking for an identifier
     bool afterStruct;         // true if we've recognized the STRUCT keyword, so can only be looking for an identifier
     bool field;               // true if we're on a field, right after a '.'
+    bool afterBuffer;         // true if we've recognized the BUFFER keyword
     TSourceLoc loc;
     TParserToken* parserToken;
     TPpToken* ppToken;
diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp
index 9b8347f..8088845 100755
--- a/glslang/MachineIndependent/Versions.cpp
+++ b/glslang/MachineIndependent/Versions.cpp
@@ -207,6 +207,7 @@
     extensionBehavior[E_GL_EXT_samplerless_texture_functions]           = EBhDisable;
     extensionBehavior[E_GL_EXT_scalar_block_layout]                     = EBhDisable;
     extensionBehavior[E_GL_EXT_fragment_invocation_density]             = EBhDisable;
+    extensionBehavior[E_GL_EXT_buffer_reference]                        = EBhDisable;
 
     extensionBehavior[E_GL_EXT_shader_16bit_storage]                    = EBhDisable;
     extensionBehavior[E_GL_EXT_shader_8bit_storage]                     = EBhDisable;
@@ -383,6 +384,7 @@
             "#define GL_EXT_samplerless_texture_functions 1\n"
             "#define GL_EXT_scalar_block_layout 1\n"
             "#define GL_EXT_fragment_invocation_density 1\n"
+            "#define GL_EXT_buffer_reference 1\n"
 
             // GL_KHR_shader_subgroup
             "#define GL_KHR_shader_subgroup_basic 1\n"
diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h
index 3207503..0606e8e 100755
--- a/glslang/MachineIndependent/Versions.h
+++ b/glslang/MachineIndependent/Versions.h
@@ -169,6 +169,7 @@
 const char* const E_GL_EXT_samplerless_texture_functions    = "GL_EXT_samplerless_texture_functions";
 const char* const E_GL_EXT_scalar_block_layout              = "GL_EXT_scalar_block_layout";
 const char* const E_GL_EXT_fragment_invocation_density      = "GL_EXT_fragment_invocation_density";
+const char* const E_GL_EXT_buffer_reference                 = "GL_EXT_buffer_reference";
 
 // Arrays of extensions for the above viewportEXTs duplications
 
diff --git a/glslang/MachineIndependent/intermOut.cpp b/glslang/MachineIndependent/intermOut.cpp
index 5ad6790..f74b90a 100644
--- a/glslang/MachineIndependent/intermOut.cpp
+++ b/glslang/MachineIndependent/intermOut.cpp
@@ -172,8 +172,12 @@
     case EOpIndexDirect:   out.debug << "direct index";   break;
     case EOpIndexIndirect: out.debug << "indirect index"; break;
     case EOpIndexDirectStruct:
-        out.debug << (*node->getLeft()->getType().getStruct())[node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()].type->getFieldName();
-        out.debug << ": direct index for structure";      break;
+        {
+            bool reference = node->getLeft()->getType().getBasicType() == EbtReference;
+            const TTypeList *members = reference ? node->getLeft()->getType().getReferentType()->getStruct() : node->getLeft()->getType().getStruct();
+            out.debug << (*members)[node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()].type->getFieldName();
+            out.debug << ": direct index for structure";      break;
+        }
     case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
     case EOpMatrixSwizzle: out.debug << "matrix swizzle"; break;
 
@@ -419,6 +423,8 @@
     case EOpConvDoubleToUint:   out.debug << "Convert double to uint"; break;
     case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break;
 
+    case EOpConvUint64ToPtr:  out.debug << "Convert uint64_t to pointer";   break;
+    case EOpConvPtrToUint64:  out.debug << "Convert pointer to uint64_t";   break;
 
     case EOpRadians:        out.debug << "radians";              break;
     case EOpDegrees:        out.debug << "degrees";              break;
@@ -674,6 +680,8 @@
     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
     case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
 
+    case EOpConstructReference: out.debug << "Construct reference type"; break;
+
     default: out.debug.message(EPrefixError, "Bad unary op");
     }
 
@@ -808,6 +816,7 @@
     case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4";   break;
     case EOpConstructStruct:  out.debug << "Construct structure";  break;
     case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
+    case EOpConstructReference:  out.debug << "Construct reference";  break;
 
     case EOpLessThan:         out.debug << "Compare Less Than";             break;
     case EOpGreaterThan:      out.debug << "Compare Greater Than";          break;
diff --git a/glslang/MachineIndependent/linkValidate.cpp b/glslang/MachineIndependent/linkValidate.cpp
index 79c8c02..977600b 100755
--- a/glslang/MachineIndependent/linkValidate.cpp
+++ b/glslang/MachineIndependent/linkValidate.cpp
@@ -261,6 +261,7 @@
 
     MERGE_TRUE(needToLegalize);
     MERGE_TRUE(binaryDoubleOutput);
+    MERGE_TRUE(usePhysicalStorageBuffer);
 }
 
 //
@@ -1355,6 +1356,7 @@
     case EbtUint8:   size = 1; return 1;
     case EbtInt16:
     case EbtUint16:  size = 2; return 2;
+    case EbtReference: size = 8; return 8;
     default:         size = 4; return 4;
     }
 }
diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h
index 589264c..c114f21 100755
--- a/glslang/MachineIndependent/localintermediate.h
+++ b/glslang/MachineIndependent/localintermediate.h
@@ -255,6 +255,7 @@
         textureSamplerTransformMode(EShTexSampTransKeep),
         needToLegalize(false),
         binaryDoubleOutput(false),
+        usePhysicalStorageBuffer(false),
         uniformLocationBase(0)
     {
         localSize[0] = 1;
@@ -390,6 +391,11 @@
         processes.addProcess("use-vulkan-memory-model");
     }
     bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; }
+    void setUsePhysicalStorageBuffer()
+    {
+        usePhysicalStorageBuffer = true;
+    }
+    bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; }
 
     template<class T> T addCounterBufferName(const T& name) const { return name + implicitCounterName; }
     bool hasCounterBufferName(const TString& name) const {
@@ -825,6 +831,7 @@
 
     bool needToLegalize;
     bool binaryDoubleOutput;
+    bool usePhysicalStorageBuffer;
 
     std::unordered_map<std::string, int> uniformLocationOverrides;
     int uniformLocationBase;
diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp
index 565eddd..170f985 100644
--- a/gtests/Spv.FromFile.cpp
+++ b/gtests/Spv.FromFile.cpp
@@ -265,6 +265,22 @@
         "spv.bool.vert",
         "spv.boolInBlock.frag",
         "spv.branch-return.vert",
+        "spv.bufferhandle1.frag",
+        "spv.bufferhandle10.frag",
+        "spv.bufferhandle11.frag",
+        "spv.bufferhandle12.frag",
+        "spv.bufferhandle13.frag",
+        "spv.bufferhandle14.frag",
+        "spv.bufferhandle15.frag",
+        "spv.bufferhandle2.frag",
+        "spv.bufferhandle3.frag",
+        "spv.bufferhandle4.frag",
+        "spv.bufferhandle5.frag",
+        "spv.bufferhandle6.frag",
+        "spv.bufferhandle7.frag",
+        "spv.bufferhandle8.frag",
+        "spv.bufferhandle9.frag",
+        "spv.bufferhandle_Error.frag",
         "spv.builtInXFB.vert",
         "spv.conditionalDiscard.frag",
         "spv.constStruct.vert",
diff --git a/known_good.json b/known_good.json
index b5c668c..face836 100644
--- a/known_good.json
+++ b/known_good.json
@@ -5,14 +5,14 @@
       "site" : "github",
       "subrepo" : "KhronosGroup/SPIRV-Tools",
       "subdir" : "External/spirv-tools",
-      "commit" : "a87d3ce48e88a653e855c3245a6b68deeae58efc"
+      "commit" : "5eab6df648eace6eab69c44ccd17bd0f5e57406d"
     },
     {
       "name" : "spirv-tools/external/spirv-headers",
       "site" : "github",
       "subrepo" : "KhronosGroup/SPIRV-Headers",
       "subdir" : "External/spirv-tools/external/spirv-headers",
-      "commit" : "4618b86e9e4b027a22040732dfee35e399cd2c47"
+      "commit" : "79b6681aadcb53c27d1052e5f8a0e82a981dbf2f"
     }
   ]
 }