• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 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/system_utils.h"
12 #include "common/utilities.h"
13 #include "libANGLE/Caps.h"
14 #include "libANGLE/Compiler.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Shader.h"
17 #include "libANGLE/features.h"
18 #include "libANGLE/renderer/ContextImpl.h"
19 #include "libANGLE/renderer/d3d/ProgramD3D.h"
20 #include "libANGLE/renderer/d3d/RendererD3D.h"
21 #include "libANGLE/trace.h"
22 
23 namespace rx
24 {
25 
26 class TranslateTaskD3D : public angle::Closure
27 {
28   public:
TranslateTaskD3D(ShHandle handle,const ShCompileOptions & options,const std::string & source,const std::string & sourcePath)29     TranslateTaskD3D(ShHandle handle,
30                      const ShCompileOptions &options,
31                      const std::string &source,
32                      const std::string &sourcePath)
33         : mHandle(handle),
34           mOptions(options),
35           mSource(source),
36           mSourcePath(sourcePath),
37           mResult(false)
38     {}
39 
operator ()()40     void operator()() override
41     {
42         ANGLE_TRACE_EVENT1("gpu.angle", "TranslateTask::run", "source", mSource);
43         std::vector<const char *> srcStrings;
44         if (!mSourcePath.empty())
45         {
46             srcStrings.push_back(mSourcePath.c_str());
47         }
48         srcStrings.push_back(mSource.c_str());
49 
50         mResult = sh::Compile(mHandle, &srcStrings[0], srcStrings.size(), mOptions);
51     }
52 
getResult()53     bool getResult() { return mResult; }
54 
55   private:
56     ShHandle mHandle;
57     ShCompileOptions mOptions;
58     std::string mSource;
59     std::string mSourcePath;
60     bool mResult;
61 };
62 
63 using PostTranslateFunctor =
64     std::function<bool(gl::ShCompilerInstance *compiler, std::string *infoLog)>;
65 
66 class WaitableCompileEventD3D final : public WaitableCompileEvent
67 {
68   public:
WaitableCompileEventD3D(std::shared_ptr<angle::WaitableEvent> waitableEvent,gl::ShCompilerInstance * compilerInstance,PostTranslateFunctor && postTranslateFunctor,std::shared_ptr<TranslateTaskD3D> translateTask)69     WaitableCompileEventD3D(std::shared_ptr<angle::WaitableEvent> waitableEvent,
70                             gl::ShCompilerInstance *compilerInstance,
71                             PostTranslateFunctor &&postTranslateFunctor,
72                             std::shared_ptr<TranslateTaskD3D> translateTask)
73         : WaitableCompileEvent(waitableEvent),
74           mCompilerInstance(compilerInstance),
75           mPostTranslateFunctor(std::move(postTranslateFunctor)),
76           mTranslateTask(translateTask)
77     {}
78 
getResult()79     bool getResult() override { return mTranslateTask->getResult(); }
80 
postTranslate(std::string * infoLog)81     bool postTranslate(std::string *infoLog) override
82     {
83         return mPostTranslateFunctor(mCompilerInstance, infoLog);
84     }
85 
86   private:
87     gl::ShCompilerInstance *mCompilerInstance;
88     PostTranslateFunctor mPostTranslateFunctor;
89     std::shared_ptr<TranslateTaskD3D> mTranslateTask;
90 };
91 
ShaderD3D(const gl::ShaderState & state,RendererD3D * renderer)92 ShaderD3D::ShaderD3D(const gl::ShaderState &state, RendererD3D *renderer)
93     : ShaderImpl(state), mRenderer(renderer)
94 {
95     uncompile();
96 }
97 
~ShaderD3D()98 ShaderD3D::~ShaderD3D() {}
99 
getDebugInfo() const100 std::string ShaderD3D::getDebugInfo() const
101 {
102     if (mDebugInfo.empty())
103     {
104         return "";
105     }
106 
107     return mDebugInfo + std::string("\n// ") + gl::GetShaderTypeString(mState.getShaderType()) +
108            " SHADER END\n";
109 }
110 
111 // initialize/clean up previous state
uncompile()112 void ShaderD3D::uncompile()
113 {
114     // set by compileToHLSL
115     mCompilerOutputType = SH_ESSL_OUTPUT;
116 
117     mUsesMultipleRenderTargets   = false;
118     mUsesFragColor               = false;
119     mUsesFragData                = false;
120     mUsesSecondaryColor          = false;
121     mUsesFragCoord               = false;
122     mUsesFrontFacing             = false;
123     mUsesHelperInvocation        = false;
124     mUsesPointSize               = false;
125     mUsesPointCoord              = false;
126     mUsesSampleID                = false;
127     mUsesSamplePosition          = false;
128     mUsesSampleMaskIn            = false;
129     mUsesSampleMask              = false;
130     mUsesDepthRange              = false;
131     mHasMultiviewEnabled         = false;
132     mUsesVertexID                = false;
133     mUsesViewID                  = false;
134     mUsesDiscardRewriting        = false;
135     mUsesNestedBreak             = false;
136     mRequiresIEEEStrictCompiling = false;
137     mFragDepthUsage              = FragDepthUsage::Unused;
138     mClipDistanceSize            = 0;
139     mCullDistanceSize            = 0;
140 
141     mDebugInfo.clear();
142 }
143 
generateWorkarounds(CompilerWorkaroundsD3D * workarounds) const144 void ShaderD3D::generateWorkarounds(CompilerWorkaroundsD3D *workarounds) const
145 {
146     if (mUsesDiscardRewriting)
147     {
148         // ANGLE issue 486:
149         // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by
150         // disabling optimization
151         workarounds->skipOptimization = true;
152     }
153     else if (mUsesNestedBreak)
154     {
155         // ANGLE issue 603:
156         // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop,
157         // by maximizing optimization We want to keep the use of
158         // ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes
159         // precedence
160         workarounds->useMaxOptimization = true;
161     }
162 
163     if (mRequiresIEEEStrictCompiling)
164     {
165         // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work.
166         workarounds->enableIEEEStrictness = true;
167     }
168 }
169 
getUniformRegister(const std::string & uniformName) const170 unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const
171 {
172     ASSERT(mUniformRegisterMap.count(uniformName) > 0);
173     return mUniformRegisterMap.find(uniformName)->second;
174 }
175 
getUniformBlockRegister(const std::string & blockName) const176 unsigned int ShaderD3D::getUniformBlockRegister(const std::string &blockName) const
177 {
178     ASSERT(mUniformBlockRegisterMap.count(blockName) > 0);
179     return mUniformBlockRegisterMap.find(blockName)->second;
180 }
181 
shouldUniformBlockUseStructuredBuffer(const std::string & blockName) const182 bool ShaderD3D::shouldUniformBlockUseStructuredBuffer(const std::string &blockName) const
183 {
184     ASSERT(mUniformBlockUseStructuredBufferMap.count(blockName) > 0);
185     return mUniformBlockUseStructuredBufferMap.find(blockName)->second;
186 }
187 
getShaderStorageBlockRegister(const std::string & blockName) const188 unsigned int ShaderD3D::getShaderStorageBlockRegister(const std::string &blockName) const
189 {
190     ASSERT(mShaderStorageBlockRegisterMap.count(blockName) > 0);
191     return mShaderStorageBlockRegisterMap.find(blockName)->second;
192 }
193 
getCompilerOutputType() const194 ShShaderOutput ShaderD3D::getCompilerOutputType() const
195 {
196     return mCompilerOutputType;
197 }
198 
useImage2DFunction(const std::string & functionName) const199 bool ShaderD3D::useImage2DFunction(const std::string &functionName) const
200 {
201     if (mUsedImage2DFunctionNames.empty())
202     {
203         return false;
204     }
205 
206     return mUsedImage2DFunctionNames.find(functionName) != mUsedImage2DFunctionNames.end();
207 }
208 
getSlowCompilingUniformBlockSet() const209 const std::set<std::string> &ShaderD3D::getSlowCompilingUniformBlockSet() const
210 {
211     return mSlowCompilingUniformBlockSet;
212 }
213 
GetUniformRegisterMap(const std::map<std::string,unsigned int> * uniformRegisterMap)214 const std::map<std::string, unsigned int> &GetUniformRegisterMap(
215     const std::map<std::string, unsigned int> *uniformRegisterMap)
216 {
217     ASSERT(uniformRegisterMap);
218     return *uniformRegisterMap;
219 }
220 
GetSlowCompilingUniformBlockSet(const std::set<std::string> * slowCompilingUniformBlockSet)221 const std::set<std::string> &GetSlowCompilingUniformBlockSet(
222     const std::set<std::string> *slowCompilingUniformBlockSet)
223 {
224     ASSERT(slowCompilingUniformBlockSet);
225     return *slowCompilingUniformBlockSet;
226 }
227 
GetUsedImage2DFunctionNames(const std::set<std::string> * usedImage2DFunctionNames)228 const std::set<std::string> &GetUsedImage2DFunctionNames(
229     const std::set<std::string> *usedImage2DFunctionNames)
230 {
231     ASSERT(usedImage2DFunctionNames);
232     return *usedImage2DFunctionNames;
233 }
234 
compile(const gl::Context * context,gl::ShCompilerInstance * compilerInstance,ShCompileOptions * options)235 std::shared_ptr<WaitableCompileEvent> ShaderD3D::compile(const gl::Context *context,
236                                                          gl::ShCompilerInstance *compilerInstance,
237                                                          ShCompileOptions *options)
238 {
239     std::string sourcePath;
240     uncompile();
241 
242     const angle::FeaturesD3D &features = mRenderer->getFeatures();
243     const gl::Extensions &extensions   = mRenderer->getNativeExtensions();
244 
245     const std::string &source = mState.getSource();
246 
247 #if !defined(ANGLE_ENABLE_WINDOWS_UWP)
248     if (gl::DebugAnnotationsActive(context))
249     {
250         sourcePath = angle::CreateTemporaryFile().value();
251         writeFile(sourcePath.c_str(), source.c_str(), source.length());
252         options->lineDirectives = true;
253         options->sourcePath     = true;
254     }
255 #endif
256 
257     if (features.expandIntegerPowExpressions.enabled)
258     {
259         options->expandSelectHLSLIntegerPowExpressions = true;
260     }
261 
262     if (features.getDimensionsIgnoresBaseLevel.enabled)
263     {
264         options->HLSLGetDimensionsIgnoresBaseLevel = true;
265     }
266 
267     if (features.preAddTexelFetchOffsets.enabled)
268     {
269         options->rewriteTexelFetchOffsetToTexelFetch = true;
270     }
271     if (features.rewriteUnaryMinusOperator.enabled)
272     {
273         options->rewriteIntegerUnaryMinusOperator = true;
274     }
275     if (features.emulateIsnanFloat.enabled)
276     {
277         options->emulateIsnanFloatFunction = true;
278     }
279     if (features.skipVSConstantRegisterZero.enabled &&
280         mState.getShaderType() == gl::ShaderType::Vertex)
281     {
282         options->skipD3DConstantRegisterZero = true;
283     }
284     if (features.forceAtomicValueResolution.enabled)
285     {
286         options->forceAtomicValueResolution = true;
287     }
288     if (features.allowTranslateUniformBlockToStructuredBuffer.enabled)
289     {
290         options->allowTranslateUniformBlockToStructuredBuffer = true;
291     }
292     if (extensions.multiviewOVR || extensions.multiview2OVR)
293     {
294         options->initializeBuiltinsForInstancedMultiview = true;
295     }
296     if (extensions.shaderPixelLocalStorageANGLE)
297     {
298         options->pls = mRenderer->getNativePixelLocalStorageOptions();
299     }
300 
301     auto postTranslateFunctor = [this](gl::ShCompilerInstance *compiler, std::string *infoLog) {
302         // TODO(jmadill): We shouldn't need to cache this.
303         mCompilerOutputType = compiler->getShaderOutputType();
304 
305         const std::string &translatedSource = mState.getTranslatedSource();
306 
307         mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos;
308         mUsesFragColor      = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
309         mUsesFragData       = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
310         mUsesSecondaryColor = translatedSource.find("GL_USES_SECONDARY_COLOR") != std::string::npos;
311         mUsesFragCoord      = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
312         mUsesFrontFacing    = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
313         mUsesSampleID       = translatedSource.find("GL_USES_SAMPLE_ID") != std::string::npos;
314         mUsesSamplePosition = translatedSource.find("GL_USES_SAMPLE_POSITION") != std::string::npos;
315         mUsesSampleMaskIn   = translatedSource.find("GL_USES_SAMPLE_MASK_IN") != std::string::npos;
316         mUsesSampleMask     = translatedSource.find("GL_USES_SAMPLE_MASK_OUT") != std::string::npos;
317         mUsesHelperInvocation =
318             translatedSource.find("GL_USES_HELPER_INVOCATION") != std::string::npos;
319         mUsesPointSize       = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
320         mUsesPointCoord      = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
321         mUsesDepthRange      = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
322         mHasMultiviewEnabled = translatedSource.find("GL_MULTIVIEW_ENABLED") != std::string::npos;
323         mUsesVertexID        = translatedSource.find("GL_USES_VERTEX_ID") != std::string::npos;
324         mUsesViewID          = translatedSource.find("GL_USES_VIEW_ID") != std::string::npos;
325         mUsesDiscardRewriting =
326             translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
327         mUsesNestedBreak = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
328         mRequiresIEEEStrictCompiling =
329             translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;
330 
331         ShHandle compilerHandle = compiler->getHandle();
332 
333         if (translatedSource.find("GL_USES_FRAG_DEPTH_GREATER") != std::string::npos)
334         {
335             mFragDepthUsage = FragDepthUsage::Greater;
336         }
337         else if (translatedSource.find("GL_USES_FRAG_DEPTH_LESS") != std::string::npos)
338         {
339             mFragDepthUsage = FragDepthUsage::Less;
340         }
341         else if (translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos)
342         {
343             mFragDepthUsage = FragDepthUsage::Any;
344         }
345         mClipDistanceSize   = sh::GetClipDistanceArraySize(compilerHandle);
346         mCullDistanceSize   = sh::GetCullDistanceArraySize(compilerHandle);
347         mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle));
348         mReadonlyImage2DRegisterIndex = sh::GetReadonlyImage2DRegisterIndex(compilerHandle);
349         mImage2DRegisterIndex         = sh::GetImage2DRegisterIndex(compilerHandle);
350         mUsedImage2DFunctionNames =
351             GetUsedImage2DFunctionNames(sh::GetUsedImage2DFunctionNames(compilerHandle));
352 
353         for (const sh::InterfaceBlock &interfaceBlock : mState.getUniformBlocks())
354         {
355             if (interfaceBlock.active)
356             {
357                 unsigned int index = static_cast<unsigned int>(-1);
358                 bool blockRegisterResult =
359                     sh::GetUniformBlockRegister(compilerHandle, interfaceBlock.name, &index);
360                 ASSERT(blockRegisterResult);
361                 bool useStructuredBuffer =
362                     sh::ShouldUniformBlockUseStructuredBuffer(compilerHandle, interfaceBlock.name);
363 
364                 mUniformBlockRegisterMap[interfaceBlock.name]            = index;
365                 mUniformBlockUseStructuredBufferMap[interfaceBlock.name] = useStructuredBuffer;
366             }
367         }
368 
369         mSlowCompilingUniformBlockSet =
370             GetSlowCompilingUniformBlockSet(sh::GetSlowCompilingUniformBlockSet(compilerHandle));
371 
372         for (const sh::InterfaceBlock &interfaceBlock : mState.getShaderStorageBlocks())
373         {
374             if (interfaceBlock.active)
375             {
376                 unsigned int index = static_cast<unsigned int>(-1);
377                 bool blockRegisterResult =
378                     sh::GetShaderStorageBlockRegister(compilerHandle, interfaceBlock.name, &index);
379                 ASSERT(blockRegisterResult);
380 
381                 mShaderStorageBlockRegisterMap[interfaceBlock.name] = index;
382             }
383         }
384 
385         mDebugInfo += std::string("// ") + gl::GetShaderTypeString(mState.getShaderType()) +
386                       " SHADER BEGIN\n";
387         mDebugInfo += "\n// GLSL BEGIN\n\n" + mState.getSource() + "\n\n// GLSL END\n\n\n";
388         mDebugInfo +=
389             "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n";
390         // Successive steps will append more info
391         return true;
392     };
393 
394     auto workerThreadPool = context->getWorkerThreadPool();
395     auto translateTask = std::make_shared<TranslateTaskD3D>(compilerInstance->getHandle(), *options,
396                                                             source, sourcePath);
397 
398     return std::make_shared<WaitableCompileEventD3D>(
399         workerThreadPool->postWorkerTask(translateTask), compilerInstance,
400         std::move(postTranslateFunctor), translateTask);
401 }
402 
hasUniform(const std::string & name) const403 bool ShaderD3D::hasUniform(const std::string &name) const
404 {
405     return mUniformRegisterMap.find(name) != mUniformRegisterMap.end();
406 }
407 
408 }  // namespace rx
409