blob: 6a7254802c92b56da48ed712013c81cba613c369 [file] [log] [blame]
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// SpecializationConst.cpp: Add code to generate AST node for various specialization constants.
//
#include "compiler/translator/tree_util/SpecializationConstant.h"
#include "common/PackedEnums.h"
#include "common/angleutils.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
namespace sh
{
namespace
{
// Specialization constant names
constexpr ImmutableString kSurfaceRotationSpecConstVarName =
ImmutableString("ANGLESurfaceRotation");
constexpr ImmutableString kDitherSpecConstVarName = ImmutableString("ANGLEDither");
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
SpecConst::SpecConst(TSymbolTable *symbolTable,
const ShCompileOptions &compileOptions,
GLenum shaderType)
: mSymbolTable(symbolTable),
mCompileOptions(compileOptions),
mSurfaceRotationVar(nullptr),
mDitherVar(nullptr)
{
if (shaderType == GL_FRAGMENT_SHADER || shaderType == GL_COMPUTE_SHADER)
{
return;
}
// Mark SpecConstUsage::Rotation unconditionally. gl_Position is always rotated.
if (mCompileOptions.useSpecializationConstant)
{
mUsageBits.set(vk::SpecConstUsage::Rotation);
}
}
SpecConst::~SpecConst() {}
void SpecConst::declareSpecConsts(TIntermBlock *root)
{
// Add specialization constant declarations. The default value of the specialization
// constant is irrelevant, as it will be set when creating the pipeline.
// Only emit specialized const declaration if it has been referenced.
if (mSurfaceRotationVar != nullptr)
{
TIntermDeclaration *decl = new TIntermDeclaration();
decl->appendDeclarator(
new TIntermBinary(EOpInitialize, getRotation(), CreateBoolNode(false)));
root->insertStatement(0, decl);
}
if (mDitherVar != nullptr)
{
TIntermDeclaration *decl = new TIntermDeclaration();
decl->appendDeclarator(new TIntermBinary(EOpInitialize, getDither(), CreateUIntNode(0)));
root->insertStatement(0, decl);
}
}
TIntermSymbol *SpecConst::getRotation()
{
if (mSurfaceRotationVar == nullptr)
{
const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtBool, EbpUndefined>(),
vk::SpecializationConstantId::SurfaceRotation);
mSurfaceRotationVar = new TVariable(mSymbolTable, kSurfaceRotationSpecConstVarName, type,
SymbolType::AngleInternal);
}
return new TIntermSymbol(mSurfaceRotationVar);
}
TIntermTyped *SpecConst::getSwapXY()
{
if (!mCompileOptions.useSpecializationConstant)
{
return nullptr;
}
mUsageBits.set(vk::SpecConstUsage::Rotation);
return getRotation();
}
TIntermTyped *SpecConst::getDither()
{
if (mDitherVar == nullptr)
{
const TType *type = MakeSpecConst(*StaticType::GetBasic<EbtUInt, EbpHigh>(),
vk::SpecializationConstantId::Dither);
mDitherVar =
new TVariable(mSymbolTable, kDitherSpecConstVarName, type, SymbolType::AngleInternal);
mUsageBits.set(vk::SpecConstUsage::Dither);
}
return new TIntermSymbol(mDitherVar);
}
} // namespace sh