diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp index 254177c6a..38cbd0e66 100644 --- a/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/compiler/translator/OutputGLSLBase.cpp @@ -206,6 +206,45 @@ std::string TOutputGLSLBase::getCommonLayoutQualifiers(TIntermTyped *variable) return out.str(); } +// Outputs what comes after in/out/uniform/buffer storage qualifier. +std::string TOutputGLSLBase::getMemoryQualifiers(const TType &type) +{ + std::ostringstream out; + + const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier(); + if (memoryQualifier.readonly) + { + ASSERT(IsImage(type.getBasicType())); + out << "readonly "; + } + + if (memoryQualifier.writeonly) + { + ASSERT(IsImage(type.getBasicType())); + out << "writeonly "; + } + + if (memoryQualifier.coherent) + { + ASSERT(IsImage(type.getBasicType())); + out << "coherent "; + } + + if (memoryQualifier.restrictQualifier) + { + ASSERT(IsImage(type.getBasicType())); + out << "restrict "; + } + + if (memoryQualifier.volatileQualifier) + { + ASSERT(IsImage(type.getBasicType())); + out << "volatile "; + } + + return out.str(); +} + void TOutputGLSLBase::writeLayoutQualifier(TIntermTyped *variable) { const TType &type = variable->getType(); @@ -261,6 +300,8 @@ void TOutputGLSLBase::writeQualifier(TQualifier qualifier, const TType &type, co { objSink() << result << " "; } + + objSink() << getMemoryQualifiers(type); } const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier) @@ -312,37 +353,6 @@ void TOutputGLSLBase::writeVariableType(const TType &type, const TSymbol *symbol writeQualifier(qualifier, type, symbol); } - const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier(); - if (memoryQualifier.readonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "readonly "; - } - - if (memoryQualifier.writeonly) - { - ASSERT(IsImage(type.getBasicType())); - out << "writeonly "; - } - - if (memoryQualifier.coherent) - { - ASSERT(IsImage(type.getBasicType())); - out << "coherent "; - } - - if (memoryQualifier.restrictQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "restrict "; - } - - if (memoryQualifier.volatileQualifier) - { - ASSERT(IsImage(type.getBasicType())); - out << "volatile "; - } - // Declare the struct if we have not done so already. if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) { diff --git a/src/compiler/translator/OutputGLSLBase.h b/src/compiler/translator/OutputGLSLBase.h index feeffee29..d6f9416f3 100644 --- a/src/compiler/translator/OutputGLSLBase.h +++ b/src/compiler/translator/OutputGLSLBase.h @@ -41,6 +41,7 @@ class TOutputGLSLBase : public TIntermTraverser void writeFloat(TInfoSinkBase &out, float f); void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr); std::string getCommonLayoutQualifiers(TIntermTyped *variable); + std::string getMemoryQualifiers(const TType &type); virtual void writeLayoutQualifier(TIntermTyped *variable); void writeInvariantQualifier(const TType &type); virtual void writeVariableType(const TType &type, const TSymbol *symbol); diff --git a/src/compiler/translator/OutputVulkanGLSL.cpp b/src/compiler/translator/OutputVulkanGLSL.cpp index c7121949d..265181b51 100644 --- a/src/compiler/translator/OutputVulkanGLSL.cpp +++ b/src/compiler/translator/OutputVulkanGLSL.cpp @@ -133,8 +133,8 @@ void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier, const TType &type, const TSymbol *symbol) { - if (qualifier != EvqUniform && qualifier != EvqAttribute && qualifier != EvqVertexIn && - !sh::IsVarying(qualifier)) + if (qualifier != EvqUniform && qualifier != EvqBuffer && qualifier != EvqAttribute && + qualifier != EvqVertexIn && !sh::IsVarying(qualifier)) { TOutputGLSLBase::writeQualifier(qualifier, type, symbol); return; @@ -155,7 +155,7 @@ void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier, } TInfoSinkBase &out = objSink(); - out << "@@ QUALIFIER-" << name.data() << " @@ "; + out << "@@ QUALIFIER-" << name.data() << "(" << getMemoryQualifiers(type) << ") @@ "; } void TOutputVulkanGLSL::writeVariableType(const TType &type, const TSymbol *symbol) diff --git a/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp b/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp index 00ee61b6b..512201ab8 100644 --- a/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp +++ b/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp @@ -40,8 +40,8 @@ constexpr char kLayoutMarkerBegin[] = "@@ LAYOUT-"; constexpr char kXfbDeclMarkerBegin[] = "@@ XFB-DECL"; constexpr char kXfbOutMarkerBegin[] = "@@ XFB-OUT"; constexpr char kMarkerEnd[] = " @@"; -constexpr char kLayoutParamsBegin = '('; -constexpr char kLayoutParamsEnd = ')'; +constexpr char kParamsBegin = '('; +constexpr char kParamsEnd = ')'; constexpr char kUniformQualifier[] = "uniform"; constexpr char kVersionDefine[] = "#version 450 core\n"; constexpr char kLineRasterDefine[] = R"(#version 450 core @@ -101,13 +101,18 @@ class IntermediateShaderSource final : angle::NonCopyable // // layout(specifier, extra, args) // - // or if specifier is empty, + // or if |specifier| is empty: // // layout(extra, args) // void insertLayoutSpecifier(const std::string &name, const std::string &specifier); - // Find @@ QUALIFIER-name @@ and replace it with |specifier|. + // Find @@ QUALIFIER-name(other qualifiers) @@ and replace it with: + // + // specifier other qualifiers + // + // or if |specifier| is empty, with nothing. + // void insertQualifierSpecifier(const std::string &name, const std::string &specifier); // Replace @@ XFB-DECL @@ with |decl|. @@ -116,7 +121,7 @@ class IntermediateShaderSource final : angle::NonCopyable // Replace @@ XFB-OUT @@ with |output| code block. void insertTransformFeedbackOutput(const std::string &&output); - // Remove @@ LAYOUT-name(*) @@ and @@ QUALIFIER-name @@ altogether, optionally replacing them + // Remove @@ LAYOUT-name(*) @@ and @@ QUALIFIER-name(*) @@ altogether, optionally replacing them // with something to make sure the shader still compiles. void eraseLayoutAndQualifierSpecifiers(const std::string &name, const std::string &replacement); @@ -128,7 +133,7 @@ class IntermediateShaderSource final : angle::NonCopyable { // A piece of shader source code. Text, - // Block corresponding to @@ QUALIFIER-abc @@ + // Block corresponding to @@ QUALIFIER-abc(other qualifiers) @@ Qualifier, // Block corresponding to @@ LAYOUT-abc(extra, args) @@ Layout, @@ -144,13 +149,13 @@ class IntermediateShaderSource final : angle::NonCopyable // |text| contains some shader code if Text, or the id of macro ("abc" in examples above) // being replaced if Qualifier or Layout. std::string text; - // If Layout, this contains extra parameters passed in parentheses, if any. + // If Qualifier or Layout, this contains extra parameters passed in parentheses, if any. std::string args; }; void addTextBlock(std::string &&text); void addLayoutBlock(std::string &&name, std::string &&args); - void addQualifierBlock(std::string &&name); + void addQualifierBlock(std::string &&name, std::string &&args); void addTransformFeedbackDeclarationBlock(); void addTransformFeedbackOutputBlock(); @@ -175,10 +180,10 @@ void IntermediateShaderSource::addLayoutBlock(std::string &&name, std::string && mTokens.emplace_back(std::move(token)); } -void IntermediateShaderSource::addQualifierBlock(std::string &&name) +void IntermediateShaderSource::addQualifierBlock(std::string &&name, std::string &&args) { ASSERT(!name.empty()); - Token token = {TokenType::Qualifier, std::move(name), ""}; + Token token = {TokenType::Qualifier, std::move(name), std::move(args)}; mTokens.emplace_back(std::move(token)); } @@ -194,6 +199,21 @@ void IntermediateShaderSource::addTransformFeedbackOutputBlock() mTokens.emplace_back(std::move(token)); } +size_t ExtractNameAndArgs(const std::string &source, + size_t cur, + std::string *nameOut, + std::string *argsOut) +{ + *nameOut = angle::GetPrefix(source, cur, kParamsBegin); + + // There should always be an extra args list (even if empty, for simplicity). + size_t readCount = nameOut->length() + 1; + *argsOut = angle::GetPrefix(source, cur + readCount, kParamsEnd); + readCount += argsOut->length() + 1; + + return readCount; +} + IntermediateShaderSource::IntermediateShaderSource(const std::string &source) { size_t cur = 0; @@ -216,21 +236,18 @@ IntermediateShaderSource::IntermediateShaderSource(const std::string &source) { cur += ConstStrLen(kQualifierMarkerBegin); - // Get the id of the macro and add a qualifier block. - std::string name = angle::GetPrefix(source, cur, kMarkerEnd); - cur += name.length(); - addQualifierBlock(std::move(name)); + // Get the id and arguments of the macro and add a qualifier block. + std::string name, args; + cur += ExtractNameAndArgs(source, cur, &name, &args); + addQualifierBlock(std::move(name), std::move(args)); } else if (source.compare(cur, ConstStrLen(kLayoutMarkerBegin), kLayoutMarkerBegin) == 0) { cur += ConstStrLen(kLayoutMarkerBegin); // Get the id and arguments of the macro and add a layout block. - // There should always be an extra args list (even if empty, for simplicity). - std::string name = angle::GetPrefix(source, cur, kLayoutParamsBegin); - cur += name.length() + 1; - std::string args = angle::GetPrefix(source, cur, kLayoutParamsEnd); - cur += args.length() + 1; + std::string name, args; + cur += ExtractNameAndArgs(source, cur, &name, &args); addLayoutBlock(std::move(name), std::move(args)); } else if (source.compare(cur, ConstStrLen(kXfbDeclMarkerBegin), kXfbDeclMarkerBegin) == 0) @@ -283,6 +300,10 @@ void IntermediateShaderSource::insertQualifierSpecifier(const std::string &name, { block.type = TokenType::Text; block.text = specifier; + if (!specifier.empty() && !block.args.empty()) + { + block.text += " " + block.args; + } break; } }