• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 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 // ShaderVk.cpp:
7 //    Implements the class methods for ShaderVk.
8 //
9 
10 #include "libANGLE/renderer/vulkan/ShaderVk.h"
11 
12 #include "common/debug.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Display.h"
15 #include "libANGLE/renderer/vulkan/ContextVk.h"
16 
17 namespace rx
18 {
ShaderVk(const gl::ShaderState & state)19 ShaderVk::ShaderVk(const gl::ShaderState &state) : ShaderImpl(state) {}
20 
~ShaderVk()21 ShaderVk::~ShaderVk() {}
22 
compile(const gl::Context * context,ShCompileOptions * options)23 std::shared_ptr<ShaderTranslateTask> ShaderVk::compile(const gl::Context *context,
24                                                        ShCompileOptions *options)
25 {
26     ContextVk *contextVk = vk::GetImpl(context);
27 
28     if (context->isWebGL())
29     {
30         // Only WebGL requires initialization of local variables, others don't.
31         // Extra initialization in spirv shader may affect performance.
32         options->initializeUninitializedLocals = true;
33 
34         // WebGL shaders may contain OOB array accesses which in turn cause undefined behavior,
35         // which may result in security issues. See https://crbug.com/1189110.
36         options->clampIndirectArrayBounds = true;
37 
38         if (mState.getShaderType() != gl::ShaderType::Compute)
39         {
40             options->initOutputVariables = true;
41         }
42     }
43 
44     if (contextVk->getFeatures().supportsSPIRV14.enabled)
45     {
46         options->emitSPIRV14 = true;
47     }
48 
49     if (contextVk->getFeatures().retainSPIRVDebugInfo.enabled)
50     {
51         options->outputDebugInfo = true;
52     }
53 
54     // robustBufferAccess on Vulkan doesn't support bound check on shader local variables
55     // but the GL_EXT_robustness does support.
56     // Enable the flag clampIndirectArrayBounds to ensure out of bounds local variable writes in
57     // shaders are protected when the context has GL_EXT_robustness enabled
58     if (contextVk->getShareGroup()->hasAnyContextWithRobustness())
59     {
60         options->clampIndirectArrayBounds = true;
61     }
62 
63     if (contextVk->getFeatures().clampPointSize.enabled)
64     {
65         options->clampPointSize = true;
66     }
67 
68     if (contextVk->getFeatures().emulateAdvancedBlendEquations.enabled)
69     {
70         options->addAdvancedBlendEquationsEmulation = true;
71     }
72 
73     if (contextVk->emulateSeamfulCubeMapSampling())
74     {
75         options->emulateSeamfulCubeMapSampling = true;
76     }
77 
78     if (!contextVk->getFeatures().enablePrecisionQualifiers.enabled)
79     {
80         options->ignorePrecisionQualifiers = true;
81     }
82 
83     if (contextVk->getFeatures().forceFragmentShaderPrecisionHighpToMediump.enabled)
84     {
85         options->forceShaderPrecisionHighpToMediump = true;
86     }
87 
88     // Let compiler use specialized constant for pre-rotation.
89     if (!contextVk->getFeatures().preferDriverUniformOverSpecConst.enabled)
90     {
91         options->useSpecializationConstant = true;
92     }
93 
94     if (contextVk->getFeatures().clampFragDepth.enabled)
95     {
96         options->clampFragDepth = true;
97     }
98 
99     if (!contextVk->getFeatures().supportsDepthClipControl.enabled)
100     {
101         options->addVulkanDepthCorrection = true;
102     }
103 
104     if (contextVk->getFeatures().supportsTransformFeedbackExtension.enabled)
105     {
106         options->addVulkanXfbExtensionSupportCode = true;
107     }
108     else if (mState.getShaderType() == gl::ShaderType::Vertex &&
109              contextVk->getFeatures().emulateTransformFeedback.enabled)
110     {
111         options->addVulkanXfbEmulationSupportCode = true;
112     }
113 
114     if (contextVk->getFeatures().roundOutputAfterDithering.enabled)
115     {
116         options->roundOutputAfterDithering = true;
117     }
118 
119     if (contextVk->getFeatures().appendAliasedMemoryDecorations.enabled)
120     {
121         options->aliasedUnlessRestrict = true;
122     }
123 
124     if (contextVk->getFeatures().explicitlyCastMediumpFloatTo16Bit.enabled)
125     {
126         options->castMediumpFloatTo16Bit = true;
127     }
128 
129     if (contextVk->getExtensions().shaderPixelLocalStorageANGLE)
130     {
131         options->pls = contextVk->getNativePixelLocalStorageOptions();
132     }
133 
134     if (contextVk->getFeatures().avoidOpSelectWithMismatchingRelaxedPrecision.enabled)
135     {
136         options->avoidOpSelectWithMismatchingRelaxedPrecision = true;
137     }
138 
139     // The Vulkan backend needs no post-processing of the translated shader.
140     return std::shared_ptr<ShaderTranslateTask>(new ShaderTranslateTask);
141 }
142 
getDebugInfo() const143 std::string ShaderVk::getDebugInfo() const
144 {
145     const sh::BinaryBlob &spirv = mState.getCompiledState()->compiledBinary;
146     if (spirv.empty())
147     {
148         return "";
149     }
150 
151     std::ostringstream blob;
152     if (!mState.getCompiledState()->inputVaryings.empty())
153     {
154         blob << "Inputs:";
155         for (const sh::ShaderVariable &var : mState.getCompiledState()->inputVaryings)
156         {
157             blob << " " << var.name;
158         }
159         blob << std::endl;
160     }
161     if (!mState.getCompiledState()->activeAttributes.empty())
162     {
163         blob << "Inputs:";
164         for (const sh::ShaderVariable &var : mState.getCompiledState()->activeAttributes)
165         {
166             blob << " " << var.name;
167         }
168         blob << std::endl;
169     }
170     if (!mState.getCompiledState()->outputVaryings.empty())
171     {
172         blob << "Outputs:";
173         for (const sh::ShaderVariable &var : mState.getCompiledState()->outputVaryings)
174         {
175             blob << " " << var.name;
176         }
177         blob << std::endl;
178     }
179     if (!mState.getCompiledState()->activeOutputVariables.empty())
180     {
181         blob << "Outputs:";
182         for (const sh::ShaderVariable &var : mState.getCompiledState()->activeOutputVariables)
183         {
184             blob << " " << var.name;
185         }
186         blob << std::endl;
187     }
188     if (!mState.getCompiledState()->uniforms.empty())
189     {
190         blob << "Uniforms:";
191         for (const sh::ShaderVariable &var : mState.getCompiledState()->uniforms)
192         {
193             blob << " " << var.name;
194         }
195         blob << std::endl;
196     }
197     if (!mState.getCompiledState()->uniformBlocks.empty())
198     {
199         blob << "Uniform blocks:";
200         for (const sh::InterfaceBlock &block : mState.getCompiledState()->uniformBlocks)
201         {
202             blob << " " << block.name;
203         }
204         blob << std::endl;
205     }
206     if (!mState.getCompiledState()->shaderStorageBlocks.empty())
207     {
208         blob << "Storage blocks:";
209         for (const sh::InterfaceBlock &block : mState.getCompiledState()->shaderStorageBlocks)
210         {
211             blob << " " << block.name;
212         }
213         blob << std::endl;
214     }
215 
216     blob << R"(
217 Paste the following SPIR-V binary in https://www.khronos.org/spir/visualizer/
218 
219 Setting the environment variable ANGLE_FEATURE_OVERRIDES_ENABLED=retainSPIRVDebugInfo will retain debug info
220 
221 )";
222 
223     constexpr size_t kIndicesPerRow = 10;
224     size_t rowOffset                = 0;
225     for (size_t index = 0; index < spirv.size(); ++index, ++rowOffset)
226     {
227         if (rowOffset == kIndicesPerRow)
228         {
229             blob << std::endl;
230             rowOffset = 0;
231         }
232         blob << "0x" << std::uppercase << std::setfill('0') << std::setw(8) << std::hex
233              << spirv[index] << ",";
234     }
235 
236     return blob.str();
237 }
238 
239 }  // namespace rx
240