From 9f2aec49e9263a555346b9961107b497448d4d18 Mon Sep 17 00:00:00 2001 From: Jeff Bolz Date: Sun, 6 Jan 2019 17:58:04 -0600 Subject: [PATCH] GL_EXT_buffer_reference --- SPIRV/GLSL.ext.KHR.h | 1 + SPIRV/GlslangToSpv.cpp | 159 +++++++-- SPIRV/SpvBuilder.cpp | 119 ++++++- SPIRV/SpvBuilder.h | 26 +- SPIRV/SpvPostProcess.cpp | 127 +++++++- SPIRV/disassemble.cpp | 8 + SPIRV/doc.cpp | 8 + SPIRV/spirv.hpp | 29 +- SPIRV/spvIR.h | 6 + Test/baseResults/spv.bufferhandle1.frag.out | 104 ++++++ Test/baseResults/spv.bufferhandle10.frag.out | 73 +++++ Test/baseResults/spv.bufferhandle11.frag.out | 118 +++++++ Test/baseResults/spv.bufferhandle12.frag.out | 306 ++++++++++++++++++ Test/baseResults/spv.bufferhandle13.frag.out | 118 +++++++ Test/baseResults/spv.bufferhandle14.frag.out | 109 +++++++ Test/baseResults/spv.bufferhandle15.frag.out | 130 ++++++++ Test/baseResults/spv.bufferhandle2.frag.out | 94 ++++++ Test/baseResults/spv.bufferhandle3.frag.out | 105 ++++++ Test/baseResults/spv.bufferhandle4.frag.out | 118 +++++++ Test/baseResults/spv.bufferhandle5.frag.out | 52 +++ Test/baseResults/spv.bufferhandle6.frag.out | 238 ++++++++++++++ Test/baseResults/spv.bufferhandle7.frag.out | 77 +++++ Test/baseResults/spv.bufferhandle8.frag.out | 89 +++++ Test/baseResults/spv.bufferhandle9.frag.out | 114 +++++++ .../spv.bufferhandle_Error.frag.out | 25 ++ Test/spv.bufferhandle1.frag | 28 ++ Test/spv.bufferhandle10.frag | 23 ++ Test/spv.bufferhandle11.frag | 26 ++ Test/spv.bufferhandle12.frag | 42 +++ Test/spv.bufferhandle13.frag | 30 ++ Test/spv.bufferhandle14.frag | 40 +++ Test/spv.bufferhandle15.frag | 38 +++ Test/spv.bufferhandle2.frag | 25 ++ Test/spv.bufferhandle3.frag | 25 ++ Test/spv.bufferhandle4.frag | 26 ++ Test/spv.bufferhandle5.frag | 16 + Test/spv.bufferhandle6.frag | 30 ++ Test/spv.bufferhandle7.frag | 24 ++ Test/spv.bufferhandle8.frag | 32 ++ Test/spv.bufferhandle9.frag | 30 ++ Test/spv.bufferhandle_Error.frag | 45 +++ glslang/Include/BaseTypes.h | 2 + glslang/Include/Types.h | 93 +++++- glslang/Include/intermediate.h | 5 + glslang/MachineIndependent/Intermediate.cpp | 11 + glslang/MachineIndependent/ParseHelper.cpp | 195 +++++++++-- glslang/MachineIndependent/Scan.cpp | 9 +- glslang/MachineIndependent/ScanContext.h | 3 +- glslang/MachineIndependent/Versions.cpp | 2 + glslang/MachineIndependent/Versions.h | 1 + glslang/MachineIndependent/intermOut.cpp | 13 +- glslang/MachineIndependent/linkValidate.cpp | 2 + .../MachineIndependent/localintermediate.h | 7 + gtests/Spv.FromFile.cpp | 16 + known_good.json | 4 +- 55 files changed, 3093 insertions(+), 103 deletions(-) create mode 100644 Test/baseResults/spv.bufferhandle1.frag.out create mode 100644 Test/baseResults/spv.bufferhandle10.frag.out create mode 100644 Test/baseResults/spv.bufferhandle11.frag.out create mode 100644 Test/baseResults/spv.bufferhandle12.frag.out create mode 100644 Test/baseResults/spv.bufferhandle13.frag.out create mode 100644 Test/baseResults/spv.bufferhandle14.frag.out create mode 100644 Test/baseResults/spv.bufferhandle15.frag.out create mode 100644 Test/baseResults/spv.bufferhandle2.frag.out create mode 100644 Test/baseResults/spv.bufferhandle3.frag.out create mode 100644 Test/baseResults/spv.bufferhandle4.frag.out create mode 100644 Test/baseResults/spv.bufferhandle5.frag.out create mode 100644 Test/baseResults/spv.bufferhandle6.frag.out create mode 100644 Test/baseResults/spv.bufferhandle7.frag.out create mode 100644 Test/baseResults/spv.bufferhandle8.frag.out create mode 100644 Test/baseResults/spv.bufferhandle9.frag.out create mode 100644 Test/baseResults/spv.bufferhandle_Error.frag.out create mode 100644 Test/spv.bufferhandle1.frag create mode 100644 Test/spv.bufferhandle10.frag create mode 100644 Test/spv.bufferhandle11.frag create mode 100644 Test/spv.bufferhandle12.frag create mode 100644 Test/spv.bufferhandle13.frag create mode 100644 Test/spv.bufferhandle14.frag create mode 100644 Test/spv.bufferhandle15.frag create mode 100644 Test/spv.bufferhandle2.frag create mode 100644 Test/spv.bufferhandle3.frag create mode 100644 Test/spv.bufferhandle4.frag create mode 100644 Test/spv.bufferhandle5.frag create mode 100644 Test/spv.bufferhandle6.frag create mode 100644 Test/spv.bufferhandle7.frag create mode 100644 Test/spv.bufferhandle8.frag create mode 100644 Test/spv.bufferhandle9.frag create mode 100644 Test/spv.bufferhandle_Error.frag diff --git a/SPIRV/GLSL.ext.KHR.h b/SPIRV/GLSL.ext.KHR.h index 16b0d9cf..333442bb 100644 --- a/SPIRV/GLSL.ext.KHR.h +++ b/SPIRV/GLSL.ext.KHR.h @@ -40,5 +40,6 @@ static const char* const E_SPV_KHR_8bit_storage = "SPV_KHR_8bit_ 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 6dc25ab1..c7cab841 100644 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -145,9 +145,9 @@ protected: 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& 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 @@ protected: 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 @@ protected: std::unordered_map > memberRemapper; std::stack breakForLoop; // false means break for switch std::unordered_map counterOriginator; + // Map pointee types for EbtReference to their forward pointers + std::map forwardPointers; }; // @@ -1303,12 +1314,22 @@ TGlslangToSpvTraverser::TGlslangToSpvTraverser(unsigned int spvVersion, const gl 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 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T // so short circuit the access-chain stuff with a swizzle. std::vector 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 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T } // 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 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T // 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 @@ bool TGlslangToSpvTraverser::visitBinary(glslang::TVisit /* visit */, glslang::T node->getLeft()->traverse(this); std::vector 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 @@ bool TGlslangToSpvTraverser::visitAggregate(glslang::TVisit visit, glslang::TInt case glslang::EOpConstructU64Vec4: case glslang::EOpConstructStruct: case glslang::EOpConstructTextureSampler: + case glslang::EOpConstructReference: { builder.setLine(node->getLoc().line, node->getLoc().getFilename()); std::vector arguments; @@ -2829,6 +2873,7 @@ spv::Id TGlslangToSpvTraverser::createSpvVariable(const glslang::TIntermSymbol* 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 @@ void TGlslangToSpvTraverser::convertSwizzle(const glslang::TIntermAggregate& nod // 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 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty 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 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy // Create a vector of struct types for SPIR-V to consume std::vector spvMembers; int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks + std::vector > deferredForwardPointers; for (int i = 0; i < (int)glslangMembers->size(); i++) { glslang::TType& glslangMember = *(*glslangMembers)[i].type; if (glslangMember.hiddenMember()) { @@ -3144,8 +3208,19 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy // 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 @@ spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TTy // 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::Id TGlslangToSpvTraverser::accessChainLoad(const glslang::TType& type) 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 @@ void TGlslangToSpvTraverser::accessChainStore(const glslang::TType& type, spv::I 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 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id // 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 @@ void TGlslangToSpvTraverser::multiTypeStore(const glslang::TType& type, spv::Id // 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 @@ bool TGlslangToSpvTraverser::originalParam(glslang::TStorageQualifier qualifier, // Make all the functions, skeletally, without actually visiting their bodies. void TGlslangToSpvTraverser::makeFunctions(const glslang::TIntermSequence& glslFunctions) { - const auto getParamDecorations = [](std::vector& decorations, const glslang::TType& type, bool useVulkanMemoryModel) { + const auto getParamDecorations = [&](std::vector& 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::Id TGlslangToSpvTraverser::createImageTextureFunctionCall(glslang::TIntermO 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 @@ spv::Id TGlslangToSpvTraverser::createUnaryOperation(glslang::TOperator op, OpDe unaryOp = spv::OpGroupNonUniformPartitionNV; break; #endif + case glslang::EOpConstructReference: + unaryOp = spv::OpBitcast; + break; default: return 0; } @@ -5782,6 +5883,12 @@ spv::Id TGlslangToSpvTraverser::createConversion(glslang::TOperator op, OpDecora // 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 @@ spv::Id TGlslangToSpvTraverser::getSymbolId(const glslang::TIntermSymbol* symbol 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 @@ spv::Id TGlslangToSpvTraverser::createSpvConstantFromConstUnionArray(const glsla 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::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 9ba3158e..3375ec4f 100755 --- a/SPIRV/SpvBuilder.cpp +++ b/SPIRV/SpvBuilder.cpp @@ -194,6 +194,40 @@ Id Builder::makePointer(StorageClass storageClass, Id pointee) 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(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(type)); + module.mapInstruction(type); + + return type->getResultId(); +} + Id Builder::makeIntegerType(int width, bool hasSign) { // try to find it @@ -576,6 +610,7 @@ int Builder::getNumTypeConstituents(Id typeId) const case OpTypeBool: case OpTypeInt: case OpTypeFloat: + case OpTypePointer: return 1; case OpTypeVector: case OpTypeMatrix: @@ -669,17 +704,36 @@ bool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const 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 @@ Id Builder::createUndefined(Id type) 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 @@ void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAcce } // 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 @@ Id Builder::createConstructor(Decoration precision, const std::vector& sourc // 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 @@ void Builder::clearAccessChain() accessChain.preSwizzleBaseType = NoType; accessChain.isRValue = false; accessChain.coherentFlags.clear(); + accessChain.alignment = 0; } // Comments in header -void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizzleBaseType) +void Builder::accessChainPushSwizzle(std::vector& 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 @@ void Builder::accessChainPushSwizzle(std::vector& swizzle, Id preSwizz } // 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 @@ void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, sp 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 Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resu 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 3af6ace3..edeac1b6 100755 --- a/SPIRV/SpvBuilder.h +++ b/SPIRV/SpvBuilder.h @@ -138,7 +138,9 @@ public: // 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 @@ public: 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 @@ public: 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& offsets); @@ -535,6 +538,7 @@ public: 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 @@ public: } // 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& swizzle, Id preSwizzleBaseType); + void accessChainPushSwizzle(std::vector& 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 @@ public: 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 @@ public: void dumpSourceInstructions(const spv::Id fileId, const std::string& text, std::vector&) const; void dumpInstructions(std::vector&, const std::vector >&) const; void dumpModuleProcesses(std::vector&) 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 51875307..04d594cb 100755 --- a/SPIRV/SpvPostProcess.cpp +++ b/SPIRV/SpvPostProcess.cpp @@ -87,6 +87,7 @@ void Builder::postProcessType(const Instruction& inst, Id typeId) StorageClass storageClass = getStorageClass(inst.getIdOperand(0)); if (width == 8) { switch (storageClass) { + case StorageClassPhysicalStorageBufferEXT: case StorageClassUniform: case StorageClassStorageBuffer: case StorageClassPushConstant: @@ -97,6 +98,7 @@ void Builder::postProcessType(const Instruction& inst, Id typeId) } } else if (width == 16) { switch (storageClass) { + case StorageClassPhysicalStorageBufferEXT: case StorageClassUniform: case StorageClassStorageBuffer: case StorageClassPushConstant: @@ -151,7 +153,7 @@ void Builder::postProcessType(const Instruction& inst, Id typeId) } // 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 @@ void Builder::postProcess(const Instruction& inst) 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& 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& 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 @@ void Builder::postProcess() 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& 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 22c83ea9..631173c0 100644 --- a/SPIRV/disassemble.cpp +++ b/SPIRV/disassemble.cpp @@ -540,6 +540,14 @@ void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, 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 b0b01fba..bd6df107 100644 --- a/SPIRV/doc.cpp +++ b/SPIRV/doc.cpp @@ -124,6 +124,8 @@ const char* AddressingString(int addr) case 1: return "Physical32"; case 2: return "Physical64"; + case AddressingModelPhysicalStorageBuffer64EXT: return "PhysicalStorageBuffer64EXT"; + default: return "Bad"; } } @@ -220,6 +222,8 @@ const char* StorageClassString(int StorageClass) case StorageClassIncomingCallableDataNV: return "IncomingCallableDataNV"; #endif + case StorageClassPhysicalStorageBufferEXT: return "PhysicalStorageBufferEXT"; + default: return "Bad"; } } @@ -295,6 +299,8 @@ const char* DecorationString(int decoration) case DecorationNonUniformEXT: return "DecorationNonUniformEXT"; case DecorationHlslCounterBufferGOOGLE: return "DecorationHlslCounterBufferGOOGLE"; case DecorationHlslSemanticGOOGLE: return "DecorationHlslSemanticGOOGLE"; + case DecorationRestrictPointerEXT: return "DecorationRestrictPointerEXT"; + case DecorationAliasedPointerEXT: return "DecorationAliasedPointerEXT"; } } @@ -922,6 +928,8 @@ const char* CapabilityString(int info) case CapabilityVulkanMemoryModelKHR: return "CapabilityVulkanMemoryModelKHR"; case CapabilityVulkanMemoryModelDeviceScopeKHR: return "CapabilityVulkanMemoryModelDeviceScopeKHR"; + case CapabilityPhysicalStorageBufferAddressesEXT: return "CapabilityPhysicalStorageBufferAddressesEXT"; + default: return "Bad"; } } diff --git a/SPIRV/spirv.hpp b/SPIRV/spirv.hpp index 72e577a1..44d06168 100644 --- a/SPIRV/spirv.hpp +++ b/SPIRV/spirv.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018 The Khronos Group Inc. +// Copyright (c) 2014-2019 The Khronos Group Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and/or associated documentation files (the "Materials"), @@ -26,14 +26,16 @@ // the Binary Section of the SPIR-V specification. // Enumeration tokens for SPIR-V, in various styles: -// C, C++, C++11, JSON, Lua, Python, C# +// C, C++, C++11, JSON, Lua, Python, C#, D // // - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL // - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL // - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL // - Lua will use tables, e.g.: spv.SourceLanguage.GLSL // - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] -// - C# will use enum classes in the Specification class located in the "Spv" namespace, e.g.: Spv.Specification.SourceLanguage.GLSL +// - C# will use enum classes in the Specification class located in the "Spv" namespace, +// e.g.: Spv.Specification.SourceLanguage.GLSL +// - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL // // Some tokens act like mask values, which can be OR'd together, // while others are mutually exclusive. The mask-like ones have @@ -48,11 +50,11 @@ namespace spv { typedef unsigned int Id; #define SPV_VERSION 0x10300 -#define SPV_REVISION 1 +#define SPV_REVISION 6 static const unsigned int MagicNumber = 0x07230203; static const unsigned int Version = 0x00010300; -static const unsigned int Revision = 1; +static const unsigned int Revision = 6; static const unsigned int OpCodeMask = 0xffff; static const unsigned int WordCountShift = 16; @@ -89,6 +91,7 @@ enum AddressingModel { AddressingModelLogical = 0, AddressingModelPhysical32 = 1, AddressingModelPhysical64 = 2, + AddressingModelPhysicalStorageBuffer64EXT = 5348, AddressingModelMax = 0x7fffffff, }; @@ -140,6 +143,11 @@ enum ExecutionMode { ExecutionModeLocalSizeId = 38, ExecutionModeLocalSizeHintId = 39, ExecutionModePostDepthCoverage = 4446, + ExecutionModeDenormPreserve = 4459, + ExecutionModeDenormFlushToZero = 4460, + ExecutionModeSignedZeroInfNanPreserve = 4461, + ExecutionModeRoundingModeRTE = 4462, + ExecutionModeRoundingModeRTZ = 4463, ExecutionModeStencilRefReplacingEXT = 5027, ExecutionModeOutputLinesNV = 5269, ExecutionModeOutputPrimitivesNV = 5270, @@ -169,6 +177,7 @@ enum StorageClass { StorageClassHitAttributeNV = 5339, StorageClassIncomingRayPayloadNV = 5342, StorageClassShaderRecordBufferNV = 5343, + StorageClassPhysicalStorageBufferEXT = 5349, StorageClassMax = 0x7fffffff, }; @@ -417,6 +426,8 @@ enum Decoration { DecorationMaxByteOffset = 45, DecorationAlignmentId = 46, DecorationMaxByteOffsetId = 47, + DecorationNoSignedWrap = 4469, + DecorationNoUnsignedWrap = 4470, DecorationExplicitInterpAMD = 4999, DecorationOverrideCoverageNV = 5248, DecorationPassthroughNV = 5250, @@ -427,6 +438,8 @@ enum Decoration { DecorationPerTaskNV = 5273, DecorationPerVertexNV = 5285, DecorationNonUniformEXT = 5300, + DecorationRestrictPointerEXT = 5355, + DecorationAliasedPointerEXT = 5356, DecorationHlslCounterBufferGOOGLE = 5634, DecorationHlslSemanticGOOGLE = 5635, DecorationMax = 0x7fffffff, @@ -756,6 +769,11 @@ enum Capability { CapabilityStorageBuffer8BitAccess = 4448, CapabilityUniformAndStorageBuffer8BitAccess = 4449, CapabilityStoragePushConstant8 = 4450, + CapabilityDenormPreserve = 4464, + CapabilityDenormFlushToZero = 4465, + CapabilitySignedZeroInfNanPreserve = 4466, + CapabilityRoundingModeRTE = 4467, + CapabilityRoundingModeRTZ = 4468, CapabilityFloat16ImageAMD = 5008, CapabilityImageGatherBiasLodAMD = 5009, CapabilityFragmentMaskAMD = 5010, @@ -791,6 +809,7 @@ enum Capability { CapabilityRayTracingNV = 5340, CapabilityVulkanMemoryModelKHR = 5345, CapabilityVulkanMemoryModelDeviceScopeKHR = 5346, + CapabilityPhysicalStorageBufferAddressesEXT = 5347, CapabilityComputeDerivativeGroupLinearNV = 5350, CapabilitySubgroupShuffleINTEL = 5568, CapabilitySubgroupBufferBlockIOINTEL = 5569, diff --git a/SPIRV/spvIR.h b/SPIRV/spvIR.h index 82639603..8c2d0b6f 100755 --- a/SPIRV/spvIR.h +++ b/SPIRV/spvIR.h @@ -102,6 +102,11 @@ public: 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 @@ public: const std::vector >& getInstructions() const { return instructions; } + const std::vector >& 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 00000000..906cb51a --- /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 00000000..bfaa2d8a --- /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 00000000..0764a003 --- /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 00000000..38b390ff --- /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 00000000..14380860 --- /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 00000000..d8c27269 --- /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 00000000..a4a434d0 --- /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 00000000..fbcf16cb --- /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 00000000..a2cb85f1 --- /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 00000000..08de8711 --- /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 00000000..36564088 --- /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 00000000..54db3cf5 --- /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 00000000..4a52596e --- /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 00000000..168da818 --- /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 00000000..e74be8a5 --- /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 00000000..a1ee9a4b --- /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 00000000..14acac19 --- /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 00000000..1d537e42 --- /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 00000000..14d05dcc --- /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 00000000..cb7ec6ad --- /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 00000000..1538d90b --- /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 00000000..132af69f --- /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 00000000..ca645937 --- /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 00000000..497e5509 --- /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 00000000..6dddf20b --- /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 00000000..16a02cbf --- /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 00000000..6ad51881 --- /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 00000000..dcc30d00 --- /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 00000000..dbc9b2f1 --- /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 00000000..1bc13c3c --- /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 00000000..7c9f6085 --- /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 00000000..98cbac86 --- /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 fabd6135..1827c496 100644 --- a/glslang/Include/BaseTypes.h +++ b/glslang/Include/BaseTypes.h @@ -66,6 +66,8 @@ enum TBasicType { EbtAccStructNV, #endif + EbtReference, + // HLSL types that live only temporarily. EbtString, diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 30fc8ce1..eb57c3a0 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -721,6 +721,7 @@ public: clearUniformLayout(); layoutPushConstant = false; + layoutBufferReference = false; #ifdef NV_EXTENSIONS layoutPassthrough = false; layoutViewportRelative = false; @@ -729,6 +730,8 @@ public: layoutShaderRecordNV = false; #endif + layoutBufferReferenceAlign = layoutBufferReferenceAlignEnd; + clearInterstageLayout(); layoutSpecConstantId = layoutSpecConstantIdEnd; @@ -763,7 +766,8 @@ public: #ifdef NV_EXTENSIONS layoutShaderRecordNV || #endif - layoutPushConstant; + layoutPushConstant || + layoutBufferReference; } bool hasLayout() const { @@ -808,9 +812,14 @@ public: 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 @@ public: // 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: #ifdef NV_EXTENSIONS case EbtAccStructNV: return "accelerationStructureNV"; #endif + case EbtReference: return "reference"; default: return "unknown type"; } } @@ -1773,6 +1808,12 @@ public: } 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 @@ public: } // 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ protected: *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 @@ protected: 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 27250070..4b6bcb7b 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -269,6 +269,10 @@ enum TOperator { EOpConvDoubleToFloat16, EOpConvDoubleToFloat, + // uint64_t <-> pointer + EOpConvUint64ToPtr, + EOpConvPtrToUint64, + // // binary operations // @@ -732,6 +736,7 @@ enum TOperator { 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 a3ca56cd..32b38a0c 100755 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -984,6 +984,14 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt 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 @@ TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const } } break; + case EbtReference: + op = EOpConstructReference; + break; default: break; } diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 7ddc27ee..d16dc994 100755 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -354,6 +354,11 @@ TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symb 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 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm 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 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt } } + 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 @@ void TParseContext::globalQualifierTypeCheck(const TSourceLoc& loc, const TQuali 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 @@ void TParseContext::checkRuntimeSizable(const TSourceLoc& loc, const TIntermType 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 @@ bool TParseContext::isRuntimeLength(const TIntermTyped& base) const 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 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi 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 @@ void TParseContext::setLayoutQualifier(const TSourceLoc& loc, TPublicType& publi } #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 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie 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 @@ void TParseContext::mergeObjectLayoutQualifiers(TQualifier& dst, const TQualifie 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 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) #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 @@ void TParseContext::layoutTypeCheck(const TSourceLoc& loc, const TType& type) 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 @@ void TParseContext::layoutQualifierCheck(const TSourceLoc& loc, const TQualifier 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 @@ void TParseContext::declareTypeDefaults(const TSourceLoc& loc, const TPublicType return; } - if (publicType.qualifier.hasLayout()) + if (publicType.qualifier.hasLayout() && !publicType.qualifier.layoutBufferReference) warn(loc, "useless application of layout qualifier", "layout", ""); } @@ -6659,10 +6726,15 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T 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 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T 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 @@ void TParseContext::declareBlock(const TSourceLoc& loc, TTypeList& typeList, con 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::fixBlockUniformOffsets(TQualifier& qualifier, TTypeList& typ 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 @@ void TParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, con 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 22472502..2ec26c6f 100644 --- a/glslang/MachineIndependent/Scan.cpp +++ b/glslang/MachineIndependent/Scan.cpp @@ -776,7 +776,7 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token) 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 @@ int TScanContext::tokenize(TPpContext* pp, TParserToken& token) 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 @@ int TScanContext::tokenizeIdentifier() 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 @@ int TScanContext::identifierOrType() 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 0cc7ea0a..74b2b3c7 100644 --- a/glslang/MachineIndependent/ScanContext.h +++ b/glslang/MachineIndependent/ScanContext.h @@ -53,7 +53,7 @@ public: 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 @@ protected: 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 9b8347f6..80888454 100755 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -207,6 +207,7 @@ void TParseVersions::initializeExtensionBehavior() 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 @@ void TParseVersions::getPreamble(std::string& preamble) "#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 3207503b..0606e8e9 100755 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -169,6 +169,7 @@ const char* const E_GL_EXT_nonuniform_qualifier = "GL_EXT_nonuniform 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 5ad67906..f74b90aa 100644 --- a/glslang/MachineIndependent/intermOut.cpp +++ b/glslang/MachineIndependent/intermOut.cpp @@ -172,8 +172,12 @@ bool TOutputTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node) 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 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) 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 @@ bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node) 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 @@ bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node 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 79c8c02a..977600b5 100755 --- a/glslang/MachineIndependent/linkValidate.cpp +++ b/glslang/MachineIndependent/linkValidate.cpp @@ -261,6 +261,7 @@ void TIntermediate::mergeModes(TInfoSink& infoSink, TIntermediate& unit) MERGE_TRUE(needToLegalize); MERGE_TRUE(binaryDoubleOutput); + MERGE_TRUE(usePhysicalStorageBuffer); } // @@ -1355,6 +1356,7 @@ int TIntermediate::getBaseAlignmentScalar(const TType& type, int& size) 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 eb8fe0b1..cd589d82 100755 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -255,6 +255,7 @@ public: textureSamplerTransformMode(EShTexSampTransKeep), needToLegalize(false), binaryDoubleOutput(false), + usePhysicalStorageBuffer(false), uniformLocationBase(0) { localSize[0] = 1; @@ -390,6 +391,11 @@ public: processes.addProcess("use-vulkan-memory-model"); } bool usingVulkanMemoryModel() const { return useVulkanMemoryModel; } + void setUsePhysicalStorageBuffer() + { + usePhysicalStorageBuffer = true; + } + bool usingPhysicalStorageBuffer() const { return usePhysicalStorageBuffer; } template T addCounterBufferName(const T& name) const { return name + implicitCounterName; } bool hasCounterBufferName(const TString& name) const { @@ -825,6 +831,7 @@ protected: bool needToLegalize; bool binaryDoubleOutput; + bool usePhysicalStorageBuffer; std::unordered_map uniformLocationOverrides; int uniformLocationBase; diff --git a/gtests/Spv.FromFile.cpp b/gtests/Spv.FromFile.cpp index 565eddd7..170f985b 100644 --- a/gtests/Spv.FromFile.cpp +++ b/gtests/Spv.FromFile.cpp @@ -265,6 +265,22 @@ INSTANTIATE_TEST_CASE_P( "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 b5c668c3..face836e 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" } ] }