1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // SpecializationConst.cpp: Add code to generate AST node for various specialization constants.
7 //
8
9 #include "compiler/translator/tree_util/SpecializationConstant.h"
10 #include "common/PackedEnums.h"
11 #include "common/angleutils.h"
12 #include "compiler/translator/StaticType.h"
13 #include "compiler/translator/SymbolTable.h"
14 #include "compiler/translator/tree_util/IntermNode_util.h"
15
16 namespace sh
17 {
18
19 namespace
20 {
21 // Specialization constant names
22 constexpr ImmutableString kSurfaceRotationSpecConstVarName =
23 ImmutableString("ANGLESurfaceRotation");
24 constexpr ImmutableString kDitherSpecConstVarName = ImmutableString("ANGLEDither");
25
MakeSpecConst(const TType & type,vk::SpecializationConstantId id)26 const TType *MakeSpecConst(const TType &type, vk::SpecializationConstantId id)
27 {
28 // Create a new type with the EvqSpecConst qualifier
29 TType *specConstType = new TType(type);
30 specConstType->setQualifier(EvqSpecConst);
31
32 // Set the constant_id of the spec const
33 TLayoutQualifier layoutQualifier = TLayoutQualifier::Create();
34 layoutQualifier.location = static_cast<int>(id);
35 specConstType->setLayoutQualifier(layoutQualifier);
36
37 return specConstType;
38 }
39 } // anonymous namespace
40
SpecConst(TSymbolTable * symbolTable,const ShCompileOptions & compileOptions,GLenum shaderType)41 SpecConst::SpecConst(TSymbolTable *symbolTable,
42 const ShCompileOptions &compileOptions,
43 GLenum shaderType)
44 : mSymbolTable(symbolTable),
45 mCompileOptions(compileOptions),
46 mSurfaceRotationVar(nullptr),
47 mDitherVar(nullptr)
48 {
49 if (shaderType == GL_FRAGMENT_SHADER || shaderType == GL_COMPUTE_SHADER)
50 {
51 return;
52 }
53
54 // Mark SpecConstUsage::Rotation unconditionally. gl_Position is always rotated.
55 if (mCompileOptions.useSpecializationConstant)
56 {
57 mUsageBits.set(vk::SpecConstUsage::Rotation);
58 }
59 }
60
~SpecConst()61 SpecConst::~SpecConst() {}
62
declareSpecConsts(TIntermBlock * root)63 void SpecConst::declareSpecConsts(TIntermBlock *root)
64 {
65 // Add specialization constant declarations. The default value of the specialization
66 // constant is irrelevant, as it will be set when creating the pipeline.
67 // Only emit specialized const declaration if it has been referenced.
68 if (mSurfaceRotationVar != nullptr)
69 {
70 TIntermDeclaration *decl = new TIntermDeclaration();
71 decl->appendDeclarator(
72 new TIntermBinary(EOpInitialize, getRotation(), CreateBoolNode(false)));
73
74 root->insertStatement(0, decl);
75 }
76
77 if (mDitherVar != nullptr)
78 {
79 TIntermDeclaration *decl = new TIntermDeclaration();
80 decl->appendDeclarator(new TIntermBinary(EOpInitialize, getDither(), CreateUIntNode(0)));
81
82 root->insertStatement(0, decl);
83 }
84 }
85
getRotation()86 TIntermSymbol *SpecConst::getRotation()
87 {
88 if (mSurfaceRotationVar == nullptr)
89 {
90 const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
91 vk::SpecializationConstantId::SurfaceRotation);
92
93 mSurfaceRotationVar = new TVariable(mSymbolTable, kSurfaceRotationSpecConstVarName, type,
94 SymbolType::AngleInternal);
95 }
96 return new TIntermSymbol(mSurfaceRotationVar);
97 }
98
getSwapXY()99 TIntermTyped *SpecConst::getSwapXY()
100 {
101 if (!mCompileOptions.useSpecializationConstant)
102 {
103 return nullptr;
104 }
105 mUsageBits.set(vk::SpecConstUsage::Rotation);
106 return getRotation();
107 }
108
getDither()109 TIntermTyped *SpecConst::getDither()
110 {
111 if (mDitherVar == nullptr)
112 {
113 const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtUInt, EbpHigh>(),
114 vk::SpecializationConstantId::Dither);
115
116 mDitherVar =
117 new TVariable(mSymbolTable, kDitherSpecConstVarName, type, SymbolType::AngleInternal);
118 mUsageBits.set(vk::SpecConstUsage::Dither);
119 }
120 return new TIntermSymbol(mDitherVar);
121 }
122 } // namespace sh
123