1 //
2 // Copyright (c) 2014 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 // ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
8
9 #include "libANGLE/renderer/d3d/ShaderD3D.h"
10
11 #include "common/utilities.h"
12 #include "libANGLE/Caps.h"
13 #include "libANGLE/Compiler.h"
14 #include "libANGLE/Shader.h"
15 #include "libANGLE/features.h"
16 #include "libANGLE/renderer/d3d/ProgramD3D.h"
17 #include "libANGLE/renderer/d3d/RendererD3D.h"
18
19 // Definitions local to the translation unit
20 namespace
21 {
22
GetShaderTypeString(GLenum type)23 const char *GetShaderTypeString(GLenum type)
24 {
25 switch (type)
26 {
27 case GL_VERTEX_SHADER:
28 return "VERTEX";
29
30 case GL_FRAGMENT_SHADER:
31 return "FRAGMENT";
32
33 case GL_COMPUTE_SHADER:
34 return "COMPUTE";
35
36 default:
37 UNREACHABLE();
38 return "";
39 }
40 }
41
42 } // anonymous namespace
43
44 namespace rx
45 {
46
ShaderD3D(const gl::ShaderState & data,const angle::WorkaroundsD3D & workarounds,const gl::Extensions & extensions)47 ShaderD3D::ShaderD3D(const gl::ShaderState &data,
48 const angle::WorkaroundsD3D &workarounds,
49 const gl::Extensions &extensions)
50 : ShaderImpl(data), mAdditionalOptions(0)
51 {
52 uncompile();
53
54 if (workarounds.expandIntegerPowExpressions)
55 {
56 mAdditionalOptions |= SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS;
57 }
58
59 if (workarounds.getDimensionsIgnoresBaseLevel)
60 {
61 mAdditionalOptions |= SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL;
62 }
63
64 if (workarounds.preAddTexelFetchOffsets)
65 {
66 mAdditionalOptions |= SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH;
67 }
68 if (workarounds.rewriteUnaryMinusOperator)
69 {
70 mAdditionalOptions |= SH_REWRITE_INTEGER_UNARY_MINUS_OPERATOR;
71 }
72 if (workarounds.emulateIsnanFloat)
73 {
74 mAdditionalOptions |= SH_EMULATE_ISNAN_FLOAT_FUNCTION;
75 }
76 if (extensions.multiview)
77 {
78 mAdditionalOptions |= SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW;
79 }
80 }
81
~ShaderD3D()82 ShaderD3D::~ShaderD3D()
83 {
84 }
85
getDebugInfo() const86 std::string ShaderD3D::getDebugInfo() const
87 {
88 if (mDebugInfo.empty())
89 {
90 return "";
91 }
92
93 return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mData.getShaderType()) +
94 " SHADER END\n";
95 }
96
97 // initialize/clean up previous state
uncompile()98 void ShaderD3D::uncompile()
99 {
100 // set by compileToHLSL
101 mCompilerOutputType = SH_ESSL_OUTPUT;
102
103 mUsesMultipleRenderTargets = false;
104 mUsesFragColor = false;
105 mUsesFragData = false;
106 mUsesFragCoord = false;
107 mUsesFrontFacing = false;
108 mUsesPointSize = false;
109 mUsesPointCoord = false;
110 mUsesDepthRange = false;
111 mUsesFragDepth = false;
112 mHasANGLEMultiviewEnabled = false;
113 mUsesViewID = false;
114 mUsesDiscardRewriting = false;
115 mUsesNestedBreak = false;
116 mRequiresIEEEStrictCompiling = false;
117
118 mDebugInfo.clear();
119 }
120
generateWorkarounds(angle::CompilerWorkaroundsD3D * workarounds) const121 void ShaderD3D::generateWorkarounds(angle::CompilerWorkaroundsD3D *workarounds) const
122 {
123 if (mUsesDiscardRewriting)
124 {
125 // ANGLE issue 486:
126 // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
127 workarounds->skipOptimization = true;
128 }
129 else if (mUsesNestedBreak)
130 {
131 // ANGLE issue 603:
132 // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
133 // We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
134 workarounds->useMaxOptimization = true;
135 }
136
137 if (mRequiresIEEEStrictCompiling)
138 {
139 // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work.
140 workarounds->enableIEEEStrictness = true;
141 }
142 }
143
getUniformRegister(const std::string & uniformName) const144 unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const
145 {
146 ASSERT(mUniformRegisterMap.count(uniformName) > 0);
147 return mUniformRegisterMap.find(uniformName)->second;
148 }
149
getUniformBlockRegister(const std::string & blockName) const150 unsigned int ShaderD3D::getUniformBlockRegister(const std::string &blockName) const
151 {
152 ASSERT(mUniformBlockRegisterMap.count(blockName) > 0);
153 return mUniformBlockRegisterMap.find(blockName)->second;
154 }
155
getCompilerOutputType() const156 ShShaderOutput ShaderD3D::getCompilerOutputType() const
157 {
158 return mCompilerOutputType;
159 }
160
prepareSourceAndReturnOptions(std::stringstream * shaderSourceStream,std::string * sourcePath)161 ShCompileOptions ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream,
162 std::string *sourcePath)
163 {
164 uncompile();
165
166 ShCompileOptions additionalOptions = 0;
167
168 const std::string &source = mData.getSource();
169
170 #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
171 if (gl::DebugAnnotationsActive())
172 {
173 *sourcePath = getTempPath();
174 writeFile(sourcePath->c_str(), source.c_str(), source.length());
175 additionalOptions |= SH_LINE_DIRECTIVES | SH_SOURCE_PATH;
176 }
177 #endif
178
179 additionalOptions |= mAdditionalOptions;
180
181 *shaderSourceStream << source;
182 return additionalOptions;
183 }
184
hasUniform(const std::string & name) const185 bool ShaderD3D::hasUniform(const std::string &name) const
186 {
187 return mUniformRegisterMap.find(name) != mUniformRegisterMap.end();
188 }
189
GetUniformRegisterMap(const std::map<std::string,unsigned int> * uniformRegisterMap)190 const std::map<std::string, unsigned int> &GetUniformRegisterMap(
191 const std::map<std::string, unsigned int> *uniformRegisterMap)
192 {
193 ASSERT(uniformRegisterMap);
194 return *uniformRegisterMap;
195 }
196
postTranslateCompile(gl::Compiler * compiler,std::string * infoLog)197 bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog)
198 {
199 // TODO(jmadill): We shouldn't need to cache this.
200 mCompilerOutputType = compiler->getShaderOutputType();
201
202 const std::string &translatedSource = mData.getTranslatedSource();
203
204 mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos;
205 mUsesFragColor = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
206 mUsesFragData = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
207 mUsesFragCoord = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
208 mUsesFrontFacing = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
209 mUsesPointSize = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
210 mUsesPointCoord = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
211 mUsesDepthRange = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
212 mUsesFragDepth = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
213 mHasANGLEMultiviewEnabled =
214 translatedSource.find("GL_ANGLE_MULTIVIEW_ENABLED") != std::string::npos;
215 mUsesViewID = translatedSource.find("GL_USES_VIEW_ID") != std::string::npos;
216 mUsesDiscardRewriting =
217 translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
218 mUsesNestedBreak = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
219 mRequiresIEEEStrictCompiling =
220 translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;
221
222 ShHandle compilerHandle = compiler->getCompilerHandle(mData.getShaderType());
223
224 mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle));
225
226 for (const sh::InterfaceBlock &interfaceBlock : mData.getUniformBlocks())
227 {
228 if (interfaceBlock.staticUse)
229 {
230 unsigned int index = static_cast<unsigned int>(-1);
231 bool blockRegisterResult =
232 sh::GetUniformBlockRegister(compilerHandle, interfaceBlock.name, &index);
233 ASSERT(blockRegisterResult);
234
235 mUniformBlockRegisterMap[interfaceBlock.name] = index;
236 }
237 }
238
239 mDebugInfo +=
240 std::string("// ") + GetShaderTypeString(mData.getShaderType()) + " SHADER BEGIN\n";
241 mDebugInfo += "\n// GLSL BEGIN\n\n" + mData.getSource() + "\n\n// GLSL END\n\n\n";
242 mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n";
243 // Successive steps will append more info
244 return true;
245 }
246
247 } // namespace rx
248