Commit 5dfad811 by Shahbaz Youssefi Committed by Commit Bot

Vulkan: GLSL output support for SSBO memory qualifiers

Makes the QUALIFIER macro take arguments similar to LAYOUT, to allow passing in tokens to be conditionally output after the storage qualifier. Bug: angleproject:3561 Change-Id: I4368eba2c34c1398f81d33cd23c9e56557fd4ed8 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1685876 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 91295e1a
...@@ -206,6 +206,45 @@ std::string TOutputGLSLBase::getCommonLayoutQualifiers(TIntermTyped *variable) ...@@ -206,6 +206,45 @@ std::string TOutputGLSLBase::getCommonLayoutQualifiers(TIntermTyped *variable)
return out.str(); 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) void TOutputGLSLBase::writeLayoutQualifier(TIntermTyped *variable)
{ {
const TType &type = variable->getType(); const TType &type = variable->getType();
...@@ -261,6 +300,8 @@ void TOutputGLSLBase::writeQualifier(TQualifier qualifier, const TType &type, co ...@@ -261,6 +300,8 @@ void TOutputGLSLBase::writeQualifier(TQualifier qualifier, const TType &type, co
{ {
objSink() << result << " "; objSink() << result << " ";
} }
objSink() << getMemoryQualifiers(type);
} }
const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier) const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
...@@ -312,37 +353,6 @@ void TOutputGLSLBase::writeVariableType(const TType &type, const TSymbol *symbol ...@@ -312,37 +353,6 @@ void TOutputGLSLBase::writeVariableType(const TType &type, const TSymbol *symbol
writeQualifier(qualifier, type, 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. // Declare the struct if we have not done so already.
if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
{ {
......
...@@ -41,6 +41,7 @@ class TOutputGLSLBase : public TIntermTraverser ...@@ -41,6 +41,7 @@ class TOutputGLSLBase : public TIntermTraverser
void writeFloat(TInfoSinkBase &out, float f); void writeFloat(TInfoSinkBase &out, float f);
void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr); void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr);
std::string getCommonLayoutQualifiers(TIntermTyped *variable); std::string getCommonLayoutQualifiers(TIntermTyped *variable);
std::string getMemoryQualifiers(const TType &type);
virtual void writeLayoutQualifier(TIntermTyped *variable); virtual void writeLayoutQualifier(TIntermTyped *variable);
void writeInvariantQualifier(const TType &type); void writeInvariantQualifier(const TType &type);
virtual void writeVariableType(const TType &type, const TSymbol *symbol); virtual void writeVariableType(const TType &type, const TSymbol *symbol);
......
...@@ -133,8 +133,8 @@ void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier, ...@@ -133,8 +133,8 @@ void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier,
const TType &type, const TType &type,
const TSymbol *symbol) const TSymbol *symbol)
{ {
if (qualifier != EvqUniform && qualifier != EvqAttribute && qualifier != EvqVertexIn && if (qualifier != EvqUniform && qualifier != EvqBuffer && qualifier != EvqAttribute &&
!sh::IsVarying(qualifier)) qualifier != EvqVertexIn && !sh::IsVarying(qualifier))
{ {
TOutputGLSLBase::writeQualifier(qualifier, type, symbol); TOutputGLSLBase::writeQualifier(qualifier, type, symbol);
return; return;
...@@ -155,7 +155,7 @@ void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier, ...@@ -155,7 +155,7 @@ void TOutputVulkanGLSL::writeQualifier(TQualifier qualifier,
} }
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
out << "@@ QUALIFIER-" << name.data() << " @@ "; out << "@@ QUALIFIER-" << name.data() << "(" << getMemoryQualifiers(type) << ") @@ ";
} }
void TOutputVulkanGLSL::writeVariableType(const TType &type, const TSymbol *symbol) void TOutputVulkanGLSL::writeVariableType(const TType &type, const TSymbol *symbol)
......
...@@ -40,8 +40,8 @@ constexpr char kLayoutMarkerBegin[] = "@@ LAYOUT-"; ...@@ -40,8 +40,8 @@ constexpr char kLayoutMarkerBegin[] = "@@ LAYOUT-";
constexpr char kXfbDeclMarkerBegin[] = "@@ XFB-DECL"; constexpr char kXfbDeclMarkerBegin[] = "@@ XFB-DECL";
constexpr char kXfbOutMarkerBegin[] = "@@ XFB-OUT"; constexpr char kXfbOutMarkerBegin[] = "@@ XFB-OUT";
constexpr char kMarkerEnd[] = " @@"; constexpr char kMarkerEnd[] = " @@";
constexpr char kLayoutParamsBegin = '('; constexpr char kParamsBegin = '(';
constexpr char kLayoutParamsEnd = ')'; constexpr char kParamsEnd = ')';
constexpr char kUniformQualifier[] = "uniform"; constexpr char kUniformQualifier[] = "uniform";
constexpr char kVersionDefine[] = "#version 450 core\n"; constexpr char kVersionDefine[] = "#version 450 core\n";
constexpr char kLineRasterDefine[] = R"(#version 450 core constexpr char kLineRasterDefine[] = R"(#version 450 core
...@@ -101,13 +101,18 @@ class IntermediateShaderSource final : angle::NonCopyable ...@@ -101,13 +101,18 @@ class IntermediateShaderSource final : angle::NonCopyable
// //
// layout(specifier, extra, args) // layout(specifier, extra, args)
// //
// or if specifier is empty, // or if |specifier| is empty:
// //
// layout(extra, args) // layout(extra, args)
// //
void insertLayoutSpecifier(const std::string &name, const std::string &specifier); 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); void insertQualifierSpecifier(const std::string &name, const std::string &specifier);
// Replace @@ XFB-DECL @@ with |decl|. // Replace @@ XFB-DECL @@ with |decl|.
...@@ -116,7 +121,7 @@ class IntermediateShaderSource final : angle::NonCopyable ...@@ -116,7 +121,7 @@ class IntermediateShaderSource final : angle::NonCopyable
// Replace @@ XFB-OUT @@ with |output| code block. // Replace @@ XFB-OUT @@ with |output| code block.
void insertTransformFeedbackOutput(const std::string &&output); 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. // with something to make sure the shader still compiles.
void eraseLayoutAndQualifierSpecifiers(const std::string &name, const std::string &replacement); void eraseLayoutAndQualifierSpecifiers(const std::string &name, const std::string &replacement);
...@@ -128,7 +133,7 @@ class IntermediateShaderSource final : angle::NonCopyable ...@@ -128,7 +133,7 @@ class IntermediateShaderSource final : angle::NonCopyable
{ {
// A piece of shader source code. // A piece of shader source code.
Text, Text,
// Block corresponding to @@ QUALIFIER-abc @@ // Block corresponding to @@ QUALIFIER-abc(other qualifiers) @@
Qualifier, Qualifier,
// Block corresponding to @@ LAYOUT-abc(extra, args) @@ // Block corresponding to @@ LAYOUT-abc(extra, args) @@
Layout, Layout,
...@@ -144,13 +149,13 @@ class IntermediateShaderSource final : angle::NonCopyable ...@@ -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) // |text| contains some shader code if Text, or the id of macro ("abc" in examples above)
// being replaced if Qualifier or Layout. // being replaced if Qualifier or Layout.
std::string text; 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; std::string args;
}; };
void addTextBlock(std::string &&text); void addTextBlock(std::string &&text);
void addLayoutBlock(std::string &&name, std::string &&args); void addLayoutBlock(std::string &&name, std::string &&args);
void addQualifierBlock(std::string &&name); void addQualifierBlock(std::string &&name, std::string &&args);
void addTransformFeedbackDeclarationBlock(); void addTransformFeedbackDeclarationBlock();
void addTransformFeedbackOutputBlock(); void addTransformFeedbackOutputBlock();
...@@ -175,10 +180,10 @@ void IntermediateShaderSource::addLayoutBlock(std::string &&name, std::string && ...@@ -175,10 +180,10 @@ void IntermediateShaderSource::addLayoutBlock(std::string &&name, std::string &&
mTokens.emplace_back(std::move(token)); mTokens.emplace_back(std::move(token));
} }
void IntermediateShaderSource::addQualifierBlock(std::string &&name) void IntermediateShaderSource::addQualifierBlock(std::string &&name, std::string &&args)
{ {
ASSERT(!name.empty()); 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)); mTokens.emplace_back(std::move(token));
} }
...@@ -194,6 +199,21 @@ void IntermediateShaderSource::addTransformFeedbackOutputBlock() ...@@ -194,6 +199,21 @@ void IntermediateShaderSource::addTransformFeedbackOutputBlock()
mTokens.emplace_back(std::move(token)); 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) IntermediateShaderSource::IntermediateShaderSource(const std::string &source)
{ {
size_t cur = 0; size_t cur = 0;
...@@ -216,21 +236,18 @@ IntermediateShaderSource::IntermediateShaderSource(const std::string &source) ...@@ -216,21 +236,18 @@ IntermediateShaderSource::IntermediateShaderSource(const std::string &source)
{ {
cur += ConstStrLen(kQualifierMarkerBegin); cur += ConstStrLen(kQualifierMarkerBegin);
// Get the id of the macro and add a qualifier block. // Get the id and arguments of the macro and add a qualifier block.
std::string name = angle::GetPrefix(source, cur, kMarkerEnd); std::string name, args;
cur += name.length(); cur += ExtractNameAndArgs(source, cur, &name, &args);
addQualifierBlock(std::move(name)); addQualifierBlock(std::move(name), std::move(args));
} }
else if (source.compare(cur, ConstStrLen(kLayoutMarkerBegin), kLayoutMarkerBegin) == 0) else if (source.compare(cur, ConstStrLen(kLayoutMarkerBegin), kLayoutMarkerBegin) == 0)
{ {
cur += ConstStrLen(kLayoutMarkerBegin); cur += ConstStrLen(kLayoutMarkerBegin);
// Get the id and arguments of the macro and add a layout block. // 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, args;
std::string name = angle::GetPrefix(source, cur, kLayoutParamsBegin); cur += ExtractNameAndArgs(source, cur, &name, &args);
cur += name.length() + 1;
std::string args = angle::GetPrefix(source, cur, kLayoutParamsEnd);
cur += args.length() + 1;
addLayoutBlock(std::move(name), std::move(args)); addLayoutBlock(std::move(name), std::move(args));
} }
else if (source.compare(cur, ConstStrLen(kXfbDeclMarkerBegin), kXfbDeclMarkerBegin) == 0) else if (source.compare(cur, ConstStrLen(kXfbDeclMarkerBegin), kXfbDeclMarkerBegin) == 0)
...@@ -283,6 +300,10 @@ void IntermediateShaderSource::insertQualifierSpecifier(const std::string &name, ...@@ -283,6 +300,10 @@ void IntermediateShaderSource::insertQualifierSpecifier(const std::string &name,
{ {
block.type = TokenType::Text; block.type = TokenType::Text;
block.text = specifier; block.text = specifier;
if (!specifier.empty() && !block.args.empty())
{
block.text += " " + block.args;
}
break; break;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment