Line data Source code
1 : //
2 : // Copyright (c) 2002-2013 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 :
7 : #include "compiler/translator/TranslatorHLSL.h"
8 :
9 : #include "compiler/translator/AddDefaultReturnStatements.h"
10 : #include "compiler/translator/ArrayReturnValueToOutParameter.h"
11 : #include "compiler/translator/BreakVariableAliasingInInnerLoops.h"
12 : #include "compiler/translator/EmulatePrecision.h"
13 : #include "compiler/translator/ExpandIntegerPowExpressions.h"
14 : #include "compiler/translator/IntermNodePatternMatcher.h"
15 : #include "compiler/translator/OutputHLSL.h"
16 : #include "compiler/translator/RemoveDynamicIndexing.h"
17 : #include "compiler/translator/RewriteElseBlocks.h"
18 : #include "compiler/translator/RewriteTexelFetchOffset.h"
19 : #include "compiler/translator/RewriteUnaryMinusOperatorInt.h"
20 : #include "compiler/translator/SeparateArrayInitialization.h"
21 : #include "compiler/translator/SeparateDeclarations.h"
22 : #include "compiler/translator/SeparateExpressionsReturningArrays.h"
23 : #include "compiler/translator/SimplifyLoopConditions.h"
24 : #include "compiler/translator/SplitSequenceOperator.h"
25 : #include "compiler/translator/UnfoldShortCircuitToIf.h"
26 :
27 : namespace sh
28 : {
29 :
30 0 : TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
31 0 : : TCompiler(type, spec, output)
32 : {
33 0 : }
34 :
35 0 : void TranslatorHLSL::translate(TIntermNode *root, ShCompileOptions compileOptions)
36 : {
37 0 : const ShBuiltInResources &resources = getResources();
38 0 : int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
39 :
40 0 : sh::AddDefaultReturnStatements(root);
41 :
42 : // Note that SimplifyLoopConditions needs to be run before any other AST transformations that
43 : // may need to generate new statements from loop conditions or loop expressions.
44 0 : SimplifyLoopConditions(root,
45 : IntermNodePatternMatcher::kExpressionReturningArray |
46 : IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
47 : IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue |
48 : IntermNodePatternMatcher::kMultiDeclaration,
49 0 : getTemporaryIndex(), getSymbolTable(), getShaderVersion());
50 :
51 : // Note that separate declarations need to be run before other AST transformations that
52 : // generate new statements from expressions.
53 0 : SeparateDeclarations(root);
54 :
55 0 : SplitSequenceOperator(root,
56 : IntermNodePatternMatcher::kExpressionReturningArray |
57 : IntermNodePatternMatcher::kUnfoldedShortCircuitExpression |
58 : IntermNodePatternMatcher::kDynamicIndexingOfVectorOrMatrixInLValue,
59 0 : getTemporaryIndex(), getSymbolTable(), getShaderVersion());
60 :
61 : // Note that SeparateDeclarations needs to be run before UnfoldShortCircuitToIf.
62 0 : UnfoldShortCircuitToIf(root, getTemporaryIndex());
63 :
64 0 : SeparateExpressionsReturningArrays(root, getTemporaryIndex());
65 :
66 : // Note that SeparateDeclarations needs to be run before SeparateArrayInitialization.
67 0 : SeparateArrayInitialization(root);
68 :
69 : // HLSL doesn't support arrays as return values, we'll need to make functions that have an array
70 : // as a return value to use an out parameter to transfer the array data instead.
71 0 : ArrayReturnValueToOutParameter(root, getTemporaryIndex());
72 :
73 0 : if (!shouldRunLoopAndIndexingValidation(compileOptions))
74 : {
75 : // HLSL doesn't support dynamic indexing of vectors and matrices.
76 0 : RemoveDynamicIndexing(root, getTemporaryIndex(), getSymbolTable(), getShaderVersion());
77 : }
78 :
79 : // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
80 : // use a vertex attribute as a condition, and some related computation in the else block.
81 0 : if (getOutputType() == SH_HLSL_3_0_OUTPUT && getShaderType() == GL_VERTEX_SHADER)
82 : {
83 0 : sh::RewriteElseBlocks(root, getTemporaryIndex());
84 : }
85 :
86 : // Work around an HLSL compiler frontend aliasing optimization bug.
87 : // TODO(cwallez) The date is 2016-08-25, Microsoft said the bug would be fixed
88 : // in the next release of d3dcompiler.dll, it would be nice to detect the DLL
89 : // version and only apply the workaround if it is too old.
90 0 : sh::BreakVariableAliasingInInnerLoops(root);
91 :
92 : bool precisionEmulation =
93 0 : getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
94 :
95 0 : if (precisionEmulation)
96 : {
97 0 : EmulatePrecision emulatePrecision(getSymbolTable(), getShaderVersion());
98 0 : root->traverse(&emulatePrecision);
99 0 : emulatePrecision.updateTree();
100 0 : emulatePrecision.writeEmulationHelpers(getInfoSink().obj, getShaderVersion(),
101 0 : getOutputType());
102 : }
103 :
104 0 : if ((compileOptions & SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS) != 0)
105 : {
106 0 : sh::ExpandIntegerPowExpressions(root, getTemporaryIndex());
107 : }
108 :
109 0 : if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
110 : {
111 0 : sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion());
112 : }
113 :
114 0 : if (((compileOptions & SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR) != 0) &&
115 0 : getShaderType() == GL_VERTEX_SHADER)
116 : {
117 0 : sh::RewriteUnaryMinusOperatorInt(root);
118 : }
119 :
120 : sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
121 0 : getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions);
122 :
123 0 : outputHLSL.output(root, getInfoSink().obj);
124 :
125 0 : mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap();
126 0 : mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
127 0 : }
128 :
129 0 : bool TranslatorHLSL::shouldFlattenPragmaStdglInvariantAll()
130 : {
131 : // Not necessary when translating to HLSL.
132 0 : return false;
133 : }
134 :
135 0 : bool TranslatorHLSL::hasInterfaceBlock(const std::string &interfaceBlockName) const
136 : {
137 0 : return (mInterfaceBlockRegisterMap.count(interfaceBlockName) > 0);
138 : }
139 :
140 0 : unsigned int TranslatorHLSL::getInterfaceBlockRegister(const std::string &interfaceBlockName) const
141 : {
142 0 : ASSERT(hasInterfaceBlock(interfaceBlockName));
143 0 : return mInterfaceBlockRegisterMap.find(interfaceBlockName)->second;
144 : }
145 :
146 0 : const std::map<std::string, unsigned int> *TranslatorHLSL::getUniformRegisterMap() const
147 : {
148 0 : return &mUniformRegisterMap;
149 : }
150 :
151 : } // namespace sh
|