blob: b1b845acf3a79ac218373efd2b4051c12526f342 [file] [log] [blame]
//
// Copyright 2002 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.
//
#ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_
#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_
#include <list>
#include <map>
#include <stack>
#include "angle_gl.h"
#include "compiler/translator/ASTMetadataHLSL.h"
#include "compiler/translator/Compiler.h"
#include "compiler/translator/FlagStd140Structs.h"
#include "compiler/translator/ImmutableString.h"
#include "compiler/translator/ShaderStorageBlockOutputHLSL.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
class BuiltInFunctionEmulator;
namespace sh
{
class AtomicCounterFunctionHLSL;
class ImageFunctionHLSL;
class ResourcesHLSL;
class StructureHLSL;
class TextureFunctionHLSL;
class TSymbolTable;
class TVariable;
class UnfoldShortCircuit;
using ReferencedVariables = std::map<int, const TVariable *>;
class OutputHLSL : public TIntermTraverser
{
public:
OutputHLSL(sh::GLenum shaderType,
ShShaderSpec shaderSpec,
int shaderVersion,
const TExtensionBehavior &extensionBehavior,
const char *sourcePath,
ShShaderOutput outputType,
int numRenderTargets,
int maxDualSourceDrawBuffers,
const std::vector<ShaderVariable> &uniforms,
ShCompileOptions compileOptions,
sh::WorkGroupSize workGroupSize,
TSymbolTable *symbolTable,
PerformanceDiagnostics *perfDiagnostics,
const std::vector<InterfaceBlock> &shaderStorageBlocks);
~OutputHLSL() override;
void output(TIntermNode *treeRoot, TInfoSinkBase &objSink);
const std::map<std::string, unsigned int> &getShaderStorageBlockRegisterMap() const;
const std::map<std::string, unsigned int> &getUniformBlockRegisterMap() const;
const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
unsigned int getReadonlyImage2DRegisterIndex() const;
unsigned int getImage2DRegisterIndex() const;
const std::set<std::string> &getUsedImage2DFunctionNames() const;
TInfoSinkBase &getInfoSink()
{
ASSERT(!mInfoSinkStack.empty());
return *mInfoSinkStack.top();
}
protected:
friend class ShaderStorageBlockOutputHLSL;
TString zeroInitializer(const TType &type) const;
void writeReferencedAttributes(TInfoSinkBase &out) const;
void writeReferencedVaryings(TInfoSinkBase &out) const;
void header(TInfoSinkBase &out,
const std::vector<MappedStruct> &std140Structs,
const BuiltInFunctionEmulator *builtInFunctionEmulator) const;
void writeFloat(TInfoSinkBase &out, float f);
void writeSingleConstant(TInfoSinkBase &out, const TConstantUnion *const constUnion);
const TConstantUnion *writeConstantUnionArray(TInfoSinkBase &out,
const TConstantUnion *const constUnion,
const size_t size);
// Visit AST nodes and output their code to the body stream
void visitSymbol(TIntermSymbol *) override;
void visitConstantUnion(TIntermConstantUnion *) override;
bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
bool visitBinary(Visit visit, TIntermBinary *) override;
bool visitUnary(Visit visit, TIntermUnary *) override;
bool visitTernary(Visit visit, TIntermTernary *) override;
bool visitIfElse(Visit visit, TIntermIfElse *) override;
bool visitSwitch(Visit visit, TIntermSwitch *) override;
bool visitCase(Visit visit, TIntermCase *) override;
void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *) override;
bool visitBlock(Visit visit, TIntermBlock *node) override;
bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
bool visitLoop(Visit visit, TIntermLoop *) override;
bool visitBranch(Visit visit, TIntermBranch *) override;
bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node);
// Emit one of three strings depending on traverse phase. Called with literal strings so using
// const char* instead of TString.
void outputTriplet(TInfoSinkBase &out,
Visit visit,
const char *preString,
const char *inString,
const char *postString);
void outputLineDirective(TInfoSinkBase &out, int line);
void writeParameter(const TVariable *param, TInfoSinkBase &out);
void outputConstructor(TInfoSinkBase &out, Visit visit, TIntermAggregate *node);
const TConstantUnion *writeConstantUnion(TInfoSinkBase &out,
const TType &type,
const TConstantUnion *constUnion);
void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out);
void outputAssign(Visit visit, const TType &type, TInfoSinkBase &out);
void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op);
// Returns true if it found a 'same symbol' initializer (initializer that references the
// variable it's initting)
bool writeSameSymbolInitializer(TInfoSinkBase &out,
TIntermSymbol *symbolNode,
TIntermTyped *expression);
// Returns true if variable initializer could be written using literal {} notation.
bool writeConstantInitialization(TInfoSinkBase &out,
TIntermSymbol *symbolNode,
TIntermTyped *expression);
void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node);
// Returns the function name
TString addStructEqualityFunction(const TStructure &structure);
TString addArrayEqualityFunction(const TType &type);
TString addArrayAssignmentFunction(const TType &type);
TString addArrayConstructIntoFunction(const TType &type);
// Ensures if the type is a struct, the struct is defined
void ensureStructDefined(const TType &type);
bool shaderNeedsGenerateOutput() const;
const char *generateOutputCall() const;
sh::GLenum mShaderType;
ShShaderSpec mShaderSpec;
int mShaderVersion;
const TExtensionBehavior &mExtensionBehavior;
const char *mSourcePath;
const ShShaderOutput mOutputType;
ShCompileOptions mCompileOptions;
bool mInsideFunction;
bool mInsideMain;
// Output streams
TInfoSinkBase mHeader;
TInfoSinkBase mBody;
TInfoSinkBase mFooter;
// A stack is useful when we want to traverse in the header, or in helper functions, but not
// always write to the body. Instead use an InfoSink stack to keep our current state intact.
// TODO (jmadill): Just passing an InfoSink in function parameters would be simpler.
std::stack<TInfoSinkBase *> mInfoSinkStack;
ReferencedVariables mReferencedUniforms;
// Indexed by block id, not instance id.
ReferencedInterfaceBlocks mReferencedUniformBlocks;
ReferencedVariables mReferencedAttributes;
ReferencedVariables mReferencedVaryings;
ReferencedVariables mReferencedOutputVariables;
StructureHLSL *mStructureHLSL;
ResourcesHLSL *mResourcesHLSL;
TextureFunctionHLSL *mTextureFunctionHLSL;
ImageFunctionHLSL *mImageFunctionHLSL;
AtomicCounterFunctionHLSL *mAtomicCounterFunctionHLSL;
// Parameters determining what goes in the header output
bool mUsesFragColor;
bool mUsesFragData;
bool mUsesDepthRange;
bool mUsesFragCoord;
bool mUsesPointCoord;
bool mUsesFrontFacing;
bool mUsesHelperInvocation;
bool mUsesPointSize;
bool mUsesInstanceID;
bool mHasMultiviewExtensionEnabled;
bool mUsesViewID;
bool mUsesVertexID;
bool mUsesFragDepth;
bool mUsesNumWorkGroups;
bool mUsesWorkGroupID;
bool mUsesLocalInvocationID;
bool mUsesGlobalInvocationID;
bool mUsesLocalInvocationIndex;
bool mUsesXor;
bool mUsesDiscardRewriting;
bool mUsesNestedBreak;
bool mRequiresIEEEStrictCompiling;
mutable bool mUseZeroArray;
bool mUsesSecondaryColor;
int mNumRenderTargets;
int mMaxDualSourceDrawBuffers;
int mUniqueIndex; // For creating unique names
CallDAG mCallDag;
MetadataList mASTMetadataList;
ASTMetadataHLSL *mCurrentFunctionMetadata;
bool mOutputLod0Function;
bool mInsideDiscontinuousLoop;
int mNestedLoopDepth;
TIntermSymbol *mExcessiveLoopIndex;
TString structInitializerString(int indent, const TType &type, const TString &name) const;
struct HelperFunction
{
TString functionName;
TString functionDefinition;
virtual ~HelperFunction() {}
};
// A list of all equality comparison functions. It's important to preserve the order at
// which we add the functions, since nested structures call each other recursively, and
// structure equality functions may need to call array equality functions and vice versa.
// The ownership of the pointers is maintained by the type-specific arrays.
std::vector<HelperFunction *> mEqualityFunctions;
struct StructEqualityFunction : public HelperFunction
{
const TStructure *structure;
};
std::vector<StructEqualityFunction *> mStructEqualityFunctions;
struct ArrayHelperFunction : public HelperFunction
{
TType type;
};
std::vector<ArrayHelperFunction *> mArrayEqualityFunctions;
std::vector<ArrayHelperFunction> mArrayAssignmentFunctions;
// The construct-into functions are functions that fill an N-element array passed as an out
// parameter with the other N parameters of the function. This is used to work around that
// arrays can't be return values in HLSL.
std::vector<ArrayHelperFunction> mArrayConstructIntoFunctions;
sh::WorkGroupSize mWorkGroupSize;
PerformanceDiagnostics *mPerfDiagnostics;
private:
TString generateStructMapping(const std::vector<MappedStruct> &std140Structs) const;
ImmutableString samplerNamePrefixFromStruct(TIntermTyped *node);
bool ancestorEvaluatesToSamplerInStruct();
// We need to do struct mapping when pass the struct to a function or copy the struct via
// assignment.
bool needStructMapping(TIntermTyped *node);
ShaderStorageBlockOutputHLSL *mSSBOOutputHLSL;
bool mNeedStructMapping;
};
} // namespace sh
#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_