Commit 31641b8e by Shahbaz Youssefi Committed by Angle LUCI CQ

Declare specialization constants in the AST

A new qualifier (EvqSpecConst) is added so that specialization constants can be declared in tree. This enables TVariable references to specialization constants to be validated, which were in fact invalid as every reference declared a new variable. That is fixed. Bug: angleproject:4889 Change-Id: I1711e41cbc5a1260843d2d004d3568bdae11e963 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2941451Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
parent 82654e5d
...@@ -1030,6 +1030,11 @@ enum TQualifier ...@@ -1030,6 +1030,11 @@ enum TQualifier
EvqTessEvaluationOut, EvqTessEvaluationOut,
EvqTessCoord, EvqTessCoord,
// A specialization constant, which is not valid GLSL ES, but is there to support Vulkan output
// generation. In that case, TLayoutQualifier::location will contain the somewhat equivalent
// constant_id.
EvqSpecConst,
// end of list // end of list
EvqLast EvqLast
}; };
...@@ -1449,6 +1454,7 @@ inline const char *getQualifierString(TQualifier q) ...@@ -1449,6 +1454,7 @@ inline const char *getQualifierString(TQualifier q)
case EvqTessEvaluationIn: return "in"; case EvqTessEvaluationIn: return "in";
case EvqTessEvaluationOut: return "out"; case EvqTessEvaluationOut: return "out";
case EvqTessCoord: return "TessCoord"; case EvqTessCoord: return "TessCoord";
case EvqSpecConst: return "const";
default: UNREACHABLE(); return "unknown qualifier"; default: UNREACHABLE(); return "unknown qualifier";
} }
// clang-format on // clang-format on
......
...@@ -1603,8 +1603,12 @@ void TIntermBinary::promote() ...@@ -1603,8 +1603,12 @@ void TIntermBinary::promote()
TQualifier resultQualifier = EvqConst; TQualifier resultQualifier = EvqConst;
// Binary operations results in temporary variables unless both // Binary operations results in temporary variables unless both
// operands are const. // operands are const. If initializing a specialization constant, make the declarator also
if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) // EvqSpecConst.
const bool isSpecConstInit = mOp == EOpInitialize && mLeft->getQualifier() == EvqSpecConst;
const bool isEitherNonConst =
mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst;
if (!isSpecConstInit && isEitherNonConst)
{ {
resultQualifier = EvqTemporary; resultQualifier = EvqTemporary;
getTypePointer()->setQualifier(EvqTemporary); getTypePointer()->setQualifier(EvqTemporary);
......
...@@ -167,7 +167,7 @@ void TOutputGLSLBase::writeBuiltInFunctionTriplet(Visit visit, ...@@ -167,7 +167,7 @@ void TOutputGLSLBase::writeBuiltInFunctionTriplet(Visit visit,
// Outputs what goes inside layout(), except for location and binding qualifiers, as they are // Outputs what goes inside layout(), except for location and binding qualifiers, as they are
// handled differently between GL GLSL and Vulkan GLSL. // handled differently between GL GLSL and Vulkan GLSL.
std::string TOutputGLSLBase::getCommonLayoutQualifiers(TIntermTyped *variable) std::string TOutputGLSLBase::getCommonLayoutQualifiers(TIntermSymbol *variable)
{ {
std::ostringstream out; std::ostringstream out;
CommaSeparatedListItemPrefixGenerator listItemPrefix; CommaSeparatedListItemPrefixGenerator listItemPrefix;
...@@ -245,7 +245,7 @@ std::string TOutputGLSLBase::getMemoryQualifiers(const TType &type) ...@@ -245,7 +245,7 @@ std::string TOutputGLSLBase::getMemoryQualifiers(const TType &type)
return out.str(); return out.str();
} }
void TOutputGLSLBase::writeLayoutQualifier(TIntermTyped *variable) void TOutputGLSLBase::writeLayoutQualifier(TIntermSymbol *variable)
{ {
const TType &type = variable->getType(); const TType &type = variable->getType();
...@@ -1033,16 +1033,27 @@ bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node) ...@@ -1033,16 +1033,27 @@ bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node)
const TIntermSequence &sequence = *(node->getSequence()); const TIntermSequence &sequence = *(node->getSequence());
TIntermTyped *variable = sequence.front()->getAsTyped(); TIntermTyped *variable = sequence.front()->getAsTyped();
TIntermSymbol *symbolNode = variable->getAsSymbolNode(); TIntermSymbol *symbolNode = variable->getAsSymbolNode();
if (!symbolNode || (symbolNode->getName() != "gl_ClipDistance" && if (symbolNode == nullptr)
symbolNode->getName() != "gl_CullDistance")) {
ASSERT(variable->getAsBinaryNode() &&
variable->getAsBinaryNode()->getOp() == EOpInitialize);
symbolNode = variable->getAsBinaryNode()->getLeft()->getAsSymbolNode();
}
ASSERT(symbolNode);
if (symbolNode->getName() != "gl_ClipDistance" &&
symbolNode->getName() != "gl_CullDistance")
{ {
// gl_Clip/CullDistance re-declaration doesn't need layout. // gl_Clip/CullDistance re-declaration doesn't need layout.
writeLayoutQualifier(variable); writeLayoutQualifier(symbolNode);
} }
writeVariableType(variable->getType(), symbolNode ? &symbolNode->variable() : nullptr,
false); // Note: the TIntermDeclaration type is used for variable declaration instead of the
if (variable->getAsSymbolNode() == nullptr || // TIntermSymbol one. The TIntermDeclaration type includes precision promotions from the
variable->getAsSymbolNode()->variable().symbolType() != SymbolType::Empty) // right hand side that the symbol may be missing. This is an inconsistency in the tree
// that is too ingrained.
writeVariableType(variable->getType(), &symbolNode->variable(), false);
if (symbolNode->variable().symbolType() != SymbolType::Empty)
{ {
out << " "; out << " ";
} }
......
...@@ -41,9 +41,9 @@ class TOutputGLSLBase : public TIntermTraverser ...@@ -41,9 +41,9 @@ class TOutputGLSLBase : public TIntermTraverser
TInfoSinkBase &objSink() { return mObjSink; } TInfoSinkBase &objSink() { return mObjSink; }
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(TIntermSymbol *variable);
std::string getMemoryQualifiers(const TType &type); std::string getMemoryQualifiers(const TType &type);
virtual void writeLayoutQualifier(TIntermTyped *variable); virtual void writeLayoutQualifier(TIntermSymbol *variable);
void writeFieldLayoutQualifier(const TField *field); void writeFieldLayoutQualifier(const TField *field);
void writeInvariantQualifier(const TType &type); void writeInvariantQualifier(const TType &type);
void writePreciseQualifier(const TType &type); void writePreciseQualifier(const TType &type);
......
...@@ -44,9 +44,9 @@ TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink, ...@@ -44,9 +44,9 @@ TOutputVulkanGLSL::TOutputVulkanGLSL(TInfoSinkBase &objSink,
mEnablePrecision(enablePrecision) mEnablePrecision(enablePrecision)
{} {}
void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) void TOutputVulkanGLSL::writeLayoutQualifier(TIntermSymbol *symbol)
{ {
const TType &type = variable->getType(); const TType &type = symbol->getType();
bool needsSetBinding = IsSampler(type.getBasicType()) || bool needsSetBinding = IsSampler(type.getBasicType()) ||
(type.isInterfaceBlock() && (type.getQualifier() == EvqUniform || (type.isInterfaceBlock() && (type.getQualifier() == EvqUniform ||
...@@ -56,9 +56,10 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) ...@@ -56,9 +56,10 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
type.getQualifier() == EvqVertexIn || type.getQualifier() == EvqVertexIn ||
type.getQualifier() == EvqFragmentOut || IsVarying(type.getQualifier()); type.getQualifier() == EvqFragmentOut || IsVarying(type.getQualifier());
bool needsInputAttachmentIndex = IsSubpassInputType(type.getBasicType()); bool needsInputAttachmentIndex = IsSubpassInputType(type.getBasicType());
bool needsSpecConstId = type.getQualifier() == EvqSpecConst;
if (!NeedsToWriteLayoutQualifier(type) && !needsSetBinding && !needsLocation && if (!NeedsToWriteLayoutQualifier(type) && !needsSetBinding && !needsLocation &&
!needsInputAttachmentIndex) !needsInputAttachmentIndex && !needsSpecConstId)
{ {
return; return;
} }
...@@ -68,9 +69,6 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) ...@@ -68,9 +69,6 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
// This isn't super clean, but it gets the job done. // This isn't super clean, but it gets the job done.
// See corresponding code in glslang_wrapper_utils.cpp. // See corresponding code in glslang_wrapper_utils.cpp.
TIntermSymbol *symbol = variable->getAsSymbolNode();
ASSERT(symbol);
const char *blockStorage = nullptr; const char *blockStorage = nullptr;
const char *matrixPacking = nullptr; const char *matrixPacking = nullptr;
...@@ -112,6 +110,12 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) ...@@ -112,6 +110,12 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
separator = kCommaSeparator; separator = kCommaSeparator;
} }
// If it's a specialization constant, add that constant_id qualifier.
if (needsSpecConstId)
{
out << separator << "constant_id=" << layoutQualifier.location;
}
// If the resource declaration requires set & binding layout qualifiers, specify arbitrary // If the resource declaration requires set & binding layout qualifiers, specify arbitrary
// ones. // ones.
if (needsSetBinding) if (needsSetBinding)
...@@ -134,7 +138,7 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable) ...@@ -134,7 +138,7 @@ void TOutputVulkanGLSL::writeLayoutQualifier(TIntermTyped *variable)
// Output the list of qualifiers already known at this stage, i.e. everything other than // Output the list of qualifiers already known at this stage, i.e. everything other than
// `location` and `set`/`binding`. // `location` and `set`/`binding`.
std::string otherQualifiers = getCommonLayoutQualifiers(variable); std::string otherQualifiers = getCommonLayoutQualifiers(symbol);
if (blockStorage) if (blockStorage)
{ {
......
...@@ -46,7 +46,7 @@ class TOutputVulkanGLSL : public TOutputGLSL ...@@ -46,7 +46,7 @@ class TOutputVulkanGLSL : public TOutputGLSL
} }
protected: protected:
void writeLayoutQualifier(TIntermTyped *variable) override; void writeLayoutQualifier(TIntermSymbol *variable) override;
void writeVariableType(const TType &type, void writeVariableType(const TType &type,
const TSymbol *symbol, const TSymbol *symbol,
bool isFunctionArgument) override; bool isFunctionArgument) override;
......
...@@ -1293,7 +1293,8 @@ bool TranslatorVulkan::translateImpl(TInfoSinkBase &sink, ...@@ -1293,7 +1293,8 @@ bool TranslatorVulkan::translateImpl(TInfoSinkBase &sink,
break; break;
} }
specConst->outputLayoutString(sink); specConst->declareSpecConsts(root);
mValidateASTOptions.validateSpecConstReferences = true;
// Gather specialization constant usage bits so that we can feedback to context. // Gather specialization constant usage bits so that we can feedback to context.
mSpecConstUsageBits = specConst->getSpecConstUsageBits(); mSpecConstUsageBits = specConst->getSpecConstUsageBits();
......
...@@ -279,12 +279,11 @@ bool ValidateAST::variableNeedsDeclaration(const TVariable *variable) ...@@ -279,12 +279,11 @@ bool ValidateAST::variableNeedsDeclaration(const TVariable *variable)
return false; return false;
} }
// Additionally, don't expect declaration for Vulkan specialization constants. There is no // Additionally, don't expect declaration for Vulkan specialization constants if not enabled.
// representation for them in the AST. // The declaration of these variables is deferred.
if (variable->symbolType() == SymbolType::AngleInternal && if (variable->getType().getQualifier() == EvqSpecConst)
SpecConst::IsSpecConstName(variable->name()))
{ {
return false; return mOptions.validateSpecConstReferences;
} }
return true; return true;
......
...@@ -25,6 +25,9 @@ struct ValidateASTOptions ...@@ -25,6 +25,9 @@ struct ValidateASTOptions
bool validateSingleParent = true; bool validateSingleParent = true;
// Check that all symbols reference TVariables that have been declared. // Check that all symbols reference TVariables that have been declared.
bool validateVariableReferences = true; bool validateVariableReferences = true;
// Whether validateVariableReferences should also include specialization constants. Their
// declaration is output after their usage is discovered, so this is disabled until then.
bool validateSpecConstReferences = false;
// Check that all EOpCallFunctionInAST have their corresponding function definitions in the AST, // Check that all EOpCallFunctionInAST have their corresponding function definitions in the AST,
// with matching symbol ids. There should also be at least a prototype declaration before the // with matching symbol ids. There should also be at least a prototype declaration before the
// function is called. // function is called.
......
...@@ -231,10 +231,29 @@ TIntermTyped *CreateFloatArrayWithRotationIndex(const Vec2EnumMap &valuesEnumMap ...@@ -231,10 +231,29 @@ TIntermTyped *CreateFloatArrayWithRotationIndex(const Vec2EnumMap &valuesEnumMap
return new TIntermBinary(EOpIndexDirect, array, rotation); return new TIntermBinary(EOpIndexDirect, array, rotation);
} }
const TType *MakeSpecConst(const TType &type, vk::SpecializationConstantId id)
{
// Create a new type with the EvqSpecConst qualifier
TType *specConstType = new TType(type);
specConstType->setQualifier(EvqSpecConst);
// Set the constant_id of the spec const
TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
layoutQualifier.location = static_cast<int>(id);
specConstType->setLayoutQualifier(layoutQualifier);
return specConstType;
}
} // anonymous namespace } // anonymous namespace
SpecConst::SpecConst(TSymbolTable *symbolTable, ShCompileOptions compileOptions, GLenum shaderType) SpecConst::SpecConst(TSymbolTable *symbolTable, ShCompileOptions compileOptions, GLenum shaderType)
: mSymbolTable(symbolTable), mCompileOptions(compileOptions) : mSymbolTable(symbolTable),
mCompileOptions(compileOptions),
mLineRasterEmulationVar(nullptr),
mSurfaceRotationVar(nullptr),
mDrawableWidthVar(nullptr),
mDrawableHeightVar(nullptr)
{ {
if (shaderType == GL_FRAGMENT_SHADER || shaderType == GL_COMPUTE_SHADER) if (shaderType == GL_FRAGMENT_SHADER || shaderType == GL_COMPUTE_SHADER)
{ {
...@@ -251,33 +270,43 @@ SpecConst::SpecConst(TSymbolTable *symbolTable, ShCompileOptions compileOptions, ...@@ -251,33 +270,43 @@ SpecConst::SpecConst(TSymbolTable *symbolTable, ShCompileOptions compileOptions,
SpecConst::~SpecConst() {} SpecConst::~SpecConst() {}
void SpecConst::outputLayoutString(TInfoSinkBase &sink) const void SpecConst::declareSpecConsts(TIntermBlock *root)
{ {
// Add specialization constant declarations. The default value of the specialization // Add specialization constant declarations. The default value of the specialization
// constant is irrelevant, as it will be set when creating the pipeline. // constant is irrelevant, as it will be set when creating the pipeline.
// Only emit specialized const layout string if it has been referenced. // Only emit specialized const declaration if it has been referenced.
if (mUsageBits.test(vk::SpecConstUsage::LineRasterEmulation)) if (mLineRasterEmulationVar != nullptr)
{ {
sink << "layout(constant_id=" TIntermDeclaration *decl = new TIntermDeclaration();
<< static_cast<uint32_t>(vk::SpecializationConstantId::LineRasterEmulation) decl->appendDeclarator(
<< ") const bool " << kLineRasterEmulationSpecConstVarName << " = false;\n\n"; new TIntermBinary(EOpInitialize, getLineRasterEmulation(), CreateBoolNode(false)));
root->insertStatement(0, decl);
} }
if (mUsageBits.test(vk::SpecConstUsage::YFlip) || mUsageBits.test(vk::SpecConstUsage::Rotation)) if (mSurfaceRotationVar != nullptr)
{ {
sink << "layout(constant_id=" TIntermDeclaration *decl = new TIntermDeclaration();
<< static_cast<uint32_t>(vk::SpecializationConstantId::SurfaceRotation) decl->appendDeclarator(
<< ") const uint " << kSurfaceRotationSpecConstVarName << " = 0;\n\n"; new TIntermBinary(EOpInitialize, getFlipRotation(), CreateUIntNode(0)));
root->insertStatement(0, decl);
} }
if (mUsageBits.test(vk::SpecConstUsage::DrawableSize)) if (mDrawableWidthVar != nullptr)
{ {
sink << "layout(constant_id=" TIntermDeclaration *decl = new TIntermDeclaration();
<< static_cast<uint32_t>(vk::SpecializationConstantId::DrawableWidth) decl->appendDeclarator(
<< ") const uint " << kDrawableWidthSpecConstVarName << " = 0;\n\n"; new TIntermBinary(EOpInitialize, getDrawableWidth(), CreateFloatNode(0)));
sink << "layout(constant_id=" root->insertStatement(0, decl);
<< static_cast<uint32_t>(vk::SpecializationConstantId::DrawableHeight) }
<< ") const uint " << kDrawableHeightSpecConstVarName << " = 0;\n\n";
if (mDrawableHeightVar != nullptr)
{
TIntermDeclaration *decl = new TIntermDeclaration();
decl->appendDeclarator(
new TIntermBinary(EOpInitialize, getDrawableHeight(), CreateFloatNode(0)));
root->insertStatement(1, decl);
} }
} }
...@@ -287,19 +316,29 @@ TIntermSymbol *SpecConst::getLineRasterEmulation() ...@@ -287,19 +316,29 @@ TIntermSymbol *SpecConst::getLineRasterEmulation()
{ {
return nullptr; return nullptr;
} }
TVariable *specConstVar = if (mLineRasterEmulationVar == nullptr)
new TVariable(mSymbolTable, kLineRasterEmulationSpecConstVarName, {
StaticType::GetBasic<EbtBool>(), SymbolType::AngleInternal); const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtBool>(),
mUsageBits.set(vk::SpecConstUsage::LineRasterEmulation); vk::SpecializationConstantId::LineRasterEmulation);
return new TIntermSymbol(specConstVar);
mLineRasterEmulationVar = new TVariable(mSymbolTable, kLineRasterEmulationSpecConstVarName,
type, SymbolType::AngleInternal);
mUsageBits.set(vk::SpecConstUsage::LineRasterEmulation);
}
return new TIntermSymbol(mLineRasterEmulationVar);
} }
TIntermSymbol *SpecConst::getFlipRotation() TIntermSymbol *SpecConst::getFlipRotation()
{ {
TVariable *specConstVar = if (mSurfaceRotationVar == nullptr)
new TVariable(mSymbolTable, kSurfaceRotationSpecConstVarName, {
StaticType::GetBasic<EbtUInt>(), SymbolType::AngleInternal); const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtUInt>(),
return new TIntermSymbol(specConstVar); vk::SpecializationConstantId::SurfaceRotation);
mSurfaceRotationVar = new TVariable(mSymbolTable, kSurfaceRotationSpecConstVarName, type,
SymbolType::AngleInternal);
}
return new TIntermSymbol(mSurfaceRotationVar);
} }
TIntermTyped *SpecConst::getMultiplierXForDFdx() TIntermTyped *SpecConst::getMultiplierXForDFdx()
...@@ -448,20 +487,28 @@ TIntermTyped *SpecConst::getFragRotationMultiplyFlipXY() ...@@ -448,20 +487,28 @@ TIntermTyped *SpecConst::getFragRotationMultiplyFlipXY()
TIntermSymbol *SpecConst::getDrawableWidth() TIntermSymbol *SpecConst::getDrawableWidth()
{ {
TVariable *widthSpecConstVar = if (mDrawableWidthVar == nullptr)
new TVariable(mSymbolTable, kDrawableWidthSpecConstVarName, {
StaticType::GetBasic<EbtFloat>(), SymbolType::AngleInternal); const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat>(),
TIntermSymbol *drawableWidth = new TIntermSymbol(widthSpecConstVar); vk::SpecializationConstantId::DrawableWidth);
return drawableWidth;
mDrawableWidthVar = new TVariable(mSymbolTable, kDrawableWidthSpecConstVarName, type,
SymbolType::AngleInternal);
}
return new TIntermSymbol(mDrawableWidthVar);
} }
TIntermSymbol *SpecConst::getDrawableHeight() TIntermSymbol *SpecConst::getDrawableHeight()
{ {
TVariable *heightSpecConstVar = if (mDrawableHeightVar == nullptr)
new TVariable(mSymbolTable, kDrawableHeightSpecConstVarName, {
StaticType::GetBasic<EbtFloat>(), SymbolType::AngleInternal); const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtFloat>(),
TIntermSymbol *drawableHeight = new TIntermSymbol(heightSpecConstVar); vk::SpecializationConstantId::DrawableHeight);
return drawableHeight;
mDrawableHeightVar = new TVariable(mSymbolTable, kDrawableHeightSpecConstVarName, type,
SymbolType::AngleInternal);
}
return new TIntermSymbol(mDrawableHeightVar);
} }
TIntermBinary *SpecConst::getHalfRenderArea() TIntermBinary *SpecConst::getHalfRenderArea()
...@@ -491,11 +538,4 @@ TIntermBinary *SpecConst::getHalfRenderArea() ...@@ -491,11 +538,4 @@ TIntermBinary *SpecConst::getHalfRenderArea()
return rotatedHalfRenderArea; return rotatedHalfRenderArea;
} }
bool SpecConst::IsSpecConstName(const ImmutableString &name)
{
return name == kLineRasterEmulationSpecConstVarName ||
name == kSurfaceRotationSpecConstVarName || name == kDrawableWidthSpecConstVarName ||
name == kDrawableHeightSpecConstVarName;
}
} // namespace sh } // namespace sh
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "compiler/translator/Compiler.h" #include "compiler/translator/Compiler.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
class TIntermBlock;
class TIntermTyped; class TIntermTyped;
class TIntermSymbol; class TIntermSymbol;
class TVariable; class TVariable;
...@@ -44,11 +45,9 @@ class SpecConst ...@@ -44,11 +45,9 @@ class SpecConst
// Half render area // Half render area
TIntermBinary *getHalfRenderArea(); TIntermBinary *getHalfRenderArea();
void outputLayoutString(TInfoSinkBase &sink) const; void declareSpecConsts(TIntermBlock *root);
SpecConstUsageBits getSpecConstUsageBits() const { return mUsageBits; } SpecConstUsageBits getSpecConstUsageBits() const { return mUsageBits; }
static bool IsSpecConstName(const ImmutableString &name);
private: private:
TIntermSymbol *getFlipRotation(); TIntermSymbol *getFlipRotation();
TIntermTyped *getNegFlipY(); TIntermTyped *getNegFlipY();
...@@ -60,6 +59,11 @@ class SpecConst ...@@ -60,6 +59,11 @@ class SpecConst
TSymbolTable *mSymbolTable; TSymbolTable *mSymbolTable;
ShCompileOptions mCompileOptions; ShCompileOptions mCompileOptions;
TVariable *mLineRasterEmulationVar;
TVariable *mSurfaceRotationVar;
TVariable *mDrawableWidthVar;
TVariable *mDrawableHeightVar;
// Bit is set if YFlip or Rotation has been used // Bit is set if YFlip or Rotation has been used
SpecConstUsageBits mUsageBits; SpecConstUsageBits mUsageBits;
}; };
......
...@@ -7777,10 +7777,10 @@ void ShaderProgramHelper::setSpecializationConstant(sh::vk::SpecializationConsta ...@@ -7777,10 +7777,10 @@ void ShaderProgramHelper::setSpecializationConstant(sh::vk::SpecializationConsta
mSpecializationConstants.surfaceRotation = value; mSpecializationConstants.surfaceRotation = value;
break; break;
case sh::vk::SpecializationConstantId::DrawableWidth: case sh::vk::SpecializationConstantId::DrawableWidth:
mSpecializationConstants.drawableWidth = value; mSpecializationConstants.drawableWidth = static_cast<float>(value);
break; break;
case sh::vk::SpecializationConstantId::DrawableHeight: case sh::vk::SpecializationConstantId::DrawableHeight:
mSpecializationConstants.drawableHeight = value; mSpecializationConstants.drawableHeight = static_cast<float>(value);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
......
...@@ -727,8 +727,8 @@ struct SpecializationConstants final ...@@ -727,8 +727,8 @@ struct SpecializationConstants final
{ {
VkBool32 lineRasterEmulation; VkBool32 lineRasterEmulation;
uint32_t surfaceRotation; uint32_t surfaceRotation;
uint32_t drawableWidth; float drawableWidth;
uint32_t drawableHeight; float drawableHeight;
}; };
ANGLE_DISABLE_STRUCT_PADDING_WARNINGS ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
......
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