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