diff options
author | John Kessenich <cepheus@frii.com> | 2016-06-30 21:18:02 -0600 |
---|---|---|
committer | John Kessenich <cepheus@frii.com> | 2016-06-30 21:28:33 -0600 |
commit | 6090df0fa30a075f2ab904002cbd1e3e00c27eae (patch) | |
tree | a64a42639cd716f61e5ad1c3ff475f2922424ef1 /SPIRV/GlslangToSpv.cpp | |
parent | 266b1d3e84685126bb070c8ba1bd2aafe78b52d6 (diff) | |
download | glslang-6090df0fa30a075f2ab904002cbd1e3e00c27eae.tar.gz |
SPV: Non-functional: break up big function into three smaller ones.
Also, improve variable names. This grew to be overly hard to understand.
Diffstat (limited to 'SPIRV/GlslangToSpv.cpp')
-rwxr-xr-x | SPIRV/GlslangToSpv.cpp | 285 |
1 files changed, 156 insertions, 129 deletions
diff --git a/SPIRV/GlslangToSpv.cpp b/SPIRV/GlslangToSpv.cpp index 7f12090a..6c9068fc 100755 --- a/SPIRV/GlslangToSpv.cpp +++ b/SPIRV/GlslangToSpv.cpp @@ -115,6 +115,10 @@ protected: spv::Id getSampledType(const glslang::TSampler&); spv::Id convertGlslangToSpvType(const glslang::TType& type); spv::Id convertGlslangToSpvType(const glslang::TType& type, glslang::TLayoutPacking, const glslang::TQualifier&); + spv::Id convertGlslangStructToSpvType(const glslang::TType&, const glslang::TTypeList* glslangStruct, + glslang::TLayoutPacking, const glslang::TQualifier&); + void decorateStructType(const glslang::TType&, const glslang::TTypeList* glslangStruct, glslang::TLayoutPacking, + const glslang::TQualifier&, spv::Id); spv::Id makeArraySizeId(const glslang::TArraySizes&, int dim); spv::Id accessChainLoad(const glslang::TType& type); void accessChainStore(const glslang::TType& type, spv::Id rvalue); @@ -1789,6 +1793,7 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty // 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) { spv::Id spvType = spv::NoResult; @@ -1851,144 +1856,19 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty case glslang::EbtBlock: { // If we've seen this struct type, return it - const glslang::TTypeList* glslangStruct = type.getStruct(); - std::vector<spv::Id> structFields; + const glslang::TTypeList* glslangMembers = type.getStruct(); // Try to share structs for different layouts, but not yet for other // kinds of qualification (primarily not yet including interpolant qualification). if (! HasNonLayoutQualifiers(qualifier)) - spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangStruct]; + spvType = structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers]; if (spvType != spv::NoResult) break; // else, we haven't seen it... - - // Create a vector of struct types for SPIR-V to consume - int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangStruct].resize(glslangStruct->size()); - int locationOffset = 0; // for use across struct members, when they are called recursively - for (int i = 0; i < (int)glslangStruct->size(); i++) { - glslang::TType& glslangType = *(*glslangStruct)[i].type; - if (glslangType.hiddenMember()) { - ++memberDelta; - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangStruct][i] = -1; - } else { - if (type.getBasicType() == glslang::EbtBlock) - memberRemapper[glslangStruct][i] = i - memberDelta; - // modify just this child's view of the qualifier - glslang::TQualifier subQualifier = glslangType.getQualifier(); - InheritQualifiers(subQualifier, qualifier); - - // manually inherit location; it's more complex - if (! subQualifier.hasLocation() && qualifier.hasLocation()) - subQualifier.layoutLocation = qualifier.layoutLocation + locationOffset; - if (qualifier.hasLocation()) - locationOffset += glslangIntermediate->computeTypeLocationSize(glslangType); - - // recurse - structFields.push_back(convertGlslangToSpvType(glslangType, explicitLayout, subQualifier)); - } - } - - // Make the SPIR-V type - spvType = builder.makeStructType(structFields, type.getTypeName().c_str()); - if (! HasNonLayoutQualifiers(qualifier)) - structMap[explicitLayout][qualifier.layoutMatrix][glslangStruct] = spvType; - - // Name and decorate the non-hidden members - int offset = -1; - locationOffset = 0; // for use within the members of this struct, right now - for (int i = 0; i < (int)glslangStruct->size(); i++) { - glslang::TType& glslangType = *(*glslangStruct)[i].type; - int member = i; - if (type.getBasicType() == glslang::EbtBlock) - member = memberRemapper[glslangStruct][i]; - - // modify just this child's view of the qualifier - glslang::TQualifier subQualifier = glslangType.getQualifier(); - InheritQualifiers(subQualifier, qualifier); - - // using -1 above to indicate a hidden member - if (member >= 0) { - builder.addMemberName(spvType, member, glslangType.getFieldName().c_str()); - addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangType, subQualifier.layoutMatrix)); - addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangType)); - // Add interpolation and auxiliary storage decorations only to top-level members of Input and Output storage classes - if (type.getQualifier().storage == glslang::EvqVaryingIn || type.getQualifier().storage == glslang::EvqVaryingOut) { - if (type.getBasicType() == glslang::EbtBlock) { - addMemberDecoration(spvType, member, TranslateInterpolationDecoration(subQualifier)); - addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(subQualifier)); - } - } - addMemberDecoration(spvType, member, TranslateInvariantDecoration(subQualifier)); - - if (qualifier.storage == glslang::EvqBuffer) { - std::vector<spv::Decoration> memory; - TranslateMemoryDecoration(subQualifier, memory); - for (unsigned int i = 0; i < memory.size(); ++i) - addMemberDecoration(spvType, member, memory[i]); - } - - // compute location decoration; tricky based on whether inheritance is at play - // TODO: This algorithm (and it's cousin above doing almost the same thing) should - // probably move to the linker stage of the front end proper, and just have the - // answer sitting already distributed throughout the individual member locations. - int location = -1; // will only decorate if present or inherited - if (subQualifier.hasLocation()) { // no inheritance, or override of inheritance - // struct members should not have explicit locations - assert(type.getBasicType() != glslang::EbtStruct); - location = subQualifier.layoutLocation; - } else if (type.getBasicType() != glslang::EbtBlock) { - // If it is a not a Block, (...) Its members are assigned consecutive locations (...) - // The members, and their nested types, must not themselves have Location decorations. - } - else if (qualifier.hasLocation()) // inheritance - location = qualifier.layoutLocation + locationOffset; - if (qualifier.hasLocation()) // track for upcoming inheritance - locationOffset += glslangIntermediate->computeTypeLocationSize(glslangType); - if (location >= 0) - builder.addMemberDecoration(spvType, member, spv::DecorationLocation, location); - - // component, XFB, others - if (glslangType.getQualifier().hasComponent()) - builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangType.getQualifier().layoutComponent); - if (glslangType.getQualifier().hasXfbOffset()) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangType.getQualifier().layoutXfbOffset); - else if (explicitLayout != glslang::ElpNone) { - // figure out what to do with offset, which is accumulating - int nextOffset; - updateMemberOffset(type, glslangType, offset, nextOffset, explicitLayout, subQualifier.layoutMatrix); - if (offset >= 0) - builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset); - offset = nextOffset; - } - - if (glslangType.isMatrix() && explicitLayout != glslang::ElpNone) - builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangType, explicitLayout, subQualifier.layoutMatrix)); - - // built-in variable decorations - spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangType.getQualifier().builtIn, true); - if (builtIn != spv::BadValue) - addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); - } - } - - // Decorate the structure - addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix)); - addDecoration(spvType, TranslateBlockDecoration(type)); - if (type.getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { - builder.addCapability(spv::CapabilityGeometryStreams); - builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream); - } - if (glslangIntermediate->getXfbMode()) { - builder.addCapability(spv::CapabilityTransformFeedback); - if (type.getQualifier().hasXfbStride()) - builder.addDecoration(spvType, spv::DecorationXfbStride, type.getQualifier().layoutXfbStride); - if (type.getQualifier().hasXfbBuffer()) - builder.addDecoration(spvType, spv::DecorationXfbBuffer, type.getQualifier().layoutXfbBuffer); - } + memberRemapper[glslangMembers].resize(glslangMembers->size()); + spvType = convertGlslangStructToSpvType(type, glslangMembers, explicitLayout, qualifier); } break; default: @@ -2051,6 +1931,153 @@ spv::Id TGlslangToSpvTraverser::convertGlslangToSpvType(const glslang::TType& ty return spvType; } + +// Do full recursive conversion of a glslang structure (or block) type to a SPIR-V Id. +// explicitLayout can be kept the same throughout the hierarchical recursive walk. +// Mutually recursive with convertGlslangToSpvType(). +spv::Id TGlslangToSpvTraverser::convertGlslangStructToSpvType(const glslang::TType& type, + const glslang::TTypeList* glslangMembers, + glslang::TLayoutPacking explicitLayout, + const glslang::TQualifier& qualifier) +{ + // Create a vector of struct types for SPIR-V to consume + std::vector<spv::Id> spvMembers; + int memberDelta = 0; // how much the member's index changes from glslang to SPIR-V, normally 0, except sometimes for blocks + int locationOffset = 0; // for use across struct members, when they are called recursively + for (int i = 0; i < (int)glslangMembers->size(); i++) { + glslang::TType& glslangMember = *(*glslangMembers)[i].type; + if (glslangMember.hiddenMember()) { + ++memberDelta; + if (type.getBasicType() == glslang::EbtBlock) + memberRemapper[glslangMembers][i] = -1; + } else { + if (type.getBasicType() == glslang::EbtBlock) + memberRemapper[glslangMembers][i] = i - memberDelta; + // modify just this child's view of the qualifier + glslang::TQualifier memberQualifier = glslangMember.getQualifier(); + InheritQualifiers(memberQualifier, qualifier); + + // manually inherit location; it's more complex + if (! memberQualifier.hasLocation() && qualifier.hasLocation()) + memberQualifier.layoutLocation = qualifier.layoutLocation + locationOffset; + if (qualifier.hasLocation()) + locationOffset += glslangIntermediate->computeTypeLocationSize(glslangMember); + + // recurse + spvMembers.push_back(convertGlslangToSpvType(glslangMember, explicitLayout, memberQualifier)); + } + } + + // Make the SPIR-V type + spv::Id spvType = builder.makeStructType(spvMembers, type.getTypeName().c_str()); + if (! HasNonLayoutQualifiers(qualifier)) + structMap[explicitLayout][qualifier.layoutMatrix][glslangMembers] = spvType; + + // Decorate it + decorateStructType(type, glslangMembers, explicitLayout, qualifier, spvType); + + return spvType; +} + +void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type, + const glslang::TTypeList* glslangMembers, + glslang::TLayoutPacking explicitLayout, + const glslang::TQualifier& qualifier, + spv::Id spvType) +{ + // Name and decorate the non-hidden members + int offset = -1; + int locationOffset = 0; // for use within the members of this struct + for (int i = 0; i < (int)glslangMembers->size(); i++) { + glslang::TType& glslangMember = *(*glslangMembers)[i].type; + int member = i; + if (type.getBasicType() == glslang::EbtBlock) + member = memberRemapper[glslangMembers][i]; + + // modify just this child's view of the qualifier + glslang::TQualifier memberQualifier = glslangMember.getQualifier(); + InheritQualifiers(memberQualifier, qualifier); + + // using -1 above to indicate a hidden member + if (member >= 0) { + builder.addMemberName(spvType, member, glslangMember.getFieldName().c_str()); + addMemberDecoration(spvType, member, TranslateLayoutDecoration(glslangMember, memberQualifier.layoutMatrix)); + addMemberDecoration(spvType, member, TranslatePrecisionDecoration(glslangMember)); + // Add interpolation and auxiliary storage decorations only to top-level members of Input and Output storage classes + if (type.getQualifier().storage == glslang::EvqVaryingIn || type.getQualifier().storage == glslang::EvqVaryingOut) { + if (type.getBasicType() == glslang::EbtBlock) { + addMemberDecoration(spvType, member, TranslateInterpolationDecoration(memberQualifier)); + addMemberDecoration(spvType, member, TranslateAuxiliaryStorageDecoration(memberQualifier)); + } + } + addMemberDecoration(spvType, member, TranslateInvariantDecoration(memberQualifier)); + + if (qualifier.storage == glslang::EvqBuffer) { + std::vector<spv::Decoration> memory; + TranslateMemoryDecoration(memberQualifier, memory); + for (unsigned int i = 0; i < memory.size(); ++i) + addMemberDecoration(spvType, member, memory[i]); + } + + // compute location decoration; tricky based on whether inheritance is at play + // TODO: This algorithm (and it's cousin above doing almost the same thing) should + // probably move to the linker stage of the front end proper, and just have the + // answer sitting already distributed throughout the individual member locations. + int location = -1; // will only decorate if present or inherited + if (memberQualifier.hasLocation()) { // no inheritance, or override of inheritance + // struct members should not have explicit locations + assert(type.getBasicType() != glslang::EbtStruct); + location = memberQualifier.layoutLocation; + } else if (type.getBasicType() != glslang::EbtBlock) { + // If it is a not a Block, (...) Its members are assigned consecutive locations (...) + // The members, and their nested types, must not themselves have Location decorations. + } else if (qualifier.hasLocation()) // inheritance + location = qualifier.layoutLocation + locationOffset; + if (qualifier.hasLocation()) // track for upcoming inheritance + locationOffset += glslangIntermediate->computeTypeLocationSize(glslangMember); + if (location >= 0) + builder.addMemberDecoration(spvType, member, spv::DecorationLocation, location); + + // component, XFB, others + if (glslangMember.getQualifier().hasComponent()) + builder.addMemberDecoration(spvType, member, spv::DecorationComponent, glslangMember.getQualifier().layoutComponent); + if (glslangMember.getQualifier().hasXfbOffset()) + builder.addMemberDecoration(spvType, member, spv::DecorationOffset, glslangMember.getQualifier().layoutXfbOffset); + else if (explicitLayout != glslang::ElpNone) { + // figure out what to do with offset, which is accumulating + int nextOffset; + updateMemberOffset(type, glslangMember, offset, nextOffset, explicitLayout, memberQualifier.layoutMatrix); + if (offset >= 0) + builder.addMemberDecoration(spvType, member, spv::DecorationOffset, offset); + offset = nextOffset; + } + + if (glslangMember.isMatrix() && explicitLayout != glslang::ElpNone) + builder.addMemberDecoration(spvType, member, spv::DecorationMatrixStride, getMatrixStride(glslangMember, explicitLayout, memberQualifier.layoutMatrix)); + + // built-in variable decorations + spv::BuiltIn builtIn = TranslateBuiltInDecoration(glslangMember.getQualifier().builtIn, true); + if (builtIn != spv::BadValue) + addMemberDecoration(spvType, member, spv::DecorationBuiltIn, (int)builtIn); + } + } + + // Decorate the structure + addDecoration(spvType, TranslateLayoutDecoration(type, qualifier.layoutMatrix)); + addDecoration(spvType, TranslateBlockDecoration(type)); + if (type.getQualifier().hasStream() && glslangIntermediate->isMultiStream()) { + builder.addCapability(spv::CapabilityGeometryStreams); + builder.addDecoration(spvType, spv::DecorationStream, type.getQualifier().layoutStream); + } + if (glslangIntermediate->getXfbMode()) { + builder.addCapability(spv::CapabilityTransformFeedback); + if (type.getQualifier().hasXfbStride()) + builder.addDecoration(spvType, spv::DecorationXfbStride, type.getQualifier().layoutXfbStride); + if (type.getQualifier().hasXfbBuffer()) + builder.addDecoration(spvType, spv::DecorationXfbBuffer, type.getQualifier().layoutXfbBuffer); + } +} + // Turn the expression forming the array size into an id. // This is not quite trivial, because of specialization constants. // Sometimes, a raw constant is turned into an Id, and sometimes |