xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/ProgramExecutableVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2020 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 // ProgramExecutableVk.cpp: Collects the information and interfaces common to both ProgramVks and
7*8975f5c5SAndroid Build Coastguard Worker // ProgramPipelineVks in order to execute/draw with either.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ProgramExecutableVk.h"
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/BufferVk.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/DisplayVk.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/FramebufferVk.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/ProgramVk.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/TextureVk.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_helpers.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/vulkan/vk_utils.h"
21*8975f5c5SAndroid Build Coastguard Worker 
22*8975f5c5SAndroid Build Coastguard Worker namespace rx
23*8975f5c5SAndroid Build Coastguard Worker {
24*8975f5c5SAndroid Build Coastguard Worker namespace
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker 
27*8975f5c5SAndroid Build Coastguard Worker // Limit decompressed vulkan pipelines to 10MB per program.
28*8975f5c5SAndroid Build Coastguard Worker static constexpr size_t kMaxLocalPipelineCacheSize = 10 * 1024 * 1024;
29*8975f5c5SAndroid Build Coastguard Worker 
ValidateTransformedSpirV(vk::Context * context,const gl::ShaderBitSet & linkedShaderStages,const ShaderInterfaceVariableInfoMap & variableInfoMap,const gl::ShaderMap<angle::spirv::Blob> & spirvBlobs)30*8975f5c5SAndroid Build Coastguard Worker bool ValidateTransformedSpirV(vk::Context *context,
31*8975f5c5SAndroid Build Coastguard Worker                               const gl::ShaderBitSet &linkedShaderStages,
32*8975f5c5SAndroid Build Coastguard Worker                               const ShaderInterfaceVariableInfoMap &variableInfoMap,
33*8975f5c5SAndroid Build Coastguard Worker                               const gl::ShaderMap<angle::spirv::Blob> &spirvBlobs)
34*8975f5c5SAndroid Build Coastguard Worker {
35*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderType lastPreFragmentStage = gl::GetLastPreFragmentStage(linkedShaderStages);
36*8975f5c5SAndroid Build Coastguard Worker 
37*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : linkedShaderStages)
38*8975f5c5SAndroid Build Coastguard Worker     {
39*8975f5c5SAndroid Build Coastguard Worker         SpvTransformOptions options;
40*8975f5c5SAndroid Build Coastguard Worker         options.shaderType = shaderType;
41*8975f5c5SAndroid Build Coastguard Worker         options.isLastPreFragmentStage =
42*8975f5c5SAndroid Build Coastguard Worker             shaderType == lastPreFragmentStage && shaderType != gl::ShaderType::TessControl;
43*8975f5c5SAndroid Build Coastguard Worker         options.isTransformFeedbackStage = options.isLastPreFragmentStage;
44*8975f5c5SAndroid Build Coastguard Worker         options.useSpirvVaryingPrecisionFixer =
45*8975f5c5SAndroid Build Coastguard Worker             context->getFeatures().varyingsRequireMatchingPrecisionInSpirv.enabled;
46*8975f5c5SAndroid Build Coastguard Worker 
47*8975f5c5SAndroid Build Coastguard Worker         angle::spirv::Blob transformed;
48*8975f5c5SAndroid Build Coastguard Worker         if (SpvTransformSpirvCode(options, variableInfoMap, spirvBlobs[shaderType], &transformed) !=
49*8975f5c5SAndroid Build Coastguard Worker             angle::Result::Continue)
50*8975f5c5SAndroid Build Coastguard Worker         {
51*8975f5c5SAndroid Build Coastguard Worker             return false;
52*8975f5c5SAndroid Build Coastguard Worker         }
53*8975f5c5SAndroid Build Coastguard Worker     }
54*8975f5c5SAndroid Build Coastguard Worker     return true;
55*8975f5c5SAndroid Build Coastguard Worker }
56*8975f5c5SAndroid Build Coastguard Worker 
GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> & blocks,uint32_t bufferIndex)57*8975f5c5SAndroid Build Coastguard Worker uint32_t GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> &blocks,
58*8975f5c5SAndroid Build Coastguard Worker                                     uint32_t bufferIndex)
59*8975f5c5SAndroid Build Coastguard Worker {
60*8975f5c5SAndroid Build Coastguard Worker     const gl::InterfaceBlock &block = blocks[bufferIndex];
61*8975f5c5SAndroid Build Coastguard Worker 
62*8975f5c5SAndroid Build Coastguard Worker     if (!block.pod.isArray)
63*8975f5c5SAndroid Build Coastguard Worker     {
64*8975f5c5SAndroid Build Coastguard Worker         return 1;
65*8975f5c5SAndroid Build Coastguard Worker     }
66*8975f5c5SAndroid Build Coastguard Worker 
67*8975f5c5SAndroid Build Coastguard Worker     ASSERT(block.pod.arrayElement == 0);
68*8975f5c5SAndroid Build Coastguard Worker 
69*8975f5c5SAndroid Build Coastguard Worker     // Search consecutively until all array indices of this block are visited.
70*8975f5c5SAndroid Build Coastguard Worker     uint32_t arraySize;
71*8975f5c5SAndroid Build Coastguard Worker     for (arraySize = 1; bufferIndex + arraySize < blocks.size(); ++arraySize)
72*8975f5c5SAndroid Build Coastguard Worker     {
73*8975f5c5SAndroid Build Coastguard Worker         const gl::InterfaceBlock &nextBlock = blocks[bufferIndex + arraySize];
74*8975f5c5SAndroid Build Coastguard Worker 
75*8975f5c5SAndroid Build Coastguard Worker         if (nextBlock.pod.arrayElement != arraySize)
76*8975f5c5SAndroid Build Coastguard Worker         {
77*8975f5c5SAndroid Build Coastguard Worker             break;
78*8975f5c5SAndroid Build Coastguard Worker         }
79*8975f5c5SAndroid Build Coastguard Worker 
80*8975f5c5SAndroid Build Coastguard Worker         // It's unexpected for an array to start at a non-zero array size, so we can always rely on
81*8975f5c5SAndroid Build Coastguard Worker         // the sequential `arrayElement`s to belong to the same block.
82*8975f5c5SAndroid Build Coastguard Worker         ASSERT(nextBlock.name == block.name);
83*8975f5c5SAndroid Build Coastguard Worker         ASSERT(nextBlock.pod.isArray);
84*8975f5c5SAndroid Build Coastguard Worker     }
85*8975f5c5SAndroid Build Coastguard Worker 
86*8975f5c5SAndroid Build Coastguard Worker     return arraySize;
87*8975f5c5SAndroid Build Coastguard Worker }
88*8975f5c5SAndroid Build Coastguard Worker 
SetupDefaultPipelineState(const vk::Context * context,const gl::ProgramExecutable & glExecutable,gl::PrimitiveMode mode,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess,vk::GraphicsPipelineSubset subset,vk::GraphicsPipelineDesc * graphicsPipelineDescOut)89*8975f5c5SAndroid Build Coastguard Worker void SetupDefaultPipelineState(const vk::Context *context,
90*8975f5c5SAndroid Build Coastguard Worker                                const gl::ProgramExecutable &glExecutable,
91*8975f5c5SAndroid Build Coastguard Worker                                gl::PrimitiveMode mode,
92*8975f5c5SAndroid Build Coastguard Worker                                vk::PipelineRobustness pipelineRobustness,
93*8975f5c5SAndroid Build Coastguard Worker                                vk::PipelineProtectedAccess pipelineProtectedAccess,
94*8975f5c5SAndroid Build Coastguard Worker                                vk::GraphicsPipelineSubset subset,
95*8975f5c5SAndroid Build Coastguard Worker                                vk::GraphicsPipelineDesc *graphicsPipelineDescOut)
96*8975f5c5SAndroid Build Coastguard Worker {
97*8975f5c5SAndroid Build Coastguard Worker     graphicsPipelineDescOut->initDefaults(context, vk::GraphicsPipelineSubset::Complete,
98*8975f5c5SAndroid Build Coastguard Worker                                           pipelineRobustness, pipelineProtectedAccess);
99*8975f5c5SAndroid Build Coastguard Worker 
100*8975f5c5SAndroid Build Coastguard Worker     // Set render pass state, affecting both complete and shaders-only pipelines.
101*8975f5c5SAndroid Build Coastguard Worker     graphicsPipelineDescOut->setTopology(mode);
102*8975f5c5SAndroid Build Coastguard Worker     graphicsPipelineDescOut->setRenderPassSampleCount(1);
103*8975f5c5SAndroid Build Coastguard Worker     graphicsPipelineDescOut->setRenderPassFramebufferFetchMode(
104*8975f5c5SAndroid Build Coastguard Worker         vk::GetProgramFramebufferFetchMode(&glExecutable));
105*8975f5c5SAndroid Build Coastguard Worker 
106*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::ProgramOutput> &outputVariables    = glExecutable.getOutputVariables();
107*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::VariableLocation> &outputLocations = glExecutable.getOutputLocations();
108*8975f5c5SAndroid Build Coastguard Worker 
109*8975f5c5SAndroid Build Coastguard Worker     gl::DrawBufferMask drawBuffers;
110*8975f5c5SAndroid Build Coastguard Worker 
111*8975f5c5SAndroid Build Coastguard Worker     for (const gl::VariableLocation &outputLocation : outputLocations)
112*8975f5c5SAndroid Build Coastguard Worker     {
113*8975f5c5SAndroid Build Coastguard Worker         if (outputLocation.arrayIndex == 0 && outputLocation.used() && !outputLocation.ignored)
114*8975f5c5SAndroid Build Coastguard Worker         {
115*8975f5c5SAndroid Build Coastguard Worker             const gl::ProgramOutput &outputVar = outputVariables[outputLocation.index];
116*8975f5c5SAndroid Build Coastguard Worker 
117*8975f5c5SAndroid Build Coastguard Worker             if (angle::BeginsWith(outputVar.name, "gl_") && outputVar.name != "gl_FragColor")
118*8975f5c5SAndroid Build Coastguard Worker             {
119*8975f5c5SAndroid Build Coastguard Worker                 continue;
120*8975f5c5SAndroid Build Coastguard Worker             }
121*8975f5c5SAndroid Build Coastguard Worker 
122*8975f5c5SAndroid Build Coastguard Worker             uint32_t location = 0;
123*8975f5c5SAndroid Build Coastguard Worker             if (outputVar.pod.location != -1)
124*8975f5c5SAndroid Build Coastguard Worker             {
125*8975f5c5SAndroid Build Coastguard Worker                 location = outputVar.pod.location;
126*8975f5c5SAndroid Build Coastguard Worker             }
127*8975f5c5SAndroid Build Coastguard Worker 
128*8975f5c5SAndroid Build Coastguard Worker             GLenum type            = gl::VariableComponentType(outputVar.pod.type);
129*8975f5c5SAndroid Build Coastguard Worker             angle::FormatID format = angle::FormatID::R8G8B8A8_UNORM;
130*8975f5c5SAndroid Build Coastguard Worker             if (type == GL_INT)
131*8975f5c5SAndroid Build Coastguard Worker             {
132*8975f5c5SAndroid Build Coastguard Worker                 format = angle::FormatID::R8G8B8A8_SINT;
133*8975f5c5SAndroid Build Coastguard Worker             }
134*8975f5c5SAndroid Build Coastguard Worker             else if (type == GL_UNSIGNED_INT)
135*8975f5c5SAndroid Build Coastguard Worker             {
136*8975f5c5SAndroid Build Coastguard Worker                 format = angle::FormatID::R8G8B8A8_UINT;
137*8975f5c5SAndroid Build Coastguard Worker             }
138*8975f5c5SAndroid Build Coastguard Worker 
139*8975f5c5SAndroid Build Coastguard Worker             const size_t arraySize = outputVar.isArray() ? outputVar.getOutermostArraySize() : 1;
140*8975f5c5SAndroid Build Coastguard Worker             for (size_t arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
141*8975f5c5SAndroid Build Coastguard Worker             {
142*8975f5c5SAndroid Build Coastguard Worker                 graphicsPipelineDescOut->setRenderPassColorAttachmentFormat(location + arrayIndex,
143*8975f5c5SAndroid Build Coastguard Worker                                                                             format);
144*8975f5c5SAndroid Build Coastguard Worker                 drawBuffers.set(location + arrayIndex);
145*8975f5c5SAndroid Build Coastguard Worker             }
146*8975f5c5SAndroid Build Coastguard Worker         }
147*8975f5c5SAndroid Build Coastguard Worker     }
148*8975f5c5SAndroid Build Coastguard Worker 
149*8975f5c5SAndroid Build Coastguard Worker     for (const gl::ProgramOutput &outputVar : outputVariables)
150*8975f5c5SAndroid Build Coastguard Worker     {
151*8975f5c5SAndroid Build Coastguard Worker         if (outputVar.name == "gl_FragColor" || outputVar.name == "gl_FragData")
152*8975f5c5SAndroid Build Coastguard Worker         {
153*8975f5c5SAndroid Build Coastguard Worker             const size_t arraySize = outputVar.isArray() ? outputVar.getOutermostArraySize() : 1;
154*8975f5c5SAndroid Build Coastguard Worker             for (size_t arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
155*8975f5c5SAndroid Build Coastguard Worker             {
156*8975f5c5SAndroid Build Coastguard Worker                 graphicsPipelineDescOut->setRenderPassColorAttachmentFormat(
157*8975f5c5SAndroid Build Coastguard Worker                     arrayIndex, angle::FormatID::R8G8B8A8_UNORM);
158*8975f5c5SAndroid Build Coastguard Worker                 drawBuffers.set(arrayIndex);
159*8975f5c5SAndroid Build Coastguard Worker             }
160*8975f5c5SAndroid Build Coastguard Worker         }
161*8975f5c5SAndroid Build Coastguard Worker     }
162*8975f5c5SAndroid Build Coastguard Worker 
163*8975f5c5SAndroid Build Coastguard Worker     if (subset == vk::GraphicsPipelineSubset::Complete)
164*8975f5c5SAndroid Build Coastguard Worker     {
165*8975f5c5SAndroid Build Coastguard Worker         // Include vertex input state
166*8975f5c5SAndroid Build Coastguard Worker         graphicsPipelineDescOut->setVertexShaderComponentTypes(
167*8975f5c5SAndroid Build Coastguard Worker             glExecutable.getNonBuiltinAttribLocationsMask(), glExecutable.getAttributesTypeMask());
168*8975f5c5SAndroid Build Coastguard Worker 
169*8975f5c5SAndroid Build Coastguard Worker         // Include fragment output state
170*8975f5c5SAndroid Build Coastguard Worker         gl::BlendStateExt::ColorMaskStorage::Type colorMask =
171*8975f5c5SAndroid Build Coastguard Worker             gl::BlendStateExt::ColorMaskStorage::GetReplicatedValue(
172*8975f5c5SAndroid Build Coastguard Worker                 gl::BlendStateExt::PackColorMask(true, true, true, true),
173*8975f5c5SAndroid Build Coastguard Worker                 gl::BlendStateExt::ColorMaskStorage::GetMask(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS));
174*8975f5c5SAndroid Build Coastguard Worker         graphicsPipelineDescOut->setColorWriteMasks(colorMask, {}, drawBuffers);
175*8975f5c5SAndroid Build Coastguard Worker     }
176*8975f5c5SAndroid Build Coastguard Worker }
177*8975f5c5SAndroid Build Coastguard Worker 
GetPipelineCacheData(ContextVk * contextVk,const vk::PipelineCache & pipelineCache,angle::MemoryBuffer * cacheDataOut)178*8975f5c5SAndroid Build Coastguard Worker void GetPipelineCacheData(ContextVk *contextVk,
179*8975f5c5SAndroid Build Coastguard Worker                           const vk::PipelineCache &pipelineCache,
180*8975f5c5SAndroid Build Coastguard Worker                           angle::MemoryBuffer *cacheDataOut)
181*8975f5c5SAndroid Build Coastguard Worker {
182*8975f5c5SAndroid Build Coastguard Worker     ASSERT(pipelineCache.valid() || contextVk->getState().isGLES1() ||
183*8975f5c5SAndroid Build Coastguard Worker            !contextVk->getFeatures().warmUpPipelineCacheAtLink.enabled ||
184*8975f5c5SAndroid Build Coastguard Worker            !contextVk->getFeatures().hasEffectivePipelineCacheSerialization.enabled);
185*8975f5c5SAndroid Build Coastguard Worker     if (!pipelineCache.valid() ||
186*8975f5c5SAndroid Build Coastguard Worker         !contextVk->getFeatures().hasEffectivePipelineCacheSerialization.enabled)
187*8975f5c5SAndroid Build Coastguard Worker     {
188*8975f5c5SAndroid Build Coastguard Worker         return;
189*8975f5c5SAndroid Build Coastguard Worker     }
190*8975f5c5SAndroid Build Coastguard Worker 
191*8975f5c5SAndroid Build Coastguard Worker     // Extract the pipeline data.  If failed, or empty, it's simply not stored on disk.
192*8975f5c5SAndroid Build Coastguard Worker     size_t pipelineCacheSize = 0;
193*8975f5c5SAndroid Build Coastguard Worker     VkResult result =
194*8975f5c5SAndroid Build Coastguard Worker         pipelineCache.getCacheData(contextVk->getDevice(), &pipelineCacheSize, nullptr);
195*8975f5c5SAndroid Build Coastguard Worker     if (result != VK_SUCCESS || pipelineCacheSize == 0)
196*8975f5c5SAndroid Build Coastguard Worker     {
197*8975f5c5SAndroid Build Coastguard Worker         return;
198*8975f5c5SAndroid Build Coastguard Worker     }
199*8975f5c5SAndroid Build Coastguard Worker 
200*8975f5c5SAndroid Build Coastguard Worker     if (contextVk->getFeatures().enablePipelineCacheDataCompression.enabled)
201*8975f5c5SAndroid Build Coastguard Worker     {
202*8975f5c5SAndroid Build Coastguard Worker         std::vector<uint8_t> pipelineCacheData(pipelineCacheSize);
203*8975f5c5SAndroid Build Coastguard Worker         result = pipelineCache.getCacheData(contextVk->getDevice(), &pipelineCacheSize,
204*8975f5c5SAndroid Build Coastguard Worker                                             pipelineCacheData.data());
205*8975f5c5SAndroid Build Coastguard Worker         if (result != VK_SUCCESS && result != VK_INCOMPLETE)
206*8975f5c5SAndroid Build Coastguard Worker         {
207*8975f5c5SAndroid Build Coastguard Worker             return;
208*8975f5c5SAndroid Build Coastguard Worker         }
209*8975f5c5SAndroid Build Coastguard Worker 
210*8975f5c5SAndroid Build Coastguard Worker         // Compress it.
211*8975f5c5SAndroid Build Coastguard Worker         if (!angle::CompressBlob(pipelineCacheData.size(), pipelineCacheData.data(), cacheDataOut))
212*8975f5c5SAndroid Build Coastguard Worker         {
213*8975f5c5SAndroid Build Coastguard Worker             cacheDataOut->clear();
214*8975f5c5SAndroid Build Coastguard Worker         }
215*8975f5c5SAndroid Build Coastguard Worker     }
216*8975f5c5SAndroid Build Coastguard Worker     else
217*8975f5c5SAndroid Build Coastguard Worker     {
218*8975f5c5SAndroid Build Coastguard Worker         if (!cacheDataOut->resize(pipelineCacheSize))
219*8975f5c5SAndroid Build Coastguard Worker         {
220*8975f5c5SAndroid Build Coastguard Worker             ERR() << "Failed to allocate memory for pipeline cache data.";
221*8975f5c5SAndroid Build Coastguard Worker             return;
222*8975f5c5SAndroid Build Coastguard Worker         }
223*8975f5c5SAndroid Build Coastguard Worker         result = pipelineCache.getCacheData(contextVk->getDevice(), &pipelineCacheSize,
224*8975f5c5SAndroid Build Coastguard Worker                                             cacheDataOut->data());
225*8975f5c5SAndroid Build Coastguard Worker         if (result != VK_SUCCESS && result != VK_INCOMPLETE)
226*8975f5c5SAndroid Build Coastguard Worker         {
227*8975f5c5SAndroid Build Coastguard Worker             cacheDataOut->clear();
228*8975f5c5SAndroid Build Coastguard Worker         }
229*8975f5c5SAndroid Build Coastguard Worker     }
230*8975f5c5SAndroid Build Coastguard Worker }
231*8975f5c5SAndroid Build Coastguard Worker 
MakeSpecConsts(ProgramTransformOptions transformOptions,const vk::GraphicsPipelineDesc & desc)232*8975f5c5SAndroid Build Coastguard Worker vk::SpecializationConstants MakeSpecConsts(ProgramTransformOptions transformOptions,
233*8975f5c5SAndroid Build Coastguard Worker                                            const vk::GraphicsPipelineDesc &desc)
234*8975f5c5SAndroid Build Coastguard Worker {
235*8975f5c5SAndroid Build Coastguard Worker     vk::SpecializationConstants specConsts;
236*8975f5c5SAndroid Build Coastguard Worker 
237*8975f5c5SAndroid Build Coastguard Worker     specConsts.surfaceRotation = transformOptions.surfaceRotation;
238*8975f5c5SAndroid Build Coastguard Worker     specConsts.dither          = desc.getEmulatedDitherControl();
239*8975f5c5SAndroid Build Coastguard Worker 
240*8975f5c5SAndroid Build Coastguard Worker     return specConsts;
241*8975f5c5SAndroid Build Coastguard Worker }
242*8975f5c5SAndroid Build Coastguard Worker 
GetWarmUpSubset(const angle::FeaturesVk & features)243*8975f5c5SAndroid Build Coastguard Worker vk::GraphicsPipelineSubset GetWarmUpSubset(const angle::FeaturesVk &features)
244*8975f5c5SAndroid Build Coastguard Worker {
245*8975f5c5SAndroid Build Coastguard Worker     // Only build the shaders subset of the pipeline if VK_EXT_graphics_pipeline_library is
246*8975f5c5SAndroid Build Coastguard Worker     // supported.
247*8975f5c5SAndroid Build Coastguard Worker     return features.supportsGraphicsPipelineLibrary.enabled ? vk::GraphicsPipelineSubset::Shaders
248*8975f5c5SAndroid Build Coastguard Worker                                                             : vk::GraphicsPipelineSubset::Complete;
249*8975f5c5SAndroid Build Coastguard Worker }
250*8975f5c5SAndroid Build Coastguard Worker 
UpdateFullTexturesDescriptorSet(vk::Context * context,const ShaderInterfaceVariableInfoMap & variableInfoMap,const vk::WriteDescriptorDescs & writeDescriptorDescs,UpdateDescriptorSetsBuilder * updateBuilder,const gl::ProgramExecutable & executable,const gl::ActiveTextureArray<TextureVk * > & textures,const gl::SamplerBindingVector & samplers,VkDescriptorSet descriptorSet)251*8975f5c5SAndroid Build Coastguard Worker angle::Result UpdateFullTexturesDescriptorSet(vk::Context *context,
252*8975f5c5SAndroid Build Coastguard Worker                                               const ShaderInterfaceVariableInfoMap &variableInfoMap,
253*8975f5c5SAndroid Build Coastguard Worker                                               const vk::WriteDescriptorDescs &writeDescriptorDescs,
254*8975f5c5SAndroid Build Coastguard Worker                                               UpdateDescriptorSetsBuilder *updateBuilder,
255*8975f5c5SAndroid Build Coastguard Worker                                               const gl::ProgramExecutable &executable,
256*8975f5c5SAndroid Build Coastguard Worker                                               const gl::ActiveTextureArray<TextureVk *> &textures,
257*8975f5c5SAndroid Build Coastguard Worker                                               const gl::SamplerBindingVector &samplers,
258*8975f5c5SAndroid Build Coastguard Worker                                               VkDescriptorSet descriptorSet)
259*8975f5c5SAndroid Build Coastguard Worker {
260*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer                                 = context->getRenderer();
261*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::SamplerBinding> &samplerBindings = executable.getSamplerBindings();
262*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> &samplerBoundTextureUnits = executable.getSamplerBoundTextureUnits();
263*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::LinkedUniform> &uniforms      = executable.getUniforms();
264*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTextureTypeArray &textureTypes      = executable.getActiveSamplerTypes();
265*8975f5c5SAndroid Build Coastguard Worker 
266*8975f5c5SAndroid Build Coastguard Worker     // Allocate VkWriteDescriptorSet and initialize the data structure
267*8975f5c5SAndroid Build Coastguard Worker     VkWriteDescriptorSet *writeDescriptorSets =
268*8975f5c5SAndroid Build Coastguard Worker         updateBuilder->allocWriteDescriptorSets(writeDescriptorDescs.size());
269*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t writeIndex = 0; writeIndex < writeDescriptorDescs.size(); ++writeIndex)
270*8975f5c5SAndroid Build Coastguard Worker     {
271*8975f5c5SAndroid Build Coastguard Worker         ASSERT(writeDescriptorDescs[writeIndex].descriptorCount > 0);
272*8975f5c5SAndroid Build Coastguard Worker 
273*8975f5c5SAndroid Build Coastguard Worker         VkWriteDescriptorSet &writeSet = writeDescriptorSets[writeIndex];
274*8975f5c5SAndroid Build Coastguard Worker         writeSet.descriptorCount       = writeDescriptorDescs[writeIndex].descriptorCount;
275*8975f5c5SAndroid Build Coastguard Worker         writeSet.descriptorType =
276*8975f5c5SAndroid Build Coastguard Worker             static_cast<VkDescriptorType>(writeDescriptorDescs[writeIndex].descriptorType);
277*8975f5c5SAndroid Build Coastguard Worker         writeSet.dstArrayElement  = 0;
278*8975f5c5SAndroid Build Coastguard Worker         writeSet.dstBinding       = writeIndex;
279*8975f5c5SAndroid Build Coastguard Worker         writeSet.dstSet           = descriptorSet;
280*8975f5c5SAndroid Build Coastguard Worker         writeSet.pBufferInfo      = nullptr;
281*8975f5c5SAndroid Build Coastguard Worker         writeSet.pImageInfo       = nullptr;
282*8975f5c5SAndroid Build Coastguard Worker         writeSet.pNext            = nullptr;
283*8975f5c5SAndroid Build Coastguard Worker         writeSet.pTexelBufferView = nullptr;
284*8975f5c5SAndroid Build Coastguard Worker         writeSet.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
285*8975f5c5SAndroid Build Coastguard Worker         // Always allocate VkDescriptorImageInfo. In less common case that descriptorType is
286*8975f5c5SAndroid Build Coastguard Worker         // VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, this will not used.
287*8975f5c5SAndroid Build Coastguard Worker         writeSet.pImageInfo = updateBuilder->allocDescriptorImageInfos(
288*8975f5c5SAndroid Build Coastguard Worker             writeDescriptorDescs[writeIndex].descriptorCount);
289*8975f5c5SAndroid Build Coastguard Worker     }
290*8975f5c5SAndroid Build Coastguard Worker 
291*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
292*8975f5c5SAndroid Build Coastguard Worker     {
293*8975f5c5SAndroid Build Coastguard Worker         uint32_t uniformIndex = executable.getUniformIndexFromSamplerIndex(samplerIndex);
294*8975f5c5SAndroid Build Coastguard Worker         const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
295*8975f5c5SAndroid Build Coastguard Worker         if (samplerUniform.activeShaders().none())
296*8975f5c5SAndroid Build Coastguard Worker         {
297*8975f5c5SAndroid Build Coastguard Worker             continue;
298*8975f5c5SAndroid Build Coastguard Worker         }
299*8975f5c5SAndroid Build Coastguard Worker 
300*8975f5c5SAndroid Build Coastguard Worker         const gl::ShaderType firstShaderType = samplerUniform.getFirstActiveShaderType();
301*8975f5c5SAndroid Build Coastguard Worker         const ShaderInterfaceVariableInfo &info =
302*8975f5c5SAndroid Build Coastguard Worker             variableInfoMap.getVariableById(firstShaderType, samplerUniform.getId(firstShaderType));
303*8975f5c5SAndroid Build Coastguard Worker 
304*8975f5c5SAndroid Build Coastguard Worker         const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
305*8975f5c5SAndroid Build Coastguard Worker         uint32_t arraySize = static_cast<uint32_t>(samplerBinding.textureUnitsCount);
306*8975f5c5SAndroid Build Coastguard Worker 
307*8975f5c5SAndroid Build Coastguard Worker         VkWriteDescriptorSet &writeSet = writeDescriptorSets[info.binding];
308*8975f5c5SAndroid Build Coastguard Worker         // Now fill pImageInfo or pTexelBufferView for writeSet
309*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
310*8975f5c5SAndroid Build Coastguard Worker         {
311*8975f5c5SAndroid Build Coastguard Worker             GLuint textureUnit =
312*8975f5c5SAndroid Build Coastguard Worker                 samplerBinding.getTextureUnit(samplerBoundTextureUnits, arrayElement);
313*8975f5c5SAndroid Build Coastguard Worker             TextureVk *textureVk = textures[textureUnit];
314*8975f5c5SAndroid Build Coastguard Worker 
315*8975f5c5SAndroid Build Coastguard Worker             if (textureTypes[textureUnit] == gl::TextureType::Buffer)
316*8975f5c5SAndroid Build Coastguard Worker             {
317*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(writeSet.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER);
318*8975f5c5SAndroid Build Coastguard Worker                 const vk::BufferView *view = nullptr;
319*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(
320*8975f5c5SAndroid Build Coastguard Worker                     textureVk->getBufferView(context, nullptr, &samplerBinding, false, &view));
321*8975f5c5SAndroid Build Coastguard Worker 
322*8975f5c5SAndroid Build Coastguard Worker                 VkBufferView &bufferView  = updateBuilder->allocBufferView();
323*8975f5c5SAndroid Build Coastguard Worker                 bufferView                = view->getHandle();
324*8975f5c5SAndroid Build Coastguard Worker                 writeSet.pTexelBufferView = &bufferView;
325*8975f5c5SAndroid Build Coastguard Worker             }
326*8975f5c5SAndroid Build Coastguard Worker             else
327*8975f5c5SAndroid Build Coastguard Worker             {
328*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(writeSet.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
329*8975f5c5SAndroid Build Coastguard Worker                 bool isSamplerExternalY2Y =
330*8975f5c5SAndroid Build Coastguard Worker                     samplerBinding.samplerType == GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
331*8975f5c5SAndroid Build Coastguard Worker                 gl::Sampler *sampler       = samplers[textureUnit].get();
332*8975f5c5SAndroid Build Coastguard Worker                 const SamplerVk *samplerVk = sampler ? vk::GetImpl(sampler) : nullptr;
333*8975f5c5SAndroid Build Coastguard Worker                 const vk::SamplerHelper &samplerHelper =
334*8975f5c5SAndroid Build Coastguard Worker                     samplerVk ? samplerVk->getSampler()
335*8975f5c5SAndroid Build Coastguard Worker                               : textureVk->getSampler(isSamplerExternalY2Y);
336*8975f5c5SAndroid Build Coastguard Worker                 const gl::SamplerState &samplerState =
337*8975f5c5SAndroid Build Coastguard Worker                     sampler ? sampler->getSamplerState() : textureVk->getState().getSamplerState();
338*8975f5c5SAndroid Build Coastguard Worker 
339*8975f5c5SAndroid Build Coastguard Worker                 vk::ImageLayout imageLayout    = textureVk->getImage().getCurrentImageLayout();
340*8975f5c5SAndroid Build Coastguard Worker                 const vk::ImageView &imageView = textureVk->getReadImageView(
341*8975f5c5SAndroid Build Coastguard Worker                     samplerState.getSRGBDecode(), samplerUniform.isTexelFetchStaticUse(),
342*8975f5c5SAndroid Build Coastguard Worker                     isSamplerExternalY2Y);
343*8975f5c5SAndroid Build Coastguard Worker 
344*8975f5c5SAndroid Build Coastguard Worker                 VkDescriptorImageInfo *imageInfo = const_cast<VkDescriptorImageInfo *>(
345*8975f5c5SAndroid Build Coastguard Worker                     &writeSet.pImageInfo[arrayElement + samplerUniform.getOuterArrayOffset()]);
346*8975f5c5SAndroid Build Coastguard Worker                 imageInfo->imageLayout = ConvertImageLayoutToVkImageLayout(renderer, imageLayout);
347*8975f5c5SAndroid Build Coastguard Worker                 imageInfo->imageView   = imageView.getHandle();
348*8975f5c5SAndroid Build Coastguard Worker                 imageInfo->sampler     = samplerHelper.get().getHandle();
349*8975f5c5SAndroid Build Coastguard Worker             }
350*8975f5c5SAndroid Build Coastguard Worker         }
351*8975f5c5SAndroid Build Coastguard Worker     }
352*8975f5c5SAndroid Build Coastguard Worker 
353*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
354*8975f5c5SAndroid Build Coastguard Worker }
355*8975f5c5SAndroid Build Coastguard Worker }  // namespace
356*8975f5c5SAndroid Build Coastguard Worker 
357*8975f5c5SAndroid Build Coastguard Worker class ProgramExecutableVk::WarmUpTaskCommon : public vk::Context, public LinkSubTask
358*8975f5c5SAndroid Build Coastguard Worker {
359*8975f5c5SAndroid Build Coastguard Worker   public:
WarmUpTaskCommon(vk::Renderer * renderer)360*8975f5c5SAndroid Build Coastguard Worker     WarmUpTaskCommon(vk::Renderer *renderer) : vk::Context(renderer) {}
WarmUpTaskCommon(vk::Renderer * renderer,ProgramExecutableVk * executableVk,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess)361*8975f5c5SAndroid Build Coastguard Worker     WarmUpTaskCommon(vk::Renderer *renderer,
362*8975f5c5SAndroid Build Coastguard Worker                      ProgramExecutableVk *executableVk,
363*8975f5c5SAndroid Build Coastguard Worker                      vk::PipelineRobustness pipelineRobustness,
364*8975f5c5SAndroid Build Coastguard Worker                      vk::PipelineProtectedAccess pipelineProtectedAccess)
365*8975f5c5SAndroid Build Coastguard Worker         : vk::Context(renderer),
366*8975f5c5SAndroid Build Coastguard Worker           mExecutableVk(executableVk),
367*8975f5c5SAndroid Build Coastguard Worker           mPipelineRobustness(pipelineRobustness),
368*8975f5c5SAndroid Build Coastguard Worker           mPipelineProtectedAccess(pipelineProtectedAccess)
369*8975f5c5SAndroid Build Coastguard Worker     {}
370*8975f5c5SAndroid Build Coastguard Worker     ~WarmUpTaskCommon() override = default;
371*8975f5c5SAndroid Build Coastguard Worker 
handleError(VkResult result,const char * file,const char * function,unsigned int line)372*8975f5c5SAndroid Build Coastguard Worker     void handleError(VkResult result,
373*8975f5c5SAndroid Build Coastguard Worker                      const char *file,
374*8975f5c5SAndroid Build Coastguard Worker                      const char *function,
375*8975f5c5SAndroid Build Coastguard Worker                      unsigned int line) override
376*8975f5c5SAndroid Build Coastguard Worker     {
377*8975f5c5SAndroid Build Coastguard Worker         mErrorCode     = result;
378*8975f5c5SAndroid Build Coastguard Worker         mErrorFile     = file;
379*8975f5c5SAndroid Build Coastguard Worker         mErrorFunction = function;
380*8975f5c5SAndroid Build Coastguard Worker         mErrorLine     = line;
381*8975f5c5SAndroid Build Coastguard Worker     }
382*8975f5c5SAndroid Build Coastguard Worker 
operator ()()383*8975f5c5SAndroid Build Coastguard Worker     void operator()() override { UNREACHABLE(); }
384*8975f5c5SAndroid Build Coastguard Worker 
getResult(const gl::Context * context,gl::InfoLog & infoLog)385*8975f5c5SAndroid Build Coastguard Worker     angle::Result getResult(const gl::Context *context, gl::InfoLog &infoLog) override
386*8975f5c5SAndroid Build Coastguard Worker     {
387*8975f5c5SAndroid Build Coastguard Worker         ContextVk *contextVk = vk::GetImpl(context);
388*8975f5c5SAndroid Build Coastguard Worker         return getResultImpl(contextVk, infoLog);
389*8975f5c5SAndroid Build Coastguard Worker     }
390*8975f5c5SAndroid Build Coastguard Worker 
getResultImpl(ContextVk * contextVk,gl::InfoLog & infoLog)391*8975f5c5SAndroid Build Coastguard Worker     angle::Result getResultImpl(ContextVk *contextVk, gl::InfoLog &infoLog)
392*8975f5c5SAndroid Build Coastguard Worker     {
393*8975f5c5SAndroid Build Coastguard Worker         // Forward any errors
394*8975f5c5SAndroid Build Coastguard Worker         if (mErrorCode != VK_SUCCESS)
395*8975f5c5SAndroid Build Coastguard Worker         {
396*8975f5c5SAndroid Build Coastguard Worker             contextVk->handleError(mErrorCode, mErrorFile, mErrorFunction, mErrorLine);
397*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
398*8975f5c5SAndroid Build Coastguard Worker         }
399*8975f5c5SAndroid Build Coastguard Worker 
400*8975f5c5SAndroid Build Coastguard Worker         // Accumulate relevant perf counters
401*8975f5c5SAndroid Build Coastguard Worker         const angle::VulkanPerfCounters &from = getPerfCounters();
402*8975f5c5SAndroid Build Coastguard Worker         angle::VulkanPerfCounters &to         = contextVk->getPerfCounters();
403*8975f5c5SAndroid Build Coastguard Worker 
404*8975f5c5SAndroid Build Coastguard Worker         to.pipelineCreationCacheHits += from.pipelineCreationCacheHits;
405*8975f5c5SAndroid Build Coastguard Worker         to.pipelineCreationCacheMisses += from.pipelineCreationCacheMisses;
406*8975f5c5SAndroid Build Coastguard Worker         to.pipelineCreationTotalCacheHitsDurationNs +=
407*8975f5c5SAndroid Build Coastguard Worker             from.pipelineCreationTotalCacheHitsDurationNs;
408*8975f5c5SAndroid Build Coastguard Worker         to.pipelineCreationTotalCacheMissesDurationNs +=
409*8975f5c5SAndroid Build Coastguard Worker             from.pipelineCreationTotalCacheMissesDurationNs;
410*8975f5c5SAndroid Build Coastguard Worker 
411*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
412*8975f5c5SAndroid Build Coastguard Worker     }
413*8975f5c5SAndroid Build Coastguard Worker 
414*8975f5c5SAndroid Build Coastguard Worker   protected:
mergeProgramExecutablePipelineCacheToRenderer()415*8975f5c5SAndroid Build Coastguard Worker     void mergeProgramExecutablePipelineCacheToRenderer()
416*8975f5c5SAndroid Build Coastguard Worker     {
417*8975f5c5SAndroid Build Coastguard Worker         angle::Result mergeResult = mExecutableVk->mergePipelineCacheToRenderer(this);
418*8975f5c5SAndroid Build Coastguard Worker 
419*8975f5c5SAndroid Build Coastguard Worker         // Treat error during merge as non fatal, log it and move on
420*8975f5c5SAndroid Build Coastguard Worker         if (mergeResult != angle::Result::Continue)
421*8975f5c5SAndroid Build Coastguard Worker         {
422*8975f5c5SAndroid Build Coastguard Worker             INFO() << "Error while merging to Renderer's pipeline cache";
423*8975f5c5SAndroid Build Coastguard Worker         }
424*8975f5c5SAndroid Build Coastguard Worker     }
425*8975f5c5SAndroid Build Coastguard Worker 
426*8975f5c5SAndroid Build Coastguard Worker     // The front-end ensures that the program is not modified while the subtask is running, so it is
427*8975f5c5SAndroid Build Coastguard Worker     // safe to directly access the executable from this parallel job.  Note that this is the reason
428*8975f5c5SAndroid Build Coastguard Worker     // why the front-end does not let the parallel job continue when a relink happens or the first
429*8975f5c5SAndroid Build Coastguard Worker     // draw with this program.
430*8975f5c5SAndroid Build Coastguard Worker     ProgramExecutableVk *mExecutableVk               = nullptr;
431*8975f5c5SAndroid Build Coastguard Worker     const vk::PipelineRobustness mPipelineRobustness = vk::PipelineRobustness::NonRobust;
432*8975f5c5SAndroid Build Coastguard Worker     const vk::PipelineProtectedAccess mPipelineProtectedAccess =
433*8975f5c5SAndroid Build Coastguard Worker         vk::PipelineProtectedAccess::Unprotected;
434*8975f5c5SAndroid Build Coastguard Worker 
435*8975f5c5SAndroid Build Coastguard Worker     // Error handling
436*8975f5c5SAndroid Build Coastguard Worker     VkResult mErrorCode        = VK_SUCCESS;
437*8975f5c5SAndroid Build Coastguard Worker     const char *mErrorFile     = nullptr;
438*8975f5c5SAndroid Build Coastguard Worker     const char *mErrorFunction = nullptr;
439*8975f5c5SAndroid Build Coastguard Worker     unsigned int mErrorLine    = 0;
440*8975f5c5SAndroid Build Coastguard Worker };
441*8975f5c5SAndroid Build Coastguard Worker 
442*8975f5c5SAndroid Build Coastguard Worker class ProgramExecutableVk::WarmUpComputeTask : public WarmUpTaskCommon
443*8975f5c5SAndroid Build Coastguard Worker {
444*8975f5c5SAndroid Build Coastguard Worker   public:
WarmUpComputeTask(vk::Renderer * renderer,ProgramExecutableVk * executableVk,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess)445*8975f5c5SAndroid Build Coastguard Worker     WarmUpComputeTask(vk::Renderer *renderer,
446*8975f5c5SAndroid Build Coastguard Worker                       ProgramExecutableVk *executableVk,
447*8975f5c5SAndroid Build Coastguard Worker                       vk::PipelineRobustness pipelineRobustness,
448*8975f5c5SAndroid Build Coastguard Worker                       vk::PipelineProtectedAccess pipelineProtectedAccess)
449*8975f5c5SAndroid Build Coastguard Worker         : WarmUpTaskCommon(renderer, executableVk, pipelineRobustness, pipelineProtectedAccess)
450*8975f5c5SAndroid Build Coastguard Worker     {}
451*8975f5c5SAndroid Build Coastguard Worker     ~WarmUpComputeTask() override = default;
452*8975f5c5SAndroid Build Coastguard Worker 
operator ()()453*8975f5c5SAndroid Build Coastguard Worker     void operator()() override
454*8975f5c5SAndroid Build Coastguard Worker     {
455*8975f5c5SAndroid Build Coastguard Worker         angle::Result result = mExecutableVk->warmUpComputePipelineCache(this, mPipelineRobustness,
456*8975f5c5SAndroid Build Coastguard Worker                                                                          mPipelineProtectedAccess);
457*8975f5c5SAndroid Build Coastguard Worker         ASSERT((result == angle::Result::Continue) == (mErrorCode == VK_SUCCESS));
458*8975f5c5SAndroid Build Coastguard Worker 
459*8975f5c5SAndroid Build Coastguard Worker         mergeProgramExecutablePipelineCacheToRenderer();
460*8975f5c5SAndroid Build Coastguard Worker     }
461*8975f5c5SAndroid Build Coastguard Worker };
462*8975f5c5SAndroid Build Coastguard Worker 
463*8975f5c5SAndroid Build Coastguard Worker using SharedRenderPass = vk::AtomicRefCounted<vk::RenderPass>;
464*8975f5c5SAndroid Build Coastguard Worker class ProgramExecutableVk::WarmUpGraphicsTask : public WarmUpTaskCommon
465*8975f5c5SAndroid Build Coastguard Worker {
466*8975f5c5SAndroid Build Coastguard Worker   public:
WarmUpGraphicsTask(vk::Renderer * renderer,ProgramExecutableVk * executableVk,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess,vk::GraphicsPipelineSubset subset,const bool isSurfaceRotated,const vk::GraphicsPipelineDesc & graphicsPipelineDesc,SharedRenderPass * compatibleRenderPass,vk::PipelineHelper * placeholderPipelineHelper)467*8975f5c5SAndroid Build Coastguard Worker     WarmUpGraphicsTask(vk::Renderer *renderer,
468*8975f5c5SAndroid Build Coastguard Worker                        ProgramExecutableVk *executableVk,
469*8975f5c5SAndroid Build Coastguard Worker                        vk::PipelineRobustness pipelineRobustness,
470*8975f5c5SAndroid Build Coastguard Worker                        vk::PipelineProtectedAccess pipelineProtectedAccess,
471*8975f5c5SAndroid Build Coastguard Worker                        vk::GraphicsPipelineSubset subset,
472*8975f5c5SAndroid Build Coastguard Worker                        const bool isSurfaceRotated,
473*8975f5c5SAndroid Build Coastguard Worker                        const vk::GraphicsPipelineDesc &graphicsPipelineDesc,
474*8975f5c5SAndroid Build Coastguard Worker                        SharedRenderPass *compatibleRenderPass,
475*8975f5c5SAndroid Build Coastguard Worker                        vk::PipelineHelper *placeholderPipelineHelper)
476*8975f5c5SAndroid Build Coastguard Worker         : WarmUpTaskCommon(renderer, executableVk, pipelineRobustness, pipelineProtectedAccess),
477*8975f5c5SAndroid Build Coastguard Worker           mPipelineSubset(subset),
478*8975f5c5SAndroid Build Coastguard Worker           mIsSurfaceRotated(isSurfaceRotated),
479*8975f5c5SAndroid Build Coastguard Worker           mGraphicsPipelineDesc(graphicsPipelineDesc),
480*8975f5c5SAndroid Build Coastguard Worker           mWarmUpPipelineHelper(placeholderPipelineHelper),
481*8975f5c5SAndroid Build Coastguard Worker           mCompatibleRenderPass(compatibleRenderPass)
482*8975f5c5SAndroid Build Coastguard Worker     {
483*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mCompatibleRenderPass);
484*8975f5c5SAndroid Build Coastguard Worker         mCompatibleRenderPass->addRef();
485*8975f5c5SAndroid Build Coastguard Worker     }
486*8975f5c5SAndroid Build Coastguard Worker     ~WarmUpGraphicsTask() override = default;
487*8975f5c5SAndroid Build Coastguard Worker 
operator ()()488*8975f5c5SAndroid Build Coastguard Worker     void operator()() override
489*8975f5c5SAndroid Build Coastguard Worker     {
490*8975f5c5SAndroid Build Coastguard Worker         angle::Result result = mExecutableVk->warmUpGraphicsPipelineCache(
491*8975f5c5SAndroid Build Coastguard Worker             this, mPipelineRobustness, mPipelineProtectedAccess, mPipelineSubset, mIsSurfaceRotated,
492*8975f5c5SAndroid Build Coastguard Worker             mGraphicsPipelineDesc, mCompatibleRenderPass->get(), mWarmUpPipelineHelper);
493*8975f5c5SAndroid Build Coastguard Worker         ASSERT((result == angle::Result::Continue) == (mErrorCode == VK_SUCCESS));
494*8975f5c5SAndroid Build Coastguard Worker 
495*8975f5c5SAndroid Build Coastguard Worker         // Release reference to shared renderpass. If this is the last reference -
496*8975f5c5SAndroid Build Coastguard Worker         // 1. merge ProgramExecutableVk's pipeline cache into the Renderer's cache
497*8975f5c5SAndroid Build Coastguard Worker         // 2. cleanup temporary renderpass
498*8975f5c5SAndroid Build Coastguard Worker         //
499*8975f5c5SAndroid Build Coastguard Worker         // Note: with dynamic rendering, |mCompatibleRenderPass| holds a VK_NULL_HANDLE, and it's
500*8975f5c5SAndroid Build Coastguard Worker         // just used as a ref count for this purpose.
501*8975f5c5SAndroid Build Coastguard Worker         const bool isLastWarmUpTask = mCompatibleRenderPass->getAndReleaseRef() == 1;
502*8975f5c5SAndroid Build Coastguard Worker         if (isLastWarmUpTask)
503*8975f5c5SAndroid Build Coastguard Worker         {
504*8975f5c5SAndroid Build Coastguard Worker             mergeProgramExecutablePipelineCacheToRenderer();
505*8975f5c5SAndroid Build Coastguard Worker 
506*8975f5c5SAndroid Build Coastguard Worker             mCompatibleRenderPass->get().destroy(getDevice());
507*8975f5c5SAndroid Build Coastguard Worker             SafeDelete(mCompatibleRenderPass);
508*8975f5c5SAndroid Build Coastguard Worker         }
509*8975f5c5SAndroid Build Coastguard Worker     }
510*8975f5c5SAndroid Build Coastguard Worker 
511*8975f5c5SAndroid Build Coastguard Worker   private:
512*8975f5c5SAndroid Build Coastguard Worker     vk::GraphicsPipelineSubset mPipelineSubset;
513*8975f5c5SAndroid Build Coastguard Worker     bool mIsSurfaceRotated;
514*8975f5c5SAndroid Build Coastguard Worker     vk::GraphicsPipelineDesc mGraphicsPipelineDesc;
515*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper *mWarmUpPipelineHelper;
516*8975f5c5SAndroid Build Coastguard Worker 
517*8975f5c5SAndroid Build Coastguard Worker     // Temporary objects to clean up at the end
518*8975f5c5SAndroid Build Coastguard Worker     SharedRenderPass *mCompatibleRenderPass;
519*8975f5c5SAndroid Build Coastguard Worker };
520*8975f5c5SAndroid Build Coastguard Worker 
521*8975f5c5SAndroid Build Coastguard Worker // ShaderInfo implementation.
ShaderInfo()522*8975f5c5SAndroid Build Coastguard Worker ShaderInfo::ShaderInfo() {}
523*8975f5c5SAndroid Build Coastguard Worker 
524*8975f5c5SAndroid Build Coastguard Worker ShaderInfo::~ShaderInfo() = default;
525*8975f5c5SAndroid Build Coastguard Worker 
initShaders(vk::Context * context,const gl::ShaderBitSet & linkedShaderStages,const gl::ShaderMap<const angle::spirv::Blob * > & spirvBlobs,const ShaderInterfaceVariableInfoMap & variableInfoMap,bool isGLES1)526*8975f5c5SAndroid Build Coastguard Worker angle::Result ShaderInfo::initShaders(vk::Context *context,
527*8975f5c5SAndroid Build Coastguard Worker                                       const gl::ShaderBitSet &linkedShaderStages,
528*8975f5c5SAndroid Build Coastguard Worker                                       const gl::ShaderMap<const angle::spirv::Blob *> &spirvBlobs,
529*8975f5c5SAndroid Build Coastguard Worker                                       const ShaderInterfaceVariableInfoMap &variableInfoMap,
530*8975f5c5SAndroid Build Coastguard Worker                                       bool isGLES1)
531*8975f5c5SAndroid Build Coastguard Worker {
532*8975f5c5SAndroid Build Coastguard Worker     clear();
533*8975f5c5SAndroid Build Coastguard Worker 
534*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : gl::AllShaderTypes())
535*8975f5c5SAndroid Build Coastguard Worker     {
536*8975f5c5SAndroid Build Coastguard Worker         if (spirvBlobs[shaderType] != nullptr)
537*8975f5c5SAndroid Build Coastguard Worker         {
538*8975f5c5SAndroid Build Coastguard Worker             mSpirvBlobs[shaderType] = *spirvBlobs[shaderType];
539*8975f5c5SAndroid Build Coastguard Worker         }
540*8975f5c5SAndroid Build Coastguard Worker     }
541*8975f5c5SAndroid Build Coastguard Worker 
542*8975f5c5SAndroid Build Coastguard Worker     // Assert that SPIR-V transformation is correct, even if the test never issues a draw call.
543*8975f5c5SAndroid Build Coastguard Worker     // Don't validate GLES1 programs because they are always created right before a draw, so they
544*8975f5c5SAndroid Build Coastguard Worker     // will naturally be validated.  This improves GLES1 test run times.
545*8975f5c5SAndroid Build Coastguard Worker     if (!isGLES1)
546*8975f5c5SAndroid Build Coastguard Worker     {
547*8975f5c5SAndroid Build Coastguard Worker         ASSERT(ValidateTransformedSpirV(context, linkedShaderStages, variableInfoMap, mSpirvBlobs));
548*8975f5c5SAndroid Build Coastguard Worker     }
549*8975f5c5SAndroid Build Coastguard Worker 
550*8975f5c5SAndroid Build Coastguard Worker     mIsInitialized = true;
551*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
552*8975f5c5SAndroid Build Coastguard Worker }
553*8975f5c5SAndroid Build Coastguard Worker 
initShaderFromProgram(gl::ShaderType shaderType,const ShaderInfo & programShaderInfo)554*8975f5c5SAndroid Build Coastguard Worker void ShaderInfo::initShaderFromProgram(gl::ShaderType shaderType,
555*8975f5c5SAndroid Build Coastguard Worker                                        const ShaderInfo &programShaderInfo)
556*8975f5c5SAndroid Build Coastguard Worker {
557*8975f5c5SAndroid Build Coastguard Worker     mSpirvBlobs[shaderType] = programShaderInfo.mSpirvBlobs[shaderType];
558*8975f5c5SAndroid Build Coastguard Worker     mIsInitialized          = true;
559*8975f5c5SAndroid Build Coastguard Worker }
560*8975f5c5SAndroid Build Coastguard Worker 
clear()561*8975f5c5SAndroid Build Coastguard Worker void ShaderInfo::clear()
562*8975f5c5SAndroid Build Coastguard Worker {
563*8975f5c5SAndroid Build Coastguard Worker     for (angle::spirv::Blob &spirvBlob : mSpirvBlobs)
564*8975f5c5SAndroid Build Coastguard Worker     {
565*8975f5c5SAndroid Build Coastguard Worker         spirvBlob.clear();
566*8975f5c5SAndroid Build Coastguard Worker     }
567*8975f5c5SAndroid Build Coastguard Worker     mIsInitialized = false;
568*8975f5c5SAndroid Build Coastguard Worker }
569*8975f5c5SAndroid Build Coastguard Worker 
load(gl::BinaryInputStream * stream)570*8975f5c5SAndroid Build Coastguard Worker void ShaderInfo::load(gl::BinaryInputStream *stream)
571*8975f5c5SAndroid Build Coastguard Worker {
572*8975f5c5SAndroid Build Coastguard Worker     clear();
573*8975f5c5SAndroid Build Coastguard Worker 
574*8975f5c5SAndroid Build Coastguard Worker     // Read in shader codes for all shader types
575*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : gl::AllShaderTypes())
576*8975f5c5SAndroid Build Coastguard Worker     {
577*8975f5c5SAndroid Build Coastguard Worker         stream->readVector(&mSpirvBlobs[shaderType]);
578*8975f5c5SAndroid Build Coastguard Worker     }
579*8975f5c5SAndroid Build Coastguard Worker 
580*8975f5c5SAndroid Build Coastguard Worker     mIsInitialized = true;
581*8975f5c5SAndroid Build Coastguard Worker }
582*8975f5c5SAndroid Build Coastguard Worker 
save(gl::BinaryOutputStream * stream)583*8975f5c5SAndroid Build Coastguard Worker void ShaderInfo::save(gl::BinaryOutputStream *stream)
584*8975f5c5SAndroid Build Coastguard Worker {
585*8975f5c5SAndroid Build Coastguard Worker     ASSERT(valid());
586*8975f5c5SAndroid Build Coastguard Worker 
587*8975f5c5SAndroid Build Coastguard Worker     // Write out shader codes for all shader types
588*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : gl::AllShaderTypes())
589*8975f5c5SAndroid Build Coastguard Worker     {
590*8975f5c5SAndroid Build Coastguard Worker         stream->writeVector(mSpirvBlobs[shaderType]);
591*8975f5c5SAndroid Build Coastguard Worker     }
592*8975f5c5SAndroid Build Coastguard Worker }
593*8975f5c5SAndroid Build Coastguard Worker 
594*8975f5c5SAndroid Build Coastguard Worker // ProgramInfo implementation.
ProgramInfo()595*8975f5c5SAndroid Build Coastguard Worker ProgramInfo::ProgramInfo() {}
596*8975f5c5SAndroid Build Coastguard Worker 
597*8975f5c5SAndroid Build Coastguard Worker ProgramInfo::~ProgramInfo() = default;
598*8975f5c5SAndroid Build Coastguard Worker 
initProgram(vk::Context * context,gl::ShaderType shaderType,bool isLastPreFragmentStage,bool isTransformFeedbackProgram,const ShaderInfo & shaderInfo,ProgramTransformOptions optionBits,const ShaderInterfaceVariableInfoMap & variableInfoMap)599*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramInfo::initProgram(vk::Context *context,
600*8975f5c5SAndroid Build Coastguard Worker                                        gl::ShaderType shaderType,
601*8975f5c5SAndroid Build Coastguard Worker                                        bool isLastPreFragmentStage,
602*8975f5c5SAndroid Build Coastguard Worker                                        bool isTransformFeedbackProgram,
603*8975f5c5SAndroid Build Coastguard Worker                                        const ShaderInfo &shaderInfo,
604*8975f5c5SAndroid Build Coastguard Worker                                        ProgramTransformOptions optionBits,
605*8975f5c5SAndroid Build Coastguard Worker                                        const ShaderInterfaceVariableInfoMap &variableInfoMap)
606*8975f5c5SAndroid Build Coastguard Worker {
607*8975f5c5SAndroid Build Coastguard Worker     const gl::ShaderMap<angle::spirv::Blob> &originalSpirvBlobs = shaderInfo.getSpirvBlobs();
608*8975f5c5SAndroid Build Coastguard Worker     const angle::spirv::Blob &originalSpirvBlob                 = originalSpirvBlobs[shaderType];
609*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderMap<angle::spirv::Blob> transformedSpirvBlobs;
610*8975f5c5SAndroid Build Coastguard Worker     angle::spirv::Blob &transformedSpirvBlob = transformedSpirvBlobs[shaderType];
611*8975f5c5SAndroid Build Coastguard Worker 
612*8975f5c5SAndroid Build Coastguard Worker     SpvTransformOptions options;
613*8975f5c5SAndroid Build Coastguard Worker     options.shaderType               = shaderType;
614*8975f5c5SAndroid Build Coastguard Worker     options.isLastPreFragmentStage   = isLastPreFragmentStage;
615*8975f5c5SAndroid Build Coastguard Worker     options.isTransformFeedbackStage = isLastPreFragmentStage && isTransformFeedbackProgram &&
616*8975f5c5SAndroid Build Coastguard Worker                                        !optionBits.removeTransformFeedbackEmulation;
617*8975f5c5SAndroid Build Coastguard Worker     options.isTransformFeedbackEmulated = context->getFeatures().emulateTransformFeedback.enabled;
618*8975f5c5SAndroid Build Coastguard Worker     options.isMultisampledFramebufferFetch =
619*8975f5c5SAndroid Build Coastguard Worker         optionBits.multiSampleFramebufferFetch && shaderType == gl::ShaderType::Fragment;
620*8975f5c5SAndroid Build Coastguard Worker     options.enableSampleShading = optionBits.enableSampleShading;
621*8975f5c5SAndroid Build Coastguard Worker 
622*8975f5c5SAndroid Build Coastguard Worker     options.useSpirvVaryingPrecisionFixer =
623*8975f5c5SAndroid Build Coastguard Worker         context->getFeatures().varyingsRequireMatchingPrecisionInSpirv.enabled;
624*8975f5c5SAndroid Build Coastguard Worker 
625*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(
626*8975f5c5SAndroid Build Coastguard Worker         SpvTransformSpirvCode(options, variableInfoMap, originalSpirvBlob, &transformedSpirvBlob));
627*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(vk::InitShaderModule(context, &mShaders[shaderType], transformedSpirvBlob.data(),
628*8975f5c5SAndroid Build Coastguard Worker                                    transformedSpirvBlob.size() * sizeof(uint32_t)));
629*8975f5c5SAndroid Build Coastguard Worker 
630*8975f5c5SAndroid Build Coastguard Worker     mProgramHelper.setShader(shaderType, mShaders[shaderType]);
631*8975f5c5SAndroid Build Coastguard Worker 
632*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
633*8975f5c5SAndroid Build Coastguard Worker }
634*8975f5c5SAndroid Build Coastguard Worker 
release(ContextVk * contextVk)635*8975f5c5SAndroid Build Coastguard Worker void ProgramInfo::release(ContextVk *contextVk)
636*8975f5c5SAndroid Build Coastguard Worker {
637*8975f5c5SAndroid Build Coastguard Worker     mProgramHelper.release(contextVk);
638*8975f5c5SAndroid Build Coastguard Worker 
639*8975f5c5SAndroid Build Coastguard Worker     for (vk::ShaderModulePtr &shader : mShaders)
640*8975f5c5SAndroid Build Coastguard Worker     {
641*8975f5c5SAndroid Build Coastguard Worker         shader.reset();
642*8975f5c5SAndroid Build Coastguard Worker     }
643*8975f5c5SAndroid Build Coastguard Worker }
644*8975f5c5SAndroid Build Coastguard Worker 
ProgramExecutableVk(const gl::ProgramExecutable * executable)645*8975f5c5SAndroid Build Coastguard Worker ProgramExecutableVk::ProgramExecutableVk(const gl::ProgramExecutable *executable)
646*8975f5c5SAndroid Build Coastguard Worker     : ProgramExecutableImpl(executable),
647*8975f5c5SAndroid Build Coastguard Worker       mImmutableSamplersMaxDescriptorCount(1),
648*8975f5c5SAndroid Build Coastguard Worker       mUniformBufferDescriptorType(VK_DESCRIPTOR_TYPE_MAX_ENUM),
649*8975f5c5SAndroid Build Coastguard Worker       mDynamicUniformDescriptorOffsets{},
650*8975f5c5SAndroid Build Coastguard Worker       mValidGraphicsPermutations{},
651*8975f5c5SAndroid Build Coastguard Worker       mValidComputePermutations{}
652*8975f5c5SAndroid Build Coastguard Worker {
653*8975f5c5SAndroid Build Coastguard Worker     for (std::shared_ptr<BufferAndLayout> &defaultBlock : mDefaultUniformBlocks)
654*8975f5c5SAndroid Build Coastguard Worker     {
655*8975f5c5SAndroid Build Coastguard Worker         defaultBlock = std::make_shared<BufferAndLayout>();
656*8975f5c5SAndroid Build Coastguard Worker     }
657*8975f5c5SAndroid Build Coastguard Worker }
658*8975f5c5SAndroid Build Coastguard Worker 
~ProgramExecutableVk()659*8975f5c5SAndroid Build Coastguard Worker ProgramExecutableVk::~ProgramExecutableVk()
660*8975f5c5SAndroid Build Coastguard Worker {
661*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mPipelineCache.valid());
662*8975f5c5SAndroid Build Coastguard Worker }
663*8975f5c5SAndroid Build Coastguard Worker 
destroy(const gl::Context * context)664*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::destroy(const gl::Context *context)
665*8975f5c5SAndroid Build Coastguard Worker {
666*8975f5c5SAndroid Build Coastguard Worker     reset(vk::GetImpl(context));
667*8975f5c5SAndroid Build Coastguard Worker }
668*8975f5c5SAndroid Build Coastguard Worker 
resetLayout(ContextVk * contextVk)669*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::resetLayout(ContextVk *contextVk)
670*8975f5c5SAndroid Build Coastguard Worker {
671*8975f5c5SAndroid Build Coastguard Worker     if (!mPipelineLayout)
672*8975f5c5SAndroid Build Coastguard Worker     {
673*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mValidGraphicsPermutations.none());
674*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mValidComputePermutations.none());
675*8975f5c5SAndroid Build Coastguard Worker         return;
676*8975f5c5SAndroid Build Coastguard Worker     }
677*8975f5c5SAndroid Build Coastguard Worker 
678*8975f5c5SAndroid Build Coastguard Worker     waitForPostLinkTasksImpl(contextVk);
679*8975f5c5SAndroid Build Coastguard Worker 
680*8975f5c5SAndroid Build Coastguard Worker     for (auto &descriptorSetLayout : mDescriptorSetLayouts)
681*8975f5c5SAndroid Build Coastguard Worker     {
682*8975f5c5SAndroid Build Coastguard Worker         descriptorSetLayout.reset();
683*8975f5c5SAndroid Build Coastguard Worker     }
684*8975f5c5SAndroid Build Coastguard Worker     mImmutableSamplersMaxDescriptorCount = 1;
685*8975f5c5SAndroid Build Coastguard Worker     mImmutableSamplerIndexMap.clear();
686*8975f5c5SAndroid Build Coastguard Worker 
687*8975f5c5SAndroid Build Coastguard Worker     for (vk::DescriptorSetPointer &descriptorSet : mDescriptorSets)
688*8975f5c5SAndroid Build Coastguard Worker     {
689*8975f5c5SAndroid Build Coastguard Worker         descriptorSet.reset();
690*8975f5c5SAndroid Build Coastguard Worker     }
691*8975f5c5SAndroid Build Coastguard Worker 
692*8975f5c5SAndroid Build Coastguard Worker     for (vk::DynamicDescriptorPoolPointer &pool : mDynamicDescriptorPools)
693*8975f5c5SAndroid Build Coastguard Worker     {
694*8975f5c5SAndroid Build Coastguard Worker         pool.reset();
695*8975f5c5SAndroid Build Coastguard Worker     }
696*8975f5c5SAndroid Build Coastguard Worker 
697*8975f5c5SAndroid Build Coastguard Worker     // Initialize with an invalid BufferSerial
698*8975f5c5SAndroid Build Coastguard Worker     mCurrentDefaultUniformBufferSerial = vk::BufferSerial();
699*8975f5c5SAndroid Build Coastguard Worker 
700*8975f5c5SAndroid Build Coastguard Worker     for (size_t index : mValidGraphicsPermutations)
701*8975f5c5SAndroid Build Coastguard Worker     {
702*8975f5c5SAndroid Build Coastguard Worker         mCompleteGraphicsPipelines[index].release(contextVk);
703*8975f5c5SAndroid Build Coastguard Worker         mShadersGraphicsPipelines[index].release(contextVk);
704*8975f5c5SAndroid Build Coastguard Worker 
705*8975f5c5SAndroid Build Coastguard Worker         // Program infos and pipeline layout must be released after pipelines are; they might be
706*8975f5c5SAndroid Build Coastguard Worker         // having pending jobs that are referencing them.
707*8975f5c5SAndroid Build Coastguard Worker         mGraphicsProgramInfos[index].release(contextVk);
708*8975f5c5SAndroid Build Coastguard Worker     }
709*8975f5c5SAndroid Build Coastguard Worker     mValidGraphicsPermutations.reset();
710*8975f5c5SAndroid Build Coastguard Worker 
711*8975f5c5SAndroid Build Coastguard Worker     for (size_t index : mValidComputePermutations)
712*8975f5c5SAndroid Build Coastguard Worker     {
713*8975f5c5SAndroid Build Coastguard Worker         mComputePipelines[index].release(contextVk);
714*8975f5c5SAndroid Build Coastguard Worker     }
715*8975f5c5SAndroid Build Coastguard Worker     mComputeProgramInfo.release(contextVk);
716*8975f5c5SAndroid Build Coastguard Worker     mValidComputePermutations.reset();
717*8975f5c5SAndroid Build Coastguard Worker 
718*8975f5c5SAndroid Build Coastguard Worker     mPipelineLayout.reset();
719*8975f5c5SAndroid Build Coastguard Worker 
720*8975f5c5SAndroid Build Coastguard Worker     contextVk->onProgramExecutableReset(this);
721*8975f5c5SAndroid Build Coastguard Worker }
722*8975f5c5SAndroid Build Coastguard Worker 
reset(ContextVk * contextVk)723*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::reset(ContextVk *contextVk)
724*8975f5c5SAndroid Build Coastguard Worker {
725*8975f5c5SAndroid Build Coastguard Worker     resetLayout(contextVk);
726*8975f5c5SAndroid Build Coastguard Worker 
727*8975f5c5SAndroid Build Coastguard Worker     if (mPipelineCache.valid())
728*8975f5c5SAndroid Build Coastguard Worker     {
729*8975f5c5SAndroid Build Coastguard Worker         mPipelineCache.destroy(contextVk->getDevice());
730*8975f5c5SAndroid Build Coastguard Worker     }
731*8975f5c5SAndroid Build Coastguard Worker }
732*8975f5c5SAndroid Build Coastguard Worker 
initializePipelineCache(vk::Context * context,bool compressed,const std::vector<uint8_t> & pipelineData)733*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::initializePipelineCache(vk::Context *context,
734*8975f5c5SAndroid Build Coastguard Worker                                                            bool compressed,
735*8975f5c5SAndroid Build Coastguard Worker                                                            const std::vector<uint8_t> &pipelineData)
736*8975f5c5SAndroid Build Coastguard Worker {
737*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mPipelineCache.valid());
738*8975f5c5SAndroid Build Coastguard Worker 
739*8975f5c5SAndroid Build Coastguard Worker     size_t dataSize            = pipelineData.size();
740*8975f5c5SAndroid Build Coastguard Worker     const uint8_t *dataPointer = pipelineData.data();
741*8975f5c5SAndroid Build Coastguard Worker 
742*8975f5c5SAndroid Build Coastguard Worker     angle::MemoryBuffer uncompressedData;
743*8975f5c5SAndroid Build Coastguard Worker     if (compressed)
744*8975f5c5SAndroid Build Coastguard Worker     {
745*8975f5c5SAndroid Build Coastguard Worker         if (!angle::DecompressBlob(dataPointer, dataSize, kMaxLocalPipelineCacheSize,
746*8975f5c5SAndroid Build Coastguard Worker                                    &uncompressedData))
747*8975f5c5SAndroid Build Coastguard Worker         {
748*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
749*8975f5c5SAndroid Build Coastguard Worker         }
750*8975f5c5SAndroid Build Coastguard Worker         dataSize    = uncompressedData.size();
751*8975f5c5SAndroid Build Coastguard Worker         dataPointer = uncompressedData.data();
752*8975f5c5SAndroid Build Coastguard Worker     }
753*8975f5c5SAndroid Build Coastguard Worker 
754*8975f5c5SAndroid Build Coastguard Worker     VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
755*8975f5c5SAndroid Build Coastguard Worker     pipelineCacheCreateInfo.sType           = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
756*8975f5c5SAndroid Build Coastguard Worker     pipelineCacheCreateInfo.initialDataSize = dataSize;
757*8975f5c5SAndroid Build Coastguard Worker     pipelineCacheCreateInfo.pInitialData    = dataPointer;
758*8975f5c5SAndroid Build Coastguard Worker 
759*8975f5c5SAndroid Build Coastguard Worker     ANGLE_VK_TRY(context, mPipelineCache.init(context->getDevice(), pipelineCacheCreateInfo));
760*8975f5c5SAndroid Build Coastguard Worker 
761*8975f5c5SAndroid Build Coastguard Worker     // Merge the pipeline cache into Renderer's.
762*8975f5c5SAndroid Build Coastguard Worker     if (context->getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled)
763*8975f5c5SAndroid Build Coastguard Worker     {
764*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(context->getRenderer()->mergeIntoPipelineCache(context, mPipelineCache));
765*8975f5c5SAndroid Build Coastguard Worker     }
766*8975f5c5SAndroid Build Coastguard Worker 
767*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
768*8975f5c5SAndroid Build Coastguard Worker }
769*8975f5c5SAndroid Build Coastguard Worker 
ensurePipelineCacheInitialized(vk::Context * context)770*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::ensurePipelineCacheInitialized(vk::Context *context)
771*8975f5c5SAndroid Build Coastguard Worker {
772*8975f5c5SAndroid Build Coastguard Worker     if (!mPipelineCache.valid())
773*8975f5c5SAndroid Build Coastguard Worker     {
774*8975f5c5SAndroid Build Coastguard Worker         VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
775*8975f5c5SAndroid Build Coastguard Worker         pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
776*8975f5c5SAndroid Build Coastguard Worker 
777*8975f5c5SAndroid Build Coastguard Worker         ANGLE_VK_TRY(context, mPipelineCache.init(context->getDevice(), pipelineCacheCreateInfo));
778*8975f5c5SAndroid Build Coastguard Worker     }
779*8975f5c5SAndroid Build Coastguard Worker 
780*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
781*8975f5c5SAndroid Build Coastguard Worker }
782*8975f5c5SAndroid Build Coastguard Worker 
load(ContextVk * contextVk,bool isSeparable,gl::BinaryInputStream * stream,egl::CacheGetResult * resultOut)783*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::load(ContextVk *contextVk,
784*8975f5c5SAndroid Build Coastguard Worker                                         bool isSeparable,
785*8975f5c5SAndroid Build Coastguard Worker                                         gl::BinaryInputStream *stream,
786*8975f5c5SAndroid Build Coastguard Worker                                         egl::CacheGetResult *resultOut)
787*8975f5c5SAndroid Build Coastguard Worker {
788*8975f5c5SAndroid Build Coastguard Worker     mVariableInfoMap.load(stream);
789*8975f5c5SAndroid Build Coastguard Worker     mOriginalShaderInfo.load(stream);
790*8975f5c5SAndroid Build Coastguard Worker 
791*8975f5c5SAndroid Build Coastguard Worker     // Deserializes the uniformLayout data of mDefaultUniformBlocks
792*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : gl::AllShaderTypes())
793*8975f5c5SAndroid Build Coastguard Worker     {
794*8975f5c5SAndroid Build Coastguard Worker         stream->readVector(&mDefaultUniformBlocks[shaderType]->uniformLayout);
795*8975f5c5SAndroid Build Coastguard Worker     }
796*8975f5c5SAndroid Build Coastguard Worker 
797*8975f5c5SAndroid Build Coastguard Worker     // Deserializes required uniform block memory sizes
798*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderMap<size_t> requiredBufferSize;
799*8975f5c5SAndroid Build Coastguard Worker     stream->readPackedEnumMap(&requiredBufferSize);
800*8975f5c5SAndroid Build Coastguard Worker 
801*8975f5c5SAndroid Build Coastguard Worker     if (!isSeparable)
802*8975f5c5SAndroid Build Coastguard Worker     {
803*8975f5c5SAndroid Build Coastguard Worker         size_t compressedPipelineDataSize = 0;
804*8975f5c5SAndroid Build Coastguard Worker         stream->readInt<size_t>(&compressedPipelineDataSize);
805*8975f5c5SAndroid Build Coastguard Worker 
806*8975f5c5SAndroid Build Coastguard Worker         std::vector<uint8_t> compressedPipelineData(compressedPipelineDataSize);
807*8975f5c5SAndroid Build Coastguard Worker         if (compressedPipelineDataSize > 0)
808*8975f5c5SAndroid Build Coastguard Worker         {
809*8975f5c5SAndroid Build Coastguard Worker             bool compressedData = false;
810*8975f5c5SAndroid Build Coastguard Worker             stream->readBool(&compressedData);
811*8975f5c5SAndroid Build Coastguard Worker             stream->readBytes(compressedPipelineData.data(), compressedPipelineDataSize);
812*8975f5c5SAndroid Build Coastguard Worker             // Initialize the pipeline cache based on cached data.
813*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(initializePipelineCache(contextVk, compressedData, compressedPipelineData));
814*8975f5c5SAndroid Build Coastguard Worker         }
815*8975f5c5SAndroid Build Coastguard Worker     }
816*8975f5c5SAndroid Build Coastguard Worker 
817*8975f5c5SAndroid Build Coastguard Worker     // Initialize and resize the mDefaultUniformBlocks' memory
818*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(resizeUniformBlockMemory(contextVk, requiredBufferSize));
819*8975f5c5SAndroid Build Coastguard Worker 
820*8975f5c5SAndroid Build Coastguard Worker     resetLayout(contextVk);
821*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(createPipelineLayout(contextVk, &contextVk->getPipelineLayoutCache(),
822*8975f5c5SAndroid Build Coastguard Worker                                    &contextVk->getDescriptorSetLayoutCache(), nullptr));
823*8975f5c5SAndroid Build Coastguard Worker 
824*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initializeDescriptorPools(contextVk, &contextVk->getDescriptorSetLayoutCache(),
825*8975f5c5SAndroid Build Coastguard Worker                                         &contextVk->getMetaDescriptorPools()));
826*8975f5c5SAndroid Build Coastguard Worker 
827*8975f5c5SAndroid Build Coastguard Worker     *resultOut = egl::CacheGetResult::Success;
828*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
829*8975f5c5SAndroid Build Coastguard Worker }
830*8975f5c5SAndroid Build Coastguard Worker 
save(ContextVk * contextVk,bool isSeparable,gl::BinaryOutputStream * stream)831*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::save(ContextVk *contextVk,
832*8975f5c5SAndroid Build Coastguard Worker                                bool isSeparable,
833*8975f5c5SAndroid Build Coastguard Worker                                gl::BinaryOutputStream *stream)
834*8975f5c5SAndroid Build Coastguard Worker {
835*8975f5c5SAndroid Build Coastguard Worker     mVariableInfoMap.save(stream);
836*8975f5c5SAndroid Build Coastguard Worker     mOriginalShaderInfo.save(stream);
837*8975f5c5SAndroid Build Coastguard Worker 
838*8975f5c5SAndroid Build Coastguard Worker     // Serializes the uniformLayout data of mDefaultUniformBlocks
839*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : gl::AllShaderTypes())
840*8975f5c5SAndroid Build Coastguard Worker     {
841*8975f5c5SAndroid Build Coastguard Worker         stream->writeVector(mDefaultUniformBlocks[shaderType]->uniformLayout);
842*8975f5c5SAndroid Build Coastguard Worker     }
843*8975f5c5SAndroid Build Coastguard Worker 
844*8975f5c5SAndroid Build Coastguard Worker     // Serializes required uniform block memory sizes
845*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderMap<size_t> uniformDataSize;
846*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : gl::AllShaderTypes())
847*8975f5c5SAndroid Build Coastguard Worker     {
848*8975f5c5SAndroid Build Coastguard Worker         uniformDataSize[shaderType] = mDefaultUniformBlocks[shaderType]->uniformData.size();
849*8975f5c5SAndroid Build Coastguard Worker     }
850*8975f5c5SAndroid Build Coastguard Worker     stream->writePackedEnumMap(uniformDataSize);
851*8975f5c5SAndroid Build Coastguard Worker 
852*8975f5c5SAndroid Build Coastguard Worker     // Need to wait for warm up tasks to complete.
853*8975f5c5SAndroid Build Coastguard Worker     waitForPostLinkTasksImpl(contextVk);
854*8975f5c5SAndroid Build Coastguard Worker 
855*8975f5c5SAndroid Build Coastguard Worker     // Compress and save mPipelineCache.  Separable programs don't warm up the cache, while program
856*8975f5c5SAndroid Build Coastguard Worker     // pipelines do.  However, currently ANGLE doesn't sync program pipelines to cache.  ANGLE could
857*8975f5c5SAndroid Build Coastguard Worker     // potentially use VK_EXT_graphics_pipeline_library to create separate pipelines for
858*8975f5c5SAndroid Build Coastguard Worker     // pre-rasterization and fragment subsets, but currently those subsets are bundled together.
859*8975f5c5SAndroid Build Coastguard Worker     if (!isSeparable)
860*8975f5c5SAndroid Build Coastguard Worker     {
861*8975f5c5SAndroid Build Coastguard Worker         angle::MemoryBuffer cacheData;
862*8975f5c5SAndroid Build Coastguard Worker 
863*8975f5c5SAndroid Build Coastguard Worker         GetPipelineCacheData(contextVk, mPipelineCache, &cacheData);
864*8975f5c5SAndroid Build Coastguard Worker         stream->writeInt(cacheData.size());
865*8975f5c5SAndroid Build Coastguard Worker         if (cacheData.size() > 0)
866*8975f5c5SAndroid Build Coastguard Worker         {
867*8975f5c5SAndroid Build Coastguard Worker             stream->writeBool(contextVk->getFeatures().enablePipelineCacheDataCompression.enabled);
868*8975f5c5SAndroid Build Coastguard Worker             stream->writeBytes(cacheData.data(), cacheData.size());
869*8975f5c5SAndroid Build Coastguard Worker         }
870*8975f5c5SAndroid Build Coastguard Worker     }
871*8975f5c5SAndroid Build Coastguard Worker }
872*8975f5c5SAndroid Build Coastguard Worker 
clearVariableInfoMap()873*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::clearVariableInfoMap()
874*8975f5c5SAndroid Build Coastguard Worker {
875*8975f5c5SAndroid Build Coastguard Worker     mVariableInfoMap.clear();
876*8975f5c5SAndroid Build Coastguard Worker }
877*8975f5c5SAndroid Build Coastguard Worker 
getPipelineCacheWarmUpTasks(vk::Renderer * renderer,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess,std::vector<std::shared_ptr<LinkSubTask>> * postLinkSubTasksOut)878*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::getPipelineCacheWarmUpTasks(
879*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer,
880*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineRobustness pipelineRobustness,
881*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineProtectedAccess pipelineProtectedAccess,
882*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<LinkSubTask>> *postLinkSubTasksOut)
883*8975f5c5SAndroid Build Coastguard Worker {
884*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!postLinkSubTasksOut || postLinkSubTasksOut->empty());
885*8975f5c5SAndroid Build Coastguard Worker 
886*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineSubset subset = GetWarmUpSubset(renderer->getFeatures());
887*8975f5c5SAndroid Build Coastguard Worker 
888*8975f5c5SAndroid Build Coastguard Worker     bool isCompute                                        = false;
889*8975f5c5SAndroid Build Coastguard Worker     angle::FixedVector<bool, 2> surfaceRotationVariations = {false};
890*8975f5c5SAndroid Build Coastguard Worker     vk::GraphicsPipelineDesc *graphicsPipelineDesc        = nullptr;
891*8975f5c5SAndroid Build Coastguard Worker     vk::RenderPass compatibleRenderPass;
892*8975f5c5SAndroid Build Coastguard Worker 
893*8975f5c5SAndroid Build Coastguard Worker     WarmUpTaskCommon prepForWarmUpContext(renderer);
894*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(prepareForWarmUpPipelineCache(
895*8975f5c5SAndroid Build Coastguard Worker         &prepForWarmUpContext, pipelineRobustness, pipelineProtectedAccess, subset, &isCompute,
896*8975f5c5SAndroid Build Coastguard Worker         &surfaceRotationVariations, &graphicsPipelineDesc, &compatibleRenderPass));
897*8975f5c5SAndroid Build Coastguard Worker 
898*8975f5c5SAndroid Build Coastguard Worker     std::vector<std::shared_ptr<rx::LinkSubTask>> warmUpSubTasks;
899*8975f5c5SAndroid Build Coastguard Worker     if (isCompute)
900*8975f5c5SAndroid Build Coastguard Worker     {
901*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!compatibleRenderPass.valid());
902*8975f5c5SAndroid Build Coastguard Worker 
903*8975f5c5SAndroid Build Coastguard Worker         warmUpSubTasks.push_back(std::make_shared<WarmUpComputeTask>(
904*8975f5c5SAndroid Build Coastguard Worker             renderer, this, pipelineRobustness, pipelineProtectedAccess));
905*8975f5c5SAndroid Build Coastguard Worker     }
906*8975f5c5SAndroid Build Coastguard Worker     else
907*8975f5c5SAndroid Build Coastguard Worker     {
908*8975f5c5SAndroid Build Coastguard Worker         ProgramTransformOptions transformOptions = {};
909*8975f5c5SAndroid Build Coastguard Worker         SharedRenderPass *sharedRenderPass = new SharedRenderPass(std::move(compatibleRenderPass));
910*8975f5c5SAndroid Build Coastguard Worker         for (bool surfaceRotation : surfaceRotationVariations)
911*8975f5c5SAndroid Build Coastguard Worker         {
912*8975f5c5SAndroid Build Coastguard Worker             // Add a placeholder entry in GraphicsPipelineCache
913*8975f5c5SAndroid Build Coastguard Worker             transformOptions.surfaceRotation   = surfaceRotation;
914*8975f5c5SAndroid Build Coastguard Worker             const uint8_t programIndex         = transformOptions.permutationIndex;
915*8975f5c5SAndroid Build Coastguard Worker             vk::PipelineHelper *pipelineHelper = nullptr;
916*8975f5c5SAndroid Build Coastguard Worker             if (subset == vk::GraphicsPipelineSubset::Complete)
917*8975f5c5SAndroid Build Coastguard Worker             {
918*8975f5c5SAndroid Build Coastguard Worker                 CompleteGraphicsPipelineCache &pipelines = mCompleteGraphicsPipelines[programIndex];
919*8975f5c5SAndroid Build Coastguard Worker                 pipelines.populate(mWarmUpGraphicsPipelineDesc, vk::Pipeline(), &pipelineHelper);
920*8975f5c5SAndroid Build Coastguard Worker             }
921*8975f5c5SAndroid Build Coastguard Worker             else
922*8975f5c5SAndroid Build Coastguard Worker             {
923*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(subset == vk::GraphicsPipelineSubset::Shaders);
924*8975f5c5SAndroid Build Coastguard Worker                 ShadersGraphicsPipelineCache &pipelines = mShadersGraphicsPipelines[programIndex];
925*8975f5c5SAndroid Build Coastguard Worker                 pipelines.populate(mWarmUpGraphicsPipelineDesc, vk::Pipeline(), &pipelineHelper);
926*8975f5c5SAndroid Build Coastguard Worker             }
927*8975f5c5SAndroid Build Coastguard Worker 
928*8975f5c5SAndroid Build Coastguard Worker             warmUpSubTasks.push_back(std::make_shared<WarmUpGraphicsTask>(
929*8975f5c5SAndroid Build Coastguard Worker                 renderer, this, pipelineRobustness, pipelineProtectedAccess, subset,
930*8975f5c5SAndroid Build Coastguard Worker                 surfaceRotation, *graphicsPipelineDesc, sharedRenderPass, pipelineHelper));
931*8975f5c5SAndroid Build Coastguard Worker         }
932*8975f5c5SAndroid Build Coastguard Worker     }
933*8975f5c5SAndroid Build Coastguard Worker 
934*8975f5c5SAndroid Build Coastguard Worker     // If the caller hasn't provided a valid async task container, inline the warmUp tasks.
935*8975f5c5SAndroid Build Coastguard Worker     if (postLinkSubTasksOut)
936*8975f5c5SAndroid Build Coastguard Worker     {
937*8975f5c5SAndroid Build Coastguard Worker         *postLinkSubTasksOut = std::move(warmUpSubTasks);
938*8975f5c5SAndroid Build Coastguard Worker     }
939*8975f5c5SAndroid Build Coastguard Worker     else
940*8975f5c5SAndroid Build Coastguard Worker     {
941*8975f5c5SAndroid Build Coastguard Worker         for (std::shared_ptr<rx::LinkSubTask> &task : warmUpSubTasks)
942*8975f5c5SAndroid Build Coastguard Worker         {
943*8975f5c5SAndroid Build Coastguard Worker             (*task)();
944*8975f5c5SAndroid Build Coastguard Worker         }
945*8975f5c5SAndroid Build Coastguard Worker         warmUpSubTasks.clear();
946*8975f5c5SAndroid Build Coastguard Worker     }
947*8975f5c5SAndroid Build Coastguard Worker 
948*8975f5c5SAndroid Build Coastguard Worker     ASSERT(warmUpSubTasks.empty());
949*8975f5c5SAndroid Build Coastguard Worker 
950*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
951*8975f5c5SAndroid Build Coastguard Worker }
952*8975f5c5SAndroid Build Coastguard Worker 
prepareForWarmUpPipelineCache(vk::Context * context,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess,vk::GraphicsPipelineSubset subset,bool * isComputeOut,angle::FixedVector<bool,2> * surfaceRotationVariationsOut,vk::GraphicsPipelineDesc ** graphicsPipelineDescOut,vk::RenderPass * renderPassOut)953*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::prepareForWarmUpPipelineCache(
954*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
955*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineRobustness pipelineRobustness,
956*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineProtectedAccess pipelineProtectedAccess,
957*8975f5c5SAndroid Build Coastguard Worker     vk::GraphicsPipelineSubset subset,
958*8975f5c5SAndroid Build Coastguard Worker     bool *isComputeOut,
959*8975f5c5SAndroid Build Coastguard Worker     angle::FixedVector<bool, 2> *surfaceRotationVariationsOut,
960*8975f5c5SAndroid Build Coastguard Worker     vk::GraphicsPipelineDesc **graphicsPipelineDescOut,
961*8975f5c5SAndroid Build Coastguard Worker     vk::RenderPass *renderPassOut)
962*8975f5c5SAndroid Build Coastguard Worker {
963*8975f5c5SAndroid Build Coastguard Worker     ASSERT(isComputeOut);
964*8975f5c5SAndroid Build Coastguard Worker     ASSERT(surfaceRotationVariationsOut);
965*8975f5c5SAndroid Build Coastguard Worker     ASSERT(graphicsPipelineDescOut);
966*8975f5c5SAndroid Build Coastguard Worker     ASSERT(renderPassOut);
967*8975f5c5SAndroid Build Coastguard Worker     ASSERT(context->getFeatures().warmUpPipelineCacheAtLink.enabled);
968*8975f5c5SAndroid Build Coastguard Worker 
969*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(ensurePipelineCacheInitialized(context));
970*8975f5c5SAndroid Build Coastguard Worker 
971*8975f5c5SAndroid Build Coastguard Worker     *isComputeOut        = false;
972*8975f5c5SAndroid Build Coastguard Worker     const bool isCompute = mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute);
973*8975f5c5SAndroid Build Coastguard Worker     if (isCompute)
974*8975f5c5SAndroid Build Coastguard Worker     {
975*8975f5c5SAndroid Build Coastguard Worker         // Initialize compute program.
976*8975f5c5SAndroid Build Coastguard Worker         vk::ComputePipelineOptions pipelineOptions =
977*8975f5c5SAndroid Build Coastguard Worker             vk::GetComputePipelineOptions(pipelineRobustness, pipelineProtectedAccess);
978*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(
979*8975f5c5SAndroid Build Coastguard Worker             initComputeProgram(context, &mComputeProgramInfo, mVariableInfoMap, pipelineOptions));
980*8975f5c5SAndroid Build Coastguard Worker 
981*8975f5c5SAndroid Build Coastguard Worker         *isComputeOut = true;
982*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
983*8975f5c5SAndroid Build Coastguard Worker     }
984*8975f5c5SAndroid Build Coastguard Worker 
985*8975f5c5SAndroid Build Coastguard Worker     // It is only at drawcall time that we will have complete information required to build the
986*8975f5c5SAndroid Build Coastguard Worker     // graphics pipeline descriptor. Use the most "commonly seen" state values and create the
987*8975f5c5SAndroid Build Coastguard Worker     // pipeline.
988*8975f5c5SAndroid Build Coastguard Worker     gl::PrimitiveMode mode = (mExecutable->hasLinkedShaderStage(gl::ShaderType::TessControl) ||
989*8975f5c5SAndroid Build Coastguard Worker                               mExecutable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
990*8975f5c5SAndroid Build Coastguard Worker                                  ? gl::PrimitiveMode::Patches
991*8975f5c5SAndroid Build Coastguard Worker                                  : gl::PrimitiveMode::TriangleStrip;
992*8975f5c5SAndroid Build Coastguard Worker     SetupDefaultPipelineState(context, *mExecutable, mode, pipelineRobustness,
993*8975f5c5SAndroid Build Coastguard Worker                               pipelineProtectedAccess, subset, &mWarmUpGraphicsPipelineDesc);
994*8975f5c5SAndroid Build Coastguard Worker 
995*8975f5c5SAndroid Build Coastguard Worker     // Create a temporary compatible RenderPass.  The render pass cache in ContextVk cannot be used
996*8975f5c5SAndroid Build Coastguard Worker     // because this function may be called from a worker thread.
997*8975f5c5SAndroid Build Coastguard Worker     vk::AttachmentOpsArray ops;
998*8975f5c5SAndroid Build Coastguard Worker     RenderPassCache::InitializeOpsForCompatibleRenderPass(
999*8975f5c5SAndroid Build Coastguard Worker         mWarmUpGraphicsPipelineDesc.getRenderPassDesc(), &ops);
1000*8975f5c5SAndroid Build Coastguard Worker     if (!context->getFeatures().preferDynamicRendering.enabled)
1001*8975f5c5SAndroid Build Coastguard Worker     {
1002*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(RenderPassCache::MakeRenderPass(
1003*8975f5c5SAndroid Build Coastguard Worker             context, mWarmUpGraphicsPipelineDesc.getRenderPassDesc(), ops, renderPassOut, nullptr));
1004*8975f5c5SAndroid Build Coastguard Worker     }
1005*8975f5c5SAndroid Build Coastguard Worker 
1006*8975f5c5SAndroid Build Coastguard Worker     *graphicsPipelineDescOut = &mWarmUpGraphicsPipelineDesc;
1007*8975f5c5SAndroid Build Coastguard Worker 
1008*8975f5c5SAndroid Build Coastguard Worker     // Variations that definitely matter:
1009*8975f5c5SAndroid Build Coastguard Worker     //
1010*8975f5c5SAndroid Build Coastguard Worker     // - PreRotation: It's a boolean specialization constant
1011*8975f5c5SAndroid Build Coastguard Worker     // - Depth correction: It's a SPIR-V transformation
1012*8975f5c5SAndroid Build Coastguard Worker     //
1013*8975f5c5SAndroid Build Coastguard Worker     // There are a number of states that are not currently dynamic (and may never be, such as sample
1014*8975f5c5SAndroid Build Coastguard Worker     // shading), but pre-creating shaders for them is impractical.  Most such state is likely unused
1015*8975f5c5SAndroid Build Coastguard Worker     // by most applications, but variations can be added here for certain apps that are known to
1016*8975f5c5SAndroid Build Coastguard Worker     // benefit from it.
1017*8975f5c5SAndroid Build Coastguard Worker     *surfaceRotationVariationsOut = {false};
1018*8975f5c5SAndroid Build Coastguard Worker     if (context->getFeatures().enablePreRotateSurfaces.enabled &&
1019*8975f5c5SAndroid Build Coastguard Worker         !context->getFeatures().preferDriverUniformOverSpecConst.enabled)
1020*8975f5c5SAndroid Build Coastguard Worker     {
1021*8975f5c5SAndroid Build Coastguard Worker         surfaceRotationVariationsOut->push_back(true);
1022*8975f5c5SAndroid Build Coastguard Worker     }
1023*8975f5c5SAndroid Build Coastguard Worker 
1024*8975f5c5SAndroid Build Coastguard Worker     ProgramTransformOptions transformOptions = {};
1025*8975f5c5SAndroid Build Coastguard Worker     for (bool rotation : *surfaceRotationVariationsOut)
1026*8975f5c5SAndroid Build Coastguard Worker     {
1027*8975f5c5SAndroid Build Coastguard Worker         // Initialize graphics programs.
1028*8975f5c5SAndroid Build Coastguard Worker         transformOptions.surfaceRotation = rotation;
1029*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(initGraphicsShaderPrograms(context, transformOptions));
1030*8975f5c5SAndroid Build Coastguard Worker     }
1031*8975f5c5SAndroid Build Coastguard Worker 
1032*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1033*8975f5c5SAndroid Build Coastguard Worker }
1034*8975f5c5SAndroid Build Coastguard Worker 
warmUpComputePipelineCache(vk::Context * context,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess)1035*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::warmUpComputePipelineCache(
1036*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1037*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineRobustness pipelineRobustness,
1038*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineProtectedAccess pipelineProtectedAccess)
1039*8975f5c5SAndroid Build Coastguard Worker {
1040*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ProgramExecutableVk::warmUpComputePipelineCache");
1041*8975f5c5SAndroid Build Coastguard Worker 
1042*8975f5c5SAndroid Build Coastguard Worker     // This method assumes that all the state necessary to create a compute pipeline has already
1043*8975f5c5SAndroid Build Coastguard Worker     // been setup by the caller. Assert that all required state is valid so all that is left will
1044*8975f5c5SAndroid Build Coastguard Worker     // be the call to `vkCreateComputePipelines`
1045*8975f5c5SAndroid Build Coastguard Worker 
1046*8975f5c5SAndroid Build Coastguard Worker     // Make sure the shader module for compute shader stage is valid.
1047*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mComputeProgramInfo.valid(gl::ShaderType::Compute));
1048*8975f5c5SAndroid Build Coastguard Worker 
1049*8975f5c5SAndroid Build Coastguard Worker     // No synchronization necessary since mPipelineCache is internally synchronized.
1050*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineCacheAccess pipelineCache;
1051*8975f5c5SAndroid Build Coastguard Worker     pipelineCache.init(&mPipelineCache, nullptr);
1052*8975f5c5SAndroid Build Coastguard Worker 
1053*8975f5c5SAndroid Build Coastguard Worker     // There is no state associated with compute programs, so only one pipeline needs creation
1054*8975f5c5SAndroid Build Coastguard Worker     // to warm up the cache.
1055*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper *pipeline = nullptr;
1056*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getOrCreateComputePipeline(context, &pipelineCache, PipelineSource::WarmUp,
1057*8975f5c5SAndroid Build Coastguard Worker                                          pipelineRobustness, pipelineProtectedAccess, &pipeline));
1058*8975f5c5SAndroid Build Coastguard Worker 
1059*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1060*8975f5c5SAndroid Build Coastguard Worker }
1061*8975f5c5SAndroid Build Coastguard Worker 
warmUpGraphicsPipelineCache(vk::Context * context,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess,vk::GraphicsPipelineSubset subset,const bool isSurfaceRotated,const vk::GraphicsPipelineDesc & graphicsPipelineDesc,const vk::RenderPass & renderPass,vk::PipelineHelper * placeholderPipelineHelper)1062*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::warmUpGraphicsPipelineCache(
1063*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1064*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineRobustness pipelineRobustness,
1065*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineProtectedAccess pipelineProtectedAccess,
1066*8975f5c5SAndroid Build Coastguard Worker     vk::GraphicsPipelineSubset subset,
1067*8975f5c5SAndroid Build Coastguard Worker     const bool isSurfaceRotated,
1068*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc &graphicsPipelineDesc,
1069*8975f5c5SAndroid Build Coastguard Worker     const vk::RenderPass &renderPass,
1070*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper *placeholderPipelineHelper)
1071*8975f5c5SAndroid Build Coastguard Worker {
1072*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRACE_EVENT0("gpu.angle", "ProgramExecutableVk::warmUpGraphicsPipelineCache");
1073*8975f5c5SAndroid Build Coastguard Worker 
1074*8975f5c5SAndroid Build Coastguard Worker     ASSERT(placeholderPipelineHelper && !placeholderPipelineHelper->valid());
1075*8975f5c5SAndroid Build Coastguard Worker 
1076*8975f5c5SAndroid Build Coastguard Worker     // No synchronization necessary since mPipelineCache is internally synchronized.
1077*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineCacheAccess pipelineCache;
1078*8975f5c5SAndroid Build Coastguard Worker     pipelineCache.init(&mPipelineCache, nullptr);
1079*8975f5c5SAndroid Build Coastguard Worker 
1080*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc *descPtr  = nullptr;
1081*8975f5c5SAndroid Build Coastguard Worker     ProgramTransformOptions transformOptions = {};
1082*8975f5c5SAndroid Build Coastguard Worker     transformOptions.surfaceRotation         = isSurfaceRotated;
1083*8975f5c5SAndroid Build Coastguard Worker 
1084*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(createGraphicsPipelineImpl(context, transformOptions, subset, &pipelineCache,
1085*8975f5c5SAndroid Build Coastguard Worker                                          PipelineSource::WarmUp, graphicsPipelineDesc, renderPass,
1086*8975f5c5SAndroid Build Coastguard Worker                                          &descPtr, &placeholderPipelineHelper));
1087*8975f5c5SAndroid Build Coastguard Worker 
1088*8975f5c5SAndroid Build Coastguard Worker     ASSERT(placeholderPipelineHelper->valid());
1089*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1090*8975f5c5SAndroid Build Coastguard Worker }
1091*8975f5c5SAndroid Build Coastguard Worker 
waitForPostLinkTasksImpl(ContextVk * contextVk)1092*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::waitForPostLinkTasksImpl(ContextVk *contextVk)
1093*8975f5c5SAndroid Build Coastguard Worker {
1094*8975f5c5SAndroid Build Coastguard Worker     const std::vector<std::shared_ptr<rx::LinkSubTask>> &postLinkSubTasks =
1095*8975f5c5SAndroid Build Coastguard Worker         mExecutable->getPostLinkSubTasks();
1096*8975f5c5SAndroid Build Coastguard Worker 
1097*8975f5c5SAndroid Build Coastguard Worker     if (postLinkSubTasks.empty())
1098*8975f5c5SAndroid Build Coastguard Worker     {
1099*8975f5c5SAndroid Build Coastguard Worker         return;
1100*8975f5c5SAndroid Build Coastguard Worker     }
1101*8975f5c5SAndroid Build Coastguard Worker 
1102*8975f5c5SAndroid Build Coastguard Worker     // Wait for all post-link tasks to finish
1103*8975f5c5SAndroid Build Coastguard Worker     angle::WaitableEvent::WaitMany(&mExecutable->getPostLinkSubTaskWaitableEvents());
1104*8975f5c5SAndroid Build Coastguard Worker 
1105*8975f5c5SAndroid Build Coastguard Worker     // Get results and clean up
1106*8975f5c5SAndroid Build Coastguard Worker     for (const std::shared_ptr<rx::LinkSubTask> &task : postLinkSubTasks)
1107*8975f5c5SAndroid Build Coastguard Worker     {
1108*8975f5c5SAndroid Build Coastguard Worker         WarmUpTaskCommon *warmUpTask = static_cast<WarmUpTaskCommon *>(task.get());
1109*8975f5c5SAndroid Build Coastguard Worker 
1110*8975f5c5SAndroid Build Coastguard Worker         // As these tasks can be run post-link, their results are ignored.  Failure is harmless, but
1111*8975f5c5SAndroid Build Coastguard Worker         // more importantly the error (effectively due to a link event) may not be allowed through
1112*8975f5c5SAndroid Build Coastguard Worker         // the entry point that results in this call.
1113*8975f5c5SAndroid Build Coastguard Worker         gl::InfoLog infoLog;
1114*8975f5c5SAndroid Build Coastguard Worker         angle::Result result = warmUpTask->getResultImpl(contextVk, infoLog);
1115*8975f5c5SAndroid Build Coastguard Worker         if (result != angle::Result::Continue)
1116*8975f5c5SAndroid Build Coastguard Worker         {
1117*8975f5c5SAndroid Build Coastguard Worker             ANGLE_PERF_WARNING(contextVk->getDebug(), GL_DEBUG_SEVERITY_LOW,
1118*8975f5c5SAndroid Build Coastguard Worker                                "Post-link task unexpectedly failed. Performance may degrade, or "
1119*8975f5c5SAndroid Build Coastguard Worker                                "device may soon be lost");
1120*8975f5c5SAndroid Build Coastguard Worker         }
1121*8975f5c5SAndroid Build Coastguard Worker     }
1122*8975f5c5SAndroid Build Coastguard Worker 
1123*8975f5c5SAndroid Build Coastguard Worker     mExecutable->onPostLinkTasksComplete();
1124*8975f5c5SAndroid Build Coastguard Worker }
1125*8975f5c5SAndroid Build Coastguard Worker 
waitForGraphicsPostLinkTasks(ContextVk * contextVk,const vk::GraphicsPipelineDesc & currentGraphicsPipelineDesc)1126*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::waitForGraphicsPostLinkTasks(
1127*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk,
1128*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc &currentGraphicsPipelineDesc)
1129*8975f5c5SAndroid Build Coastguard Worker {
1130*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex));
1131*8975f5c5SAndroid Build Coastguard Worker 
1132*8975f5c5SAndroid Build Coastguard Worker     if (mExecutable->getPostLinkSubTasks().empty())
1133*8975f5c5SAndroid Build Coastguard Worker     {
1134*8975f5c5SAndroid Build Coastguard Worker         return;
1135*8975f5c5SAndroid Build Coastguard Worker     }
1136*8975f5c5SAndroid Build Coastguard Worker 
1137*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineSubset subset = GetWarmUpSubset(contextVk->getFeatures());
1138*8975f5c5SAndroid Build Coastguard Worker 
1139*8975f5c5SAndroid Build Coastguard Worker     if (!mWarmUpGraphicsPipelineDesc.keyEqual(currentGraphicsPipelineDesc, subset))
1140*8975f5c5SAndroid Build Coastguard Worker     {
1141*8975f5c5SAndroid Build Coastguard Worker         // The GraphicsPipelineDesc used for warmup differs from the one used by the draw call.
1142*8975f5c5SAndroid Build Coastguard Worker         // There is no need to wait for the warmup tasks to complete.
1143*8975f5c5SAndroid Build Coastguard Worker         ANGLE_PERF_WARNING(
1144*8975f5c5SAndroid Build Coastguard Worker             contextVk->getDebug(), GL_DEBUG_SEVERITY_LOW,
1145*8975f5c5SAndroid Build Coastguard Worker             "GraphicsPipelineDesc used for warmup differs from the one used by draw.");
1146*8975f5c5SAndroid Build Coastguard Worker 
1147*8975f5c5SAndroid Build Coastguard Worker         // If the warm up tasks are finished anyway, let |waitForPostLinkTasksImpl| clean them up.
1148*8975f5c5SAndroid Build Coastguard Worker         if (!angle::WaitableEvent::AllReady(&mExecutable->getPostLinkSubTaskWaitableEvents()))
1149*8975f5c5SAndroid Build Coastguard Worker         {
1150*8975f5c5SAndroid Build Coastguard Worker             return;
1151*8975f5c5SAndroid Build Coastguard Worker         }
1152*8975f5c5SAndroid Build Coastguard Worker     }
1153*8975f5c5SAndroid Build Coastguard Worker 
1154*8975f5c5SAndroid Build Coastguard Worker     waitForPostLinkTasksImpl(contextVk);
1155*8975f5c5SAndroid Build Coastguard Worker }
1156*8975f5c5SAndroid Build Coastguard Worker 
mergePipelineCacheToRenderer(vk::Context * context) const1157*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::mergePipelineCacheToRenderer(vk::Context *context) const
1158*8975f5c5SAndroid Build Coastguard Worker {
1159*8975f5c5SAndroid Build Coastguard Worker     // Merge the cache with Renderer's
1160*8975f5c5SAndroid Build Coastguard Worker     if (context->getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled)
1161*8975f5c5SAndroid Build Coastguard Worker     {
1162*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRACE_EVENT0("gpu.angle", "ProgramExecutableVk::mergePipelineCacheToRenderer");
1163*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(context->getRenderer()->mergeIntoPipelineCache(context, mPipelineCache));
1164*8975f5c5SAndroid Build Coastguard Worker     }
1165*8975f5c5SAndroid Build Coastguard Worker 
1166*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1167*8975f5c5SAndroid Build Coastguard Worker }
1168*8975f5c5SAndroid Build Coastguard Worker 
addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> & blocks,gl::ShaderBitSet shaderTypes,VkDescriptorType descType,vk::DescriptorSetLayoutDesc * descOut)1169*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::addInterfaceBlockDescriptorSetDesc(
1170*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::InterfaceBlock> &blocks,
1171*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderBitSet shaderTypes,
1172*8975f5c5SAndroid Build Coastguard Worker     VkDescriptorType descType,
1173*8975f5c5SAndroid Build Coastguard Worker     vk::DescriptorSetLayoutDesc *descOut)
1174*8975f5c5SAndroid Build Coastguard Worker {
1175*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t bufferIndex = 0, arraySize = 0; bufferIndex < blocks.size();
1176*8975f5c5SAndroid Build Coastguard Worker          bufferIndex += arraySize)
1177*8975f5c5SAndroid Build Coastguard Worker     {
1178*8975f5c5SAndroid Build Coastguard Worker         gl::InterfaceBlock block = blocks[bufferIndex];
1179*8975f5c5SAndroid Build Coastguard Worker         arraySize                = GetInterfaceBlockArraySize(blocks, bufferIndex);
1180*8975f5c5SAndroid Build Coastguard Worker 
1181*8975f5c5SAndroid Build Coastguard Worker         if (block.activeShaders().none())
1182*8975f5c5SAndroid Build Coastguard Worker         {
1183*8975f5c5SAndroid Build Coastguard Worker             continue;
1184*8975f5c5SAndroid Build Coastguard Worker         }
1185*8975f5c5SAndroid Build Coastguard Worker 
1186*8975f5c5SAndroid Build Coastguard Worker         const gl::ShaderType firstShaderType = block.getFirstActiveShaderType();
1187*8975f5c5SAndroid Build Coastguard Worker         const ShaderInterfaceVariableInfo &info =
1188*8975f5c5SAndroid Build Coastguard Worker             mVariableInfoMap.getVariableById(firstShaderType, block.getId(firstShaderType));
1189*8975f5c5SAndroid Build Coastguard Worker 
1190*8975f5c5SAndroid Build Coastguard Worker         const VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
1191*8975f5c5SAndroid Build Coastguard Worker 
1192*8975f5c5SAndroid Build Coastguard Worker         descOut->addBinding(info.binding, descType, arraySize, activeStages, nullptr);
1193*8975f5c5SAndroid Build Coastguard Worker     }
1194*8975f5c5SAndroid Build Coastguard Worker }
1195*8975f5c5SAndroid Build Coastguard Worker 
addAtomicCounterBufferDescriptorSetDesc(const std::vector<gl::AtomicCounterBuffer> & atomicCounterBuffers,vk::DescriptorSetLayoutDesc * descOut)1196*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::addAtomicCounterBufferDescriptorSetDesc(
1197*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
1198*8975f5c5SAndroid Build Coastguard Worker     vk::DescriptorSetLayoutDesc *descOut)
1199*8975f5c5SAndroid Build Coastguard Worker {
1200*8975f5c5SAndroid Build Coastguard Worker     if (atomicCounterBuffers.empty())
1201*8975f5c5SAndroid Build Coastguard Worker     {
1202*8975f5c5SAndroid Build Coastguard Worker         return;
1203*8975f5c5SAndroid Build Coastguard Worker     }
1204*8975f5c5SAndroid Build Coastguard Worker 
1205*8975f5c5SAndroid Build Coastguard Worker     const ShaderInterfaceVariableInfo &info =
1206*8975f5c5SAndroid Build Coastguard Worker         mVariableInfoMap.getAtomicCounterInfo(atomicCounterBuffers[0].getFirstActiveShaderType());
1207*8975f5c5SAndroid Build Coastguard Worker     VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
1208*8975f5c5SAndroid Build Coastguard Worker 
1209*8975f5c5SAndroid Build Coastguard Worker     // A single storage buffer array is used for all stages for simplicity.
1210*8975f5c5SAndroid Build Coastguard Worker     descOut->addBinding(info.binding, vk::kStorageBufferDescriptorType,
1211*8975f5c5SAndroid Build Coastguard Worker                         gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, activeStages,
1212*8975f5c5SAndroid Build Coastguard Worker                         nullptr);
1213*8975f5c5SAndroid Build Coastguard Worker }
1214*8975f5c5SAndroid Build Coastguard Worker 
addImageDescriptorSetDesc(vk::DescriptorSetLayoutDesc * descOut)1215*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::addImageDescriptorSetDesc(vk::DescriptorSetLayoutDesc *descOut)
1216*8975f5c5SAndroid Build Coastguard Worker {
1217*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::ImageBinding> &imageBindings = mExecutable->getImageBindings();
1218*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::LinkedUniform> &uniforms     = mExecutable->getUniforms();
1219*8975f5c5SAndroid Build Coastguard Worker 
1220*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
1221*8975f5c5SAndroid Build Coastguard Worker     {
1222*8975f5c5SAndroid Build Coastguard Worker         uint32_t uniformIndex = mExecutable->getUniformIndexFromImageIndex(imageIndex);
1223*8975f5c5SAndroid Build Coastguard Worker         const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
1224*8975f5c5SAndroid Build Coastguard Worker 
1225*8975f5c5SAndroid Build Coastguard Worker         // 2D arrays are split into multiple 1D arrays when generating LinkedUniforms. Since they
1226*8975f5c5SAndroid Build Coastguard Worker         // are flattened into one array, ignore the nonzero elements and expand the array to the
1227*8975f5c5SAndroid Build Coastguard Worker         // total array size.
1228*8975f5c5SAndroid Build Coastguard Worker         if (imageUniform.activeShaders().none() || imageUniform.getOuterArrayOffset() > 0)
1229*8975f5c5SAndroid Build Coastguard Worker         {
1230*8975f5c5SAndroid Build Coastguard Worker             ASSERT(gl::SamplerNameContainsNonZeroArrayElement(
1231*8975f5c5SAndroid Build Coastguard Worker                 mExecutable->getUniformNameByIndex(uniformIndex)));
1232*8975f5c5SAndroid Build Coastguard Worker             continue;
1233*8975f5c5SAndroid Build Coastguard Worker         }
1234*8975f5c5SAndroid Build Coastguard Worker 
1235*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!gl::SamplerNameContainsNonZeroArrayElement(
1236*8975f5c5SAndroid Build Coastguard Worker             mExecutable->getUniformNameByIndex(uniformIndex)));
1237*8975f5c5SAndroid Build Coastguard Worker 
1238*8975f5c5SAndroid Build Coastguard Worker         // The front-end always binds array image units sequentially.
1239*8975f5c5SAndroid Build Coastguard Worker         const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
1240*8975f5c5SAndroid Build Coastguard Worker         uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
1241*8975f5c5SAndroid Build Coastguard Worker         arraySize *= imageUniform.getOuterArraySizeProduct();
1242*8975f5c5SAndroid Build Coastguard Worker 
1243*8975f5c5SAndroid Build Coastguard Worker         const gl::ShaderType firstShaderType = imageUniform.getFirstActiveShaderType();
1244*8975f5c5SAndroid Build Coastguard Worker         const ShaderInterfaceVariableInfo &info =
1245*8975f5c5SAndroid Build Coastguard Worker             mVariableInfoMap.getVariableById(firstShaderType, imageUniform.getId(firstShaderType));
1246*8975f5c5SAndroid Build Coastguard Worker 
1247*8975f5c5SAndroid Build Coastguard Worker         const VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
1248*8975f5c5SAndroid Build Coastguard Worker 
1249*8975f5c5SAndroid Build Coastguard Worker         const VkDescriptorType descType = imageBinding.textureType == gl::TextureType::Buffer
1250*8975f5c5SAndroid Build Coastguard Worker                                               ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
1251*8975f5c5SAndroid Build Coastguard Worker                                               : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1252*8975f5c5SAndroid Build Coastguard Worker         descOut->addBinding(info.binding, descType, arraySize, activeStages, nullptr);
1253*8975f5c5SAndroid Build Coastguard Worker     }
1254*8975f5c5SAndroid Build Coastguard Worker }
1255*8975f5c5SAndroid Build Coastguard Worker 
addInputAttachmentDescriptorSetDesc(vk::Context * context,vk::DescriptorSetLayoutDesc * descOut)1256*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::addInputAttachmentDescriptorSetDesc(vk::Context *context,
1257*8975f5c5SAndroid Build Coastguard Worker                                                               vk::DescriptorSetLayoutDesc *descOut)
1258*8975f5c5SAndroid Build Coastguard Worker {
1259*8975f5c5SAndroid Build Coastguard Worker     if (!mExecutable->getLinkedShaderStages()[gl::ShaderType::Fragment])
1260*8975f5c5SAndroid Build Coastguard Worker     {
1261*8975f5c5SAndroid Build Coastguard Worker         return;
1262*8975f5c5SAndroid Build Coastguard Worker     }
1263*8975f5c5SAndroid Build Coastguard Worker 
1264*8975f5c5SAndroid Build Coastguard Worker     if (mExecutable->usesDepthFramebufferFetch())
1265*8975f5c5SAndroid Build Coastguard Worker     {
1266*8975f5c5SAndroid Build Coastguard Worker         const uint32_t depthBinding =
1267*8975f5c5SAndroid Build Coastguard Worker             mVariableInfoMap
1268*8975f5c5SAndroid Build Coastguard Worker                 .getVariableById(gl::ShaderType::Fragment, sh::vk::spirv::kIdDepthInputAttachment)
1269*8975f5c5SAndroid Build Coastguard Worker                 .binding;
1270*8975f5c5SAndroid Build Coastguard Worker         descOut->addBinding(depthBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1,
1271*8975f5c5SAndroid Build Coastguard Worker                             VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
1272*8975f5c5SAndroid Build Coastguard Worker     }
1273*8975f5c5SAndroid Build Coastguard Worker 
1274*8975f5c5SAndroid Build Coastguard Worker     if (mExecutable->usesStencilFramebufferFetch())
1275*8975f5c5SAndroid Build Coastguard Worker     {
1276*8975f5c5SAndroid Build Coastguard Worker         const uint32_t stencilBinding =
1277*8975f5c5SAndroid Build Coastguard Worker             mVariableInfoMap
1278*8975f5c5SAndroid Build Coastguard Worker                 .getVariableById(gl::ShaderType::Fragment, sh::vk::spirv::kIdStencilInputAttachment)
1279*8975f5c5SAndroid Build Coastguard Worker                 .binding;
1280*8975f5c5SAndroid Build Coastguard Worker         descOut->addBinding(stencilBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1,
1281*8975f5c5SAndroid Build Coastguard Worker                             VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
1282*8975f5c5SAndroid Build Coastguard Worker     }
1283*8975f5c5SAndroid Build Coastguard Worker 
1284*8975f5c5SAndroid Build Coastguard Worker     if (!mExecutable->usesColorFramebufferFetch())
1285*8975f5c5SAndroid Build Coastguard Worker     {
1286*8975f5c5SAndroid Build Coastguard Worker         return;
1287*8975f5c5SAndroid Build Coastguard Worker     }
1288*8975f5c5SAndroid Build Coastguard Worker 
1289*8975f5c5SAndroid Build Coastguard Worker     const uint32_t firstInputAttachment =
1290*8975f5c5SAndroid Build Coastguard Worker         static_cast<uint32_t>(mExecutable->getFragmentInoutIndices().first());
1291*8975f5c5SAndroid Build Coastguard Worker 
1292*8975f5c5SAndroid Build Coastguard Worker     const ShaderInterfaceVariableInfo &baseInfo = mVariableInfoMap.getVariableById(
1293*8975f5c5SAndroid Build Coastguard Worker         gl::ShaderType::Fragment, sh::vk::spirv::kIdInputAttachment0 + firstInputAttachment);
1294*8975f5c5SAndroid Build Coastguard Worker 
1295*8975f5c5SAndroid Build Coastguard Worker     uint32_t baseBinding = baseInfo.binding - firstInputAttachment;
1296*8975f5c5SAndroid Build Coastguard Worker 
1297*8975f5c5SAndroid Build Coastguard Worker     const uint32_t maxColorInputAttachmentCount =
1298*8975f5c5SAndroid Build Coastguard Worker         context->getRenderer()->getMaxColorInputAttachmentCount();
1299*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t colorIndex = 0; colorIndex < maxColorInputAttachmentCount; ++colorIndex)
1300*8975f5c5SAndroid Build Coastguard Worker     {
1301*8975f5c5SAndroid Build Coastguard Worker         descOut->addBinding(baseBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1,
1302*8975f5c5SAndroid Build Coastguard Worker                             VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
1303*8975f5c5SAndroid Build Coastguard Worker         baseBinding++;
1304*8975f5c5SAndroid Build Coastguard Worker     }
1305*8975f5c5SAndroid Build Coastguard Worker }
1306*8975f5c5SAndroid Build Coastguard Worker 
addTextureDescriptorSetDesc(vk::Context * context,const gl::ActiveTextureArray<TextureVk * > * activeTextures,vk::DescriptorSetLayoutDesc * descOut)1307*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::addTextureDescriptorSetDesc(
1308*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1309*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTextureArray<TextureVk *> *activeTextures,
1310*8975f5c5SAndroid Build Coastguard Worker     vk::DescriptorSetLayoutDesc *descOut)
1311*8975f5c5SAndroid Build Coastguard Worker {
1312*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::SamplerBinding> &samplerBindings = mExecutable->getSamplerBindings();
1313*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::LinkedUniform> &uniforms         = mExecutable->getUniforms();
1314*8975f5c5SAndroid Build Coastguard Worker     const std::vector<GLuint> &samplerBoundTextureUnits =
1315*8975f5c5SAndroid Build Coastguard Worker         mExecutable->getSamplerBoundTextureUnits();
1316*8975f5c5SAndroid Build Coastguard Worker 
1317*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
1318*8975f5c5SAndroid Build Coastguard Worker     {
1319*8975f5c5SAndroid Build Coastguard Worker         uint32_t uniformIndex = mExecutable->getUniformIndexFromSamplerIndex(samplerIndex);
1320*8975f5c5SAndroid Build Coastguard Worker         const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
1321*8975f5c5SAndroid Build Coastguard Worker 
1322*8975f5c5SAndroid Build Coastguard Worker         // 2D arrays are split into multiple 1D arrays when generating LinkedUniforms. Since they
1323*8975f5c5SAndroid Build Coastguard Worker         // are flattened into one array, ignore the nonzero elements and expand the array to the
1324*8975f5c5SAndroid Build Coastguard Worker         // total array size.
1325*8975f5c5SAndroid Build Coastguard Worker         if (samplerUniform.activeShaders().none() || samplerUniform.getOuterArrayOffset() > 0)
1326*8975f5c5SAndroid Build Coastguard Worker         {
1327*8975f5c5SAndroid Build Coastguard Worker             ASSERT(gl::SamplerNameContainsNonZeroArrayElement(
1328*8975f5c5SAndroid Build Coastguard Worker                 mExecutable->getUniformNameByIndex(uniformIndex)));
1329*8975f5c5SAndroid Build Coastguard Worker             continue;
1330*8975f5c5SAndroid Build Coastguard Worker         }
1331*8975f5c5SAndroid Build Coastguard Worker 
1332*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!gl::SamplerNameContainsNonZeroArrayElement(
1333*8975f5c5SAndroid Build Coastguard Worker             mExecutable->getUniformNameByIndex(uniformIndex)));
1334*8975f5c5SAndroid Build Coastguard Worker 
1335*8975f5c5SAndroid Build Coastguard Worker         // The front-end always binds array sampler units sequentially.
1336*8975f5c5SAndroid Build Coastguard Worker         const gl::SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
1337*8975f5c5SAndroid Build Coastguard Worker         uint32_t arraySize = static_cast<uint32_t>(samplerBinding.textureUnitsCount);
1338*8975f5c5SAndroid Build Coastguard Worker         arraySize *= samplerUniform.getOuterArraySizeProduct();
1339*8975f5c5SAndroid Build Coastguard Worker 
1340*8975f5c5SAndroid Build Coastguard Worker         const gl::ShaderType firstShaderType    = samplerUniform.getFirstActiveShaderType();
1341*8975f5c5SAndroid Build Coastguard Worker         const ShaderInterfaceVariableInfo &info = mVariableInfoMap.getVariableById(
1342*8975f5c5SAndroid Build Coastguard Worker             firstShaderType, samplerUniform.getId(firstShaderType));
1343*8975f5c5SAndroid Build Coastguard Worker 
1344*8975f5c5SAndroid Build Coastguard Worker         const VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
1345*8975f5c5SAndroid Build Coastguard Worker 
1346*8975f5c5SAndroid Build Coastguard Worker         // TODO: https://issuetracker.google.com/issues/158215272: how do we handle array of
1347*8975f5c5SAndroid Build Coastguard Worker         // immutable samplers?
1348*8975f5c5SAndroid Build Coastguard Worker         GLuint textureUnit = samplerBinding.getTextureUnit(samplerBoundTextureUnits, 0);
1349*8975f5c5SAndroid Build Coastguard Worker         if (activeTextures != nullptr &&
1350*8975f5c5SAndroid Build Coastguard Worker             (*activeTextures)[textureUnit]->getImage().hasImmutableSampler())
1351*8975f5c5SAndroid Build Coastguard Worker         {
1352*8975f5c5SAndroid Build Coastguard Worker             ASSERT(samplerBinding.textureUnitsCount == 1);
1353*8975f5c5SAndroid Build Coastguard Worker 
1354*8975f5c5SAndroid Build Coastguard Worker             // In the case of samplerExternal2DY2YEXT, we need
1355*8975f5c5SAndroid Build Coastguard Worker             // samplerYcbcrConversion object with IDENTITY conversion model
1356*8975f5c5SAndroid Build Coastguard Worker             bool isSamplerExternalY2Y =
1357*8975f5c5SAndroid Build Coastguard Worker                 samplerBinding.samplerType == GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT;
1358*8975f5c5SAndroid Build Coastguard Worker 
1359*8975f5c5SAndroid Build Coastguard Worker             // Always take the texture's sampler, that's only way to get to yuv conversion for
1360*8975f5c5SAndroid Build Coastguard Worker             // externalFormat
1361*8975f5c5SAndroid Build Coastguard Worker             const TextureVk *textureVk          = (*activeTextures)[textureUnit];
1362*8975f5c5SAndroid Build Coastguard Worker             const vk::Sampler &immutableSampler = textureVk->getSampler(isSamplerExternalY2Y).get();
1363*8975f5c5SAndroid Build Coastguard Worker             descOut->addBinding(info.binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize,
1364*8975f5c5SAndroid Build Coastguard Worker                                 activeStages, &immutableSampler);
1365*8975f5c5SAndroid Build Coastguard Worker             const vk::ImageHelper &image = textureVk->getImage();
1366*8975f5c5SAndroid Build Coastguard Worker             const vk::YcbcrConversionDesc ycbcrConversionDesc =
1367*8975f5c5SAndroid Build Coastguard Worker                 isSamplerExternalY2Y ? image.getY2YConversionDesc()
1368*8975f5c5SAndroid Build Coastguard Worker                                      : image.getYcbcrConversionDesc();
1369*8975f5c5SAndroid Build Coastguard Worker             mImmutableSamplerIndexMap[ycbcrConversionDesc] = samplerIndex;
1370*8975f5c5SAndroid Build Coastguard Worker             // The Vulkan spec has the following note -
1371*8975f5c5SAndroid Build Coastguard Worker             // All descriptors in a binding use the same maximum
1372*8975f5c5SAndroid Build Coastguard Worker             // combinedImageSamplerDescriptorCount descriptors to allow implementations to use a
1373*8975f5c5SAndroid Build Coastguard Worker             // uniform stride for dynamic indexing of the descriptors in the binding.
1374*8975f5c5SAndroid Build Coastguard Worker             uint64_t externalFormat        = image.getExternalFormat();
1375*8975f5c5SAndroid Build Coastguard Worker             uint32_t formatDescriptorCount = 0;
1376*8975f5c5SAndroid Build Coastguard Worker 
1377*8975f5c5SAndroid Build Coastguard Worker             vk::Renderer *renderer = context->getRenderer();
1378*8975f5c5SAndroid Build Coastguard Worker 
1379*8975f5c5SAndroid Build Coastguard Worker             if (externalFormat != 0)
1380*8975f5c5SAndroid Build Coastguard Worker             {
1381*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(renderer->getFormatDescriptorCountForExternalFormat(
1382*8975f5c5SAndroid Build Coastguard Worker                     context, externalFormat, &formatDescriptorCount));
1383*8975f5c5SAndroid Build Coastguard Worker             }
1384*8975f5c5SAndroid Build Coastguard Worker             else
1385*8975f5c5SAndroid Build Coastguard Worker             {
1386*8975f5c5SAndroid Build Coastguard Worker                 VkFormat vkFormat = image.getActualVkFormat(renderer);
1387*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(vkFormat != 0);
1388*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_TRY(renderer->getFormatDescriptorCountForVkFormat(context, vkFormat,
1389*8975f5c5SAndroid Build Coastguard Worker                                                                         &formatDescriptorCount));
1390*8975f5c5SAndroid Build Coastguard Worker             }
1391*8975f5c5SAndroid Build Coastguard Worker 
1392*8975f5c5SAndroid Build Coastguard Worker             ASSERT(formatDescriptorCount > 0);
1393*8975f5c5SAndroid Build Coastguard Worker             mImmutableSamplersMaxDescriptorCount =
1394*8975f5c5SAndroid Build Coastguard Worker                 std::max(mImmutableSamplersMaxDescriptorCount, formatDescriptorCount);
1395*8975f5c5SAndroid Build Coastguard Worker         }
1396*8975f5c5SAndroid Build Coastguard Worker         else
1397*8975f5c5SAndroid Build Coastguard Worker         {
1398*8975f5c5SAndroid Build Coastguard Worker             const VkDescriptorType descType = samplerBinding.textureType == gl::TextureType::Buffer
1399*8975f5c5SAndroid Build Coastguard Worker                                                   ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
1400*8975f5c5SAndroid Build Coastguard Worker                                                   : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1401*8975f5c5SAndroid Build Coastguard Worker             descOut->addBinding(info.binding, descType, arraySize, activeStages, nullptr);
1402*8975f5c5SAndroid Build Coastguard Worker         }
1403*8975f5c5SAndroid Build Coastguard Worker     }
1404*8975f5c5SAndroid Build Coastguard Worker 
1405*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1406*8975f5c5SAndroid Build Coastguard Worker }
1407*8975f5c5SAndroid Build Coastguard Worker 
initializeWriteDescriptorDesc(vk::Context * context)1408*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::initializeWriteDescriptorDesc(vk::Context *context)
1409*8975f5c5SAndroid Build Coastguard Worker {
1410*8975f5c5SAndroid Build Coastguard Worker     const gl::ShaderBitSet &linkedShaderStages = mExecutable->getLinkedShaderStages();
1411*8975f5c5SAndroid Build Coastguard Worker 
1412*8975f5c5SAndroid Build Coastguard Worker     // Update mShaderResourceWriteDescriptorDescBuilder
1413*8975f5c5SAndroid Build Coastguard Worker     mShaderResourceWriteDescriptorDescs.reset();
1414*8975f5c5SAndroid Build Coastguard Worker     mShaderResourceWriteDescriptorDescs.updateShaderBuffers(
1415*8975f5c5SAndroid Build Coastguard Worker         mVariableInfoMap, mExecutable->getUniformBlocks(), getUniformBufferDescriptorType());
1416*8975f5c5SAndroid Build Coastguard Worker     mShaderResourceWriteDescriptorDescs.updateShaderBuffers(
1417*8975f5c5SAndroid Build Coastguard Worker         mVariableInfoMap, mExecutable->getShaderStorageBlocks(), getStorageBufferDescriptorType());
1418*8975f5c5SAndroid Build Coastguard Worker     mShaderResourceWriteDescriptorDescs.updateAtomicCounters(
1419*8975f5c5SAndroid Build Coastguard Worker         mVariableInfoMap, mExecutable->getAtomicCounterBuffers());
1420*8975f5c5SAndroid Build Coastguard Worker     mShaderResourceWriteDescriptorDescs.updateImages(*mExecutable, mVariableInfoMap);
1421*8975f5c5SAndroid Build Coastguard Worker     mShaderResourceWriteDescriptorDescs.updateDynamicDescriptorsCount();
1422*8975f5c5SAndroid Build Coastguard Worker 
1423*8975f5c5SAndroid Build Coastguard Worker     // Update mTextureWriteDescriptors
1424*8975f5c5SAndroid Build Coastguard Worker     mTextureWriteDescriptorDescs.reset();
1425*8975f5c5SAndroid Build Coastguard Worker     mTextureWriteDescriptorDescs.updateExecutableActiveTextures(mVariableInfoMap, *mExecutable);
1426*8975f5c5SAndroid Build Coastguard Worker     mTextureWriteDescriptorDescs.updateDynamicDescriptorsCount();
1427*8975f5c5SAndroid Build Coastguard Worker 
1428*8975f5c5SAndroid Build Coastguard Worker     // Update mDefaultUniformWriteDescriptors
1429*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformWriteDescriptorDescs.reset();
1430*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformWriteDescriptorDescs.updateDefaultUniform(linkedShaderStages, mVariableInfoMap,
1431*8975f5c5SAndroid Build Coastguard Worker                                                              *mExecutable);
1432*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformWriteDescriptorDescs.updateDynamicDescriptorsCount();
1433*8975f5c5SAndroid Build Coastguard Worker 
1434*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformAndXfbWriteDescriptorDescs.reset();
1435*8975f5c5SAndroid Build Coastguard Worker     if (mExecutable->hasTransformFeedbackOutput() &&
1436*8975f5c5SAndroid Build Coastguard Worker         context->getFeatures().emulateTransformFeedback.enabled)
1437*8975f5c5SAndroid Build Coastguard Worker     {
1438*8975f5c5SAndroid Build Coastguard Worker         // Update mDefaultUniformAndXfbWriteDescriptorDescs for the emulation code path.
1439*8975f5c5SAndroid Build Coastguard Worker         mDefaultUniformAndXfbWriteDescriptorDescs.updateDefaultUniform(
1440*8975f5c5SAndroid Build Coastguard Worker             linkedShaderStages, mVariableInfoMap, *mExecutable);
1441*8975f5c5SAndroid Build Coastguard Worker         if (linkedShaderStages[gl::ShaderType::Vertex])
1442*8975f5c5SAndroid Build Coastguard Worker         {
1443*8975f5c5SAndroid Build Coastguard Worker             mDefaultUniformAndXfbWriteDescriptorDescs.updateTransformFeedbackWrite(mVariableInfoMap,
1444*8975f5c5SAndroid Build Coastguard Worker                                                                                    *mExecutable);
1445*8975f5c5SAndroid Build Coastguard Worker         }
1446*8975f5c5SAndroid Build Coastguard Worker         mDefaultUniformAndXfbWriteDescriptorDescs.updateDynamicDescriptorsCount();
1447*8975f5c5SAndroid Build Coastguard Worker     }
1448*8975f5c5SAndroid Build Coastguard Worker     else
1449*8975f5c5SAndroid Build Coastguard Worker     {
1450*8975f5c5SAndroid Build Coastguard Worker         // Otherwise it will be the same as default uniform
1451*8975f5c5SAndroid Build Coastguard Worker         mDefaultUniformAndXfbWriteDescriptorDescs = mDefaultUniformWriteDescriptorDescs;
1452*8975f5c5SAndroid Build Coastguard Worker     }
1453*8975f5c5SAndroid Build Coastguard Worker }
1454*8975f5c5SAndroid Build Coastguard Worker 
getTransformOptions(ContextVk * contextVk,const vk::GraphicsPipelineDesc & desc)1455*8975f5c5SAndroid Build Coastguard Worker ProgramTransformOptions ProgramExecutableVk::getTransformOptions(
1456*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk,
1457*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc &desc)
1458*8975f5c5SAndroid Build Coastguard Worker {
1459*8975f5c5SAndroid Build Coastguard Worker     ProgramTransformOptions transformOptions = {};
1460*8975f5c5SAndroid Build Coastguard Worker 
1461*8975f5c5SAndroid Build Coastguard Worker     transformOptions.surfaceRotation = desc.getSurfaceRotation();
1462*8975f5c5SAndroid Build Coastguard Worker     transformOptions.removeTransformFeedbackEmulation =
1463*8975f5c5SAndroid Build Coastguard Worker         contextVk->getFeatures().emulateTransformFeedback.enabled &&
1464*8975f5c5SAndroid Build Coastguard Worker         !contextVk->getState().isTransformFeedbackActiveUnpaused();
1465*8975f5c5SAndroid Build Coastguard Worker     FramebufferVk *drawFrameBuffer = vk::GetImpl(contextVk->getState().getDrawFramebuffer());
1466*8975f5c5SAndroid Build Coastguard Worker     const bool hasFramebufferFetch = mExecutable->usesColorFramebufferFetch() ||
1467*8975f5c5SAndroid Build Coastguard Worker                                      mExecutable->usesDepthFramebufferFetch() ||
1468*8975f5c5SAndroid Build Coastguard Worker                                      mExecutable->usesStencilFramebufferFetch();
1469*8975f5c5SAndroid Build Coastguard Worker     const bool isMultisampled                    = drawFrameBuffer->getSamples() > 1;
1470*8975f5c5SAndroid Build Coastguard Worker     transformOptions.multiSampleFramebufferFetch = hasFramebufferFetch && isMultisampled;
1471*8975f5c5SAndroid Build Coastguard Worker     transformOptions.enableSampleShading =
1472*8975f5c5SAndroid Build Coastguard Worker         contextVk->getState().isSampleShadingEnabled() && isMultisampled;
1473*8975f5c5SAndroid Build Coastguard Worker 
1474*8975f5c5SAndroid Build Coastguard Worker     return transformOptions;
1475*8975f5c5SAndroid Build Coastguard Worker }
1476*8975f5c5SAndroid Build Coastguard Worker 
initGraphicsShaderPrograms(vk::Context * context,ProgramTransformOptions transformOptions)1477*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::initGraphicsShaderPrograms(
1478*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1479*8975f5c5SAndroid Build Coastguard Worker     ProgramTransformOptions transformOptions)
1480*8975f5c5SAndroid Build Coastguard Worker {
1481*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex));
1482*8975f5c5SAndroid Build Coastguard Worker 
1483*8975f5c5SAndroid Build Coastguard Worker     const uint8_t programIndex                = transformOptions.permutationIndex;
1484*8975f5c5SAndroid Build Coastguard Worker     ProgramInfo &programInfo                  = mGraphicsProgramInfos[programIndex];
1485*8975f5c5SAndroid Build Coastguard Worker     const gl::ShaderBitSet linkedShaderStages = mExecutable->getLinkedShaderStages();
1486*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderType lastPreFragmentStage       = gl::GetLastPreFragmentStage(linkedShaderStages);
1487*8975f5c5SAndroid Build Coastguard Worker 
1488*8975f5c5SAndroid Build Coastguard Worker     const bool isTransformFeedbackProgram =
1489*8975f5c5SAndroid Build Coastguard Worker         !mExecutable->getLinkedTransformFeedbackVaryings().empty();
1490*8975f5c5SAndroid Build Coastguard Worker 
1491*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : linkedShaderStages)
1492*8975f5c5SAndroid Build Coastguard Worker     {
1493*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(initGraphicsShaderProgram(context, shaderType, shaderType == lastPreFragmentStage,
1494*8975f5c5SAndroid Build Coastguard Worker                                             isTransformFeedbackProgram, transformOptions,
1495*8975f5c5SAndroid Build Coastguard Worker                                             &programInfo, mVariableInfoMap));
1496*8975f5c5SAndroid Build Coastguard Worker     }
1497*8975f5c5SAndroid Build Coastguard Worker 
1498*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1499*8975f5c5SAndroid Build Coastguard Worker }
1500*8975f5c5SAndroid Build Coastguard Worker 
initProgramThenCreateGraphicsPipeline(vk::Context * context,ProgramTransformOptions transformOptions,vk::GraphicsPipelineSubset pipelineSubset,vk::PipelineCacheAccess * pipelineCache,PipelineSource source,const vk::GraphicsPipelineDesc & desc,const vk::RenderPass & compatibleRenderPass,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)1501*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::initProgramThenCreateGraphicsPipeline(
1502*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1503*8975f5c5SAndroid Build Coastguard Worker     ProgramTransformOptions transformOptions,
1504*8975f5c5SAndroid Build Coastguard Worker     vk::GraphicsPipelineSubset pipelineSubset,
1505*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineCacheAccess *pipelineCache,
1506*8975f5c5SAndroid Build Coastguard Worker     PipelineSource source,
1507*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc &desc,
1508*8975f5c5SAndroid Build Coastguard Worker     const vk::RenderPass &compatibleRenderPass,
1509*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc **descPtrOut,
1510*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper **pipelineOut)
1511*8975f5c5SAndroid Build Coastguard Worker {
1512*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initGraphicsShaderPrograms(context, transformOptions));
1513*8975f5c5SAndroid Build Coastguard Worker 
1514*8975f5c5SAndroid Build Coastguard Worker     return createGraphicsPipelineImpl(context, transformOptions, pipelineSubset, pipelineCache,
1515*8975f5c5SAndroid Build Coastguard Worker                                       source, desc, compatibleRenderPass, descPtrOut, pipelineOut);
1516*8975f5c5SAndroid Build Coastguard Worker }
1517*8975f5c5SAndroid Build Coastguard Worker 
createGraphicsPipelineImpl(vk::Context * context,ProgramTransformOptions transformOptions,vk::GraphicsPipelineSubset pipelineSubset,vk::PipelineCacheAccess * pipelineCache,PipelineSource source,const vk::GraphicsPipelineDesc & desc,const vk::RenderPass & compatibleRenderPass,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)1518*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::createGraphicsPipelineImpl(
1519*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1520*8975f5c5SAndroid Build Coastguard Worker     ProgramTransformOptions transformOptions,
1521*8975f5c5SAndroid Build Coastguard Worker     vk::GraphicsPipelineSubset pipelineSubset,
1522*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineCacheAccess *pipelineCache,
1523*8975f5c5SAndroid Build Coastguard Worker     PipelineSource source,
1524*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc &desc,
1525*8975f5c5SAndroid Build Coastguard Worker     const vk::RenderPass &compatibleRenderPass,
1526*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc **descPtrOut,
1527*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper **pipelineOut)
1528*8975f5c5SAndroid Build Coastguard Worker {
1529*8975f5c5SAndroid Build Coastguard Worker     // This method assumes that all the state necessary to create a graphics pipeline has already
1530*8975f5c5SAndroid Build Coastguard Worker     // been setup by the caller. Assert that all required state is valid so all that is left will
1531*8975f5c5SAndroid Build Coastguard Worker     // be the call to `vkCreateGraphicsPipelines`
1532*8975f5c5SAndroid Build Coastguard Worker 
1533*8975f5c5SAndroid Build Coastguard Worker     // Make sure program index is within range
1534*8975f5c5SAndroid Build Coastguard Worker     const uint8_t programIndex = transformOptions.permutationIndex;
1535*8975f5c5SAndroid Build Coastguard Worker     ASSERT(programIndex >= 0 && programIndex < ProgramTransformOptions::kPermutationCount);
1536*8975f5c5SAndroid Build Coastguard Worker 
1537*8975f5c5SAndroid Build Coastguard Worker     // Make sure the shader modules for all linked shader stages are valid.
1538*8975f5c5SAndroid Build Coastguard Worker     ProgramInfo &programInfo = mGraphicsProgramInfos[programIndex];
1539*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
1540*8975f5c5SAndroid Build Coastguard Worker     {
1541*8975f5c5SAndroid Build Coastguard Worker         ASSERT(programInfo.valid(shaderType));
1542*8975f5c5SAndroid Build Coastguard Worker     }
1543*8975f5c5SAndroid Build Coastguard Worker 
1544*8975f5c5SAndroid Build Coastguard Worker     // Generate spec consts, a change in which results in a new pipeline.
1545*8975f5c5SAndroid Build Coastguard Worker     vk::SpecializationConstants specConsts = MakeSpecConsts(transformOptions, desc);
1546*8975f5c5SAndroid Build Coastguard Worker 
1547*8975f5c5SAndroid Build Coastguard Worker     // Choose appropriate pipeline cache based on pipeline subset
1548*8975f5c5SAndroid Build Coastguard Worker     if (pipelineSubset == vk::GraphicsPipelineSubset::Complete)
1549*8975f5c5SAndroid Build Coastguard Worker     {
1550*8975f5c5SAndroid Build Coastguard Worker         CompleteGraphicsPipelineCache &pipelines = mCompleteGraphicsPipelines[programIndex];
1551*8975f5c5SAndroid Build Coastguard Worker         return programInfo.getShaderProgram().createGraphicsPipeline(
1552*8975f5c5SAndroid Build Coastguard Worker             context, &pipelines, pipelineCache, compatibleRenderPass, getPipelineLayout(), source,
1553*8975f5c5SAndroid Build Coastguard Worker             desc, specConsts, descPtrOut, pipelineOut);
1554*8975f5c5SAndroid Build Coastguard Worker     }
1555*8975f5c5SAndroid Build Coastguard Worker     else
1556*8975f5c5SAndroid Build Coastguard Worker     {
1557*8975f5c5SAndroid Build Coastguard Worker         // Vertex input and fragment output subsets are independent of shaders, and are not created
1558*8975f5c5SAndroid Build Coastguard Worker         // through the program executable.
1559*8975f5c5SAndroid Build Coastguard Worker         ASSERT(pipelineSubset == vk::GraphicsPipelineSubset::Shaders);
1560*8975f5c5SAndroid Build Coastguard Worker 
1561*8975f5c5SAndroid Build Coastguard Worker         ShadersGraphicsPipelineCache &pipelines = mShadersGraphicsPipelines[programIndex];
1562*8975f5c5SAndroid Build Coastguard Worker         return programInfo.getShaderProgram().createGraphicsPipeline(
1563*8975f5c5SAndroid Build Coastguard Worker             context, &pipelines, pipelineCache, compatibleRenderPass, getPipelineLayout(), source,
1564*8975f5c5SAndroid Build Coastguard Worker             desc, specConsts, descPtrOut, pipelineOut);
1565*8975f5c5SAndroid Build Coastguard Worker     }
1566*8975f5c5SAndroid Build Coastguard Worker }
1567*8975f5c5SAndroid Build Coastguard Worker 
getGraphicsPipeline(ContextVk * contextVk,vk::GraphicsPipelineSubset pipelineSubset,const vk::GraphicsPipelineDesc & desc,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)1568*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::getGraphicsPipeline(ContextVk *contextVk,
1569*8975f5c5SAndroid Build Coastguard Worker                                                        vk::GraphicsPipelineSubset pipelineSubset,
1570*8975f5c5SAndroid Build Coastguard Worker                                                        const vk::GraphicsPipelineDesc &desc,
1571*8975f5c5SAndroid Build Coastguard Worker                                                        const vk::GraphicsPipelineDesc **descPtrOut,
1572*8975f5c5SAndroid Build Coastguard Worker                                                        vk::PipelineHelper **pipelineOut)
1573*8975f5c5SAndroid Build Coastguard Worker {
1574*8975f5c5SAndroid Build Coastguard Worker     ProgramTransformOptions transformOptions = getTransformOptions(contextVk, desc);
1575*8975f5c5SAndroid Build Coastguard Worker 
1576*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initGraphicsShaderPrograms(contextVk, transformOptions));
1577*8975f5c5SAndroid Build Coastguard Worker 
1578*8975f5c5SAndroid Build Coastguard Worker     const uint8_t programIndex = transformOptions.permutationIndex;
1579*8975f5c5SAndroid Build Coastguard Worker 
1580*8975f5c5SAndroid Build Coastguard Worker     *descPtrOut  = nullptr;
1581*8975f5c5SAndroid Build Coastguard Worker     *pipelineOut = nullptr;
1582*8975f5c5SAndroid Build Coastguard Worker 
1583*8975f5c5SAndroid Build Coastguard Worker     if (pipelineSubset == vk::GraphicsPipelineSubset::Complete)
1584*8975f5c5SAndroid Build Coastguard Worker     {
1585*8975f5c5SAndroid Build Coastguard Worker         mCompleteGraphicsPipelines[programIndex].getPipeline(desc, descPtrOut, pipelineOut);
1586*8975f5c5SAndroid Build Coastguard Worker     }
1587*8975f5c5SAndroid Build Coastguard Worker     else
1588*8975f5c5SAndroid Build Coastguard Worker     {
1589*8975f5c5SAndroid Build Coastguard Worker         // Vertex input and fragment output subsets are independent of shaders, and are not created
1590*8975f5c5SAndroid Build Coastguard Worker         // through the program executable.
1591*8975f5c5SAndroid Build Coastguard Worker         ASSERT(pipelineSubset == vk::GraphicsPipelineSubset::Shaders);
1592*8975f5c5SAndroid Build Coastguard Worker 
1593*8975f5c5SAndroid Build Coastguard Worker         mShadersGraphicsPipelines[programIndex].getPipeline(desc, descPtrOut, pipelineOut);
1594*8975f5c5SAndroid Build Coastguard Worker     }
1595*8975f5c5SAndroid Build Coastguard Worker 
1596*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1597*8975f5c5SAndroid Build Coastguard Worker }
1598*8975f5c5SAndroid Build Coastguard Worker 
createGraphicsPipeline(ContextVk * contextVk,vk::GraphicsPipelineSubset pipelineSubset,vk::PipelineCacheAccess * pipelineCache,PipelineSource source,const vk::GraphicsPipelineDesc & desc,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)1599*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::createGraphicsPipeline(
1600*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk,
1601*8975f5c5SAndroid Build Coastguard Worker     vk::GraphicsPipelineSubset pipelineSubset,
1602*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineCacheAccess *pipelineCache,
1603*8975f5c5SAndroid Build Coastguard Worker     PipelineSource source,
1604*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc &desc,
1605*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc **descPtrOut,
1606*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper **pipelineOut)
1607*8975f5c5SAndroid Build Coastguard Worker {
1608*8975f5c5SAndroid Build Coastguard Worker     ProgramTransformOptions transformOptions = getTransformOptions(contextVk, desc);
1609*8975f5c5SAndroid Build Coastguard Worker 
1610*8975f5c5SAndroid Build Coastguard Worker     // When creating monolithic pipelines, the renderer's pipeline cache is used as passed in.
1611*8975f5c5SAndroid Build Coastguard Worker     // When creating the shaders subset of pipelines, the program's own pipeline cache is used.
1612*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineCacheAccess perProgramPipelineCache;
1613*8975f5c5SAndroid Build Coastguard Worker     const bool useProgramPipelineCache = pipelineSubset == vk::GraphicsPipelineSubset::Shaders;
1614*8975f5c5SAndroid Build Coastguard Worker     if (useProgramPipelineCache)
1615*8975f5c5SAndroid Build Coastguard Worker     {
1616*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(ensurePipelineCacheInitialized(contextVk));
1617*8975f5c5SAndroid Build Coastguard Worker 
1618*8975f5c5SAndroid Build Coastguard Worker         perProgramPipelineCache.init(&mPipelineCache, nullptr);
1619*8975f5c5SAndroid Build Coastguard Worker         pipelineCache = &perProgramPipelineCache;
1620*8975f5c5SAndroid Build Coastguard Worker     }
1621*8975f5c5SAndroid Build Coastguard Worker 
1622*8975f5c5SAndroid Build Coastguard Worker     // Pull in a compatible RenderPass.
1623*8975f5c5SAndroid Build Coastguard Worker     const vk::RenderPass *compatibleRenderPass = nullptr;
1624*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(contextVk->getCompatibleRenderPass(desc.getRenderPassDesc(), &compatibleRenderPass));
1625*8975f5c5SAndroid Build Coastguard Worker 
1626*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initProgramThenCreateGraphicsPipeline(
1627*8975f5c5SAndroid Build Coastguard Worker         contextVk, transformOptions, pipelineSubset, pipelineCache, source, desc,
1628*8975f5c5SAndroid Build Coastguard Worker         *compatibleRenderPass, descPtrOut, pipelineOut));
1629*8975f5c5SAndroid Build Coastguard Worker 
1630*8975f5c5SAndroid Build Coastguard Worker     if (useProgramPipelineCache &&
1631*8975f5c5SAndroid Build Coastguard Worker         contextVk->getFeatures().mergeProgramPipelineCachesToGlobalCache.enabled)
1632*8975f5c5SAndroid Build Coastguard Worker     {
1633*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(contextVk->getRenderer()->mergeIntoPipelineCache(contextVk, mPipelineCache));
1634*8975f5c5SAndroid Build Coastguard Worker     }
1635*8975f5c5SAndroid Build Coastguard Worker 
1636*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1637*8975f5c5SAndroid Build Coastguard Worker }
1638*8975f5c5SAndroid Build Coastguard Worker 
linkGraphicsPipelineLibraries(ContextVk * contextVk,vk::PipelineCacheAccess * pipelineCache,const vk::GraphicsPipelineDesc & desc,vk::PipelineHelper * vertexInputPipeline,vk::PipelineHelper * shadersPipeline,vk::PipelineHelper * fragmentOutputPipeline,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)1639*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::linkGraphicsPipelineLibraries(
1640*8975f5c5SAndroid Build Coastguard Worker     ContextVk *contextVk,
1641*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineCacheAccess *pipelineCache,
1642*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc &desc,
1643*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper *vertexInputPipeline,
1644*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper *shadersPipeline,
1645*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper *fragmentOutputPipeline,
1646*8975f5c5SAndroid Build Coastguard Worker     const vk::GraphicsPipelineDesc **descPtrOut,
1647*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper **pipelineOut)
1648*8975f5c5SAndroid Build Coastguard Worker {
1649*8975f5c5SAndroid Build Coastguard Worker     ProgramTransformOptions transformOptions = getTransformOptions(contextVk, desc);
1650*8975f5c5SAndroid Build Coastguard Worker     const uint8_t programIndex               = transformOptions.permutationIndex;
1651*8975f5c5SAndroid Build Coastguard Worker 
1652*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(mCompleteGraphicsPipelines[programIndex].linkLibraries(
1653*8975f5c5SAndroid Build Coastguard Worker         contextVk, pipelineCache, desc, getPipelineLayout(), vertexInputPipeline, shadersPipeline,
1654*8975f5c5SAndroid Build Coastguard Worker         fragmentOutputPipeline, descPtrOut, pipelineOut));
1655*8975f5c5SAndroid Build Coastguard Worker 
1656*8975f5c5SAndroid Build Coastguard Worker     // If monolithic pipelines are preferred over libraries, create a task so that it can be created
1657*8975f5c5SAndroid Build Coastguard Worker     // asynchronously.
1658*8975f5c5SAndroid Build Coastguard Worker     if (contextVk->getFeatures().preferMonolithicPipelinesOverLibraries.enabled)
1659*8975f5c5SAndroid Build Coastguard Worker     {
1660*8975f5c5SAndroid Build Coastguard Worker         vk::SpecializationConstants specConsts = MakeSpecConsts(transformOptions, desc);
1661*8975f5c5SAndroid Build Coastguard Worker 
1662*8975f5c5SAndroid Build Coastguard Worker         mGraphicsProgramInfos[programIndex].getShaderProgram().createMonolithicPipelineCreationTask(
1663*8975f5c5SAndroid Build Coastguard Worker             contextVk, pipelineCache, desc, getPipelineLayout(), specConsts, *pipelineOut);
1664*8975f5c5SAndroid Build Coastguard Worker     }
1665*8975f5c5SAndroid Build Coastguard Worker 
1666*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1667*8975f5c5SAndroid Build Coastguard Worker }
1668*8975f5c5SAndroid Build Coastguard Worker 
getOrCreateComputePipeline(vk::Context * context,vk::PipelineCacheAccess * pipelineCache,PipelineSource source,vk::PipelineRobustness pipelineRobustness,vk::PipelineProtectedAccess pipelineProtectedAccess,vk::PipelineHelper ** pipelineOut)1669*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::getOrCreateComputePipeline(
1670*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1671*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineCacheAccess *pipelineCache,
1672*8975f5c5SAndroid Build Coastguard Worker     PipelineSource source,
1673*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineRobustness pipelineRobustness,
1674*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineProtectedAccess pipelineProtectedAccess,
1675*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineHelper **pipelineOut)
1676*8975f5c5SAndroid Build Coastguard Worker {
1677*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute));
1678*8975f5c5SAndroid Build Coastguard Worker 
1679*8975f5c5SAndroid Build Coastguard Worker     vk::ComputePipelineOptions pipelineOptions =
1680*8975f5c5SAndroid Build Coastguard Worker         vk::GetComputePipelineOptions(pipelineRobustness, pipelineProtectedAccess);
1681*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(initComputeProgram(context, &mComputeProgramInfo, mVariableInfoMap, pipelineOptions));
1682*8975f5c5SAndroid Build Coastguard Worker 
1683*8975f5c5SAndroid Build Coastguard Worker     return mComputeProgramInfo.getShaderProgram().getOrCreateComputePipeline(
1684*8975f5c5SAndroid Build Coastguard Worker         context, &mComputePipelines, pipelineCache, getPipelineLayout(), pipelineOptions, source,
1685*8975f5c5SAndroid Build Coastguard Worker         pipelineOut, nullptr, nullptr);
1686*8975f5c5SAndroid Build Coastguard Worker }
1687*8975f5c5SAndroid Build Coastguard Worker 
createPipelineLayout(vk::Context * context,PipelineLayoutCache * pipelineLayoutCache,DescriptorSetLayoutCache * descriptorSetLayoutCache,gl::ActiveTextureArray<TextureVk * > * activeTextures)1688*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::createPipelineLayout(
1689*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1690*8975f5c5SAndroid Build Coastguard Worker     PipelineLayoutCache *pipelineLayoutCache,
1691*8975f5c5SAndroid Build Coastguard Worker     DescriptorSetLayoutCache *descriptorSetLayoutCache,
1692*8975f5c5SAndroid Build Coastguard Worker     gl::ActiveTextureArray<TextureVk *> *activeTextures)
1693*8975f5c5SAndroid Build Coastguard Worker {
1694*8975f5c5SAndroid Build Coastguard Worker     const gl::ShaderBitSet &linkedShaderStages = mExecutable->getLinkedShaderStages();
1695*8975f5c5SAndroid Build Coastguard Worker 
1696*8975f5c5SAndroid Build Coastguard Worker     // Store a reference to the pipeline and descriptor set layouts. This will create them if they
1697*8975f5c5SAndroid Build Coastguard Worker     // don't already exist in the cache.
1698*8975f5c5SAndroid Build Coastguard Worker 
1699*8975f5c5SAndroid Build Coastguard Worker     // Default uniforms and transform feedback:
1700*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformAndXfbSetDesc          = {};
1701*8975f5c5SAndroid Build Coastguard Worker     uint32_t numDefaultUniformDescriptors = 0;
1702*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : linkedShaderStages)
1703*8975f5c5SAndroid Build Coastguard Worker     {
1704*8975f5c5SAndroid Build Coastguard Worker         const ShaderInterfaceVariableInfo &info =
1705*8975f5c5SAndroid Build Coastguard Worker             mVariableInfoMap.getDefaultUniformInfo(shaderType);
1706*8975f5c5SAndroid Build Coastguard Worker         // Note that currently the default uniform block is added unconditionally.
1707*8975f5c5SAndroid Build Coastguard Worker         ASSERT(info.activeStages[shaderType]);
1708*8975f5c5SAndroid Build Coastguard Worker 
1709*8975f5c5SAndroid Build Coastguard Worker         mDefaultUniformAndXfbSetDesc.addBinding(info.binding,
1710*8975f5c5SAndroid Build Coastguard Worker                                                 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
1711*8975f5c5SAndroid Build Coastguard Worker                                                 gl_vk::kShaderStageMap[shaderType], nullptr);
1712*8975f5c5SAndroid Build Coastguard Worker         numDefaultUniformDescriptors++;
1713*8975f5c5SAndroid Build Coastguard Worker     }
1714*8975f5c5SAndroid Build Coastguard Worker 
1715*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderType linkedTransformFeedbackStage = mExecutable->getLinkedTransformFeedbackStage();
1716*8975f5c5SAndroid Build Coastguard Worker     bool hasXfbVaryings = linkedTransformFeedbackStage != gl::ShaderType::InvalidEnum &&
1717*8975f5c5SAndroid Build Coastguard Worker                           !mExecutable->getLinkedTransformFeedbackVaryings().empty();
1718*8975f5c5SAndroid Build Coastguard Worker     if (context->getFeatures().emulateTransformFeedback.enabled && hasXfbVaryings)
1719*8975f5c5SAndroid Build Coastguard Worker     {
1720*8975f5c5SAndroid Build Coastguard Worker         size_t xfbBufferCount = mExecutable->getTransformFeedbackBufferCount();
1721*8975f5c5SAndroid Build Coastguard Worker         for (uint32_t bufferIndex = 0; bufferIndex < xfbBufferCount; ++bufferIndex)
1722*8975f5c5SAndroid Build Coastguard Worker         {
1723*8975f5c5SAndroid Build Coastguard Worker             const uint32_t binding = mVariableInfoMap.getEmulatedXfbBufferBinding(bufferIndex);
1724*8975f5c5SAndroid Build Coastguard Worker             ASSERT(binding != std::numeric_limits<uint32_t>::max());
1725*8975f5c5SAndroid Build Coastguard Worker 
1726*8975f5c5SAndroid Build Coastguard Worker             mDefaultUniformAndXfbSetDesc.addBinding(binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1,
1727*8975f5c5SAndroid Build Coastguard Worker                                                     VK_SHADER_STAGE_VERTEX_BIT, nullptr);
1728*8975f5c5SAndroid Build Coastguard Worker         }
1729*8975f5c5SAndroid Build Coastguard Worker     }
1730*8975f5c5SAndroid Build Coastguard Worker 
1731*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(descriptorSetLayoutCache->getDescriptorSetLayout(
1732*8975f5c5SAndroid Build Coastguard Worker         context, mDefaultUniformAndXfbSetDesc,
1733*8975f5c5SAndroid Build Coastguard Worker         &mDescriptorSetLayouts[DescriptorSetIndex::UniformsAndXfb]));
1734*8975f5c5SAndroid Build Coastguard Worker 
1735*8975f5c5SAndroid Build Coastguard Worker     // Uniform and storage buffers, atomic counter buffers and images:
1736*8975f5c5SAndroid Build Coastguard Worker     mShaderResourceSetDesc = {};
1737*8975f5c5SAndroid Build Coastguard Worker 
1738*8975f5c5SAndroid Build Coastguard Worker     // Count the number of active uniform buffer descriptors.
1739*8975f5c5SAndroid Build Coastguard Worker     uint32_t numActiveUniformBufferDescriptors    = 0;
1740*8975f5c5SAndroid Build Coastguard Worker     const std::vector<gl::InterfaceBlock> &blocks = mExecutable->getUniformBlocks();
1741*8975f5c5SAndroid Build Coastguard Worker     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size();)
1742*8975f5c5SAndroid Build Coastguard Worker     {
1743*8975f5c5SAndroid Build Coastguard Worker         const gl::InterfaceBlock &block = blocks[bufferIndex];
1744*8975f5c5SAndroid Build Coastguard Worker         const uint32_t arraySize        = GetInterfaceBlockArraySize(blocks, bufferIndex);
1745*8975f5c5SAndroid Build Coastguard Worker         bufferIndex += arraySize;
1746*8975f5c5SAndroid Build Coastguard Worker 
1747*8975f5c5SAndroid Build Coastguard Worker         if (block.activeShaders().any())
1748*8975f5c5SAndroid Build Coastguard Worker         {
1749*8975f5c5SAndroid Build Coastguard Worker             numActiveUniformBufferDescriptors += arraySize;
1750*8975f5c5SAndroid Build Coastguard Worker         }
1751*8975f5c5SAndroid Build Coastguard Worker     }
1752*8975f5c5SAndroid Build Coastguard Worker 
1753*8975f5c5SAndroid Build Coastguard Worker     // Decide if we should use dynamic or fixed descriptor types.
1754*8975f5c5SAndroid Build Coastguard Worker     VkPhysicalDeviceLimits limits = context->getRenderer()->getPhysicalDeviceProperties().limits;
1755*8975f5c5SAndroid Build Coastguard Worker     uint32_t totalDynamicUniformBufferCount =
1756*8975f5c5SAndroid Build Coastguard Worker         numActiveUniformBufferDescriptors + numDefaultUniformDescriptors;
1757*8975f5c5SAndroid Build Coastguard Worker     if (totalDynamicUniformBufferCount <= limits.maxDescriptorSetUniformBuffersDynamic)
1758*8975f5c5SAndroid Build Coastguard Worker     {
1759*8975f5c5SAndroid Build Coastguard Worker         mUniformBufferDescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
1760*8975f5c5SAndroid Build Coastguard Worker     }
1761*8975f5c5SAndroid Build Coastguard Worker     else
1762*8975f5c5SAndroid Build Coastguard Worker     {
1763*8975f5c5SAndroid Build Coastguard Worker         mUniformBufferDescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1764*8975f5c5SAndroid Build Coastguard Worker     }
1765*8975f5c5SAndroid Build Coastguard Worker 
1766*8975f5c5SAndroid Build Coastguard Worker     addInterfaceBlockDescriptorSetDesc(mExecutable->getUniformBlocks(), linkedShaderStages,
1767*8975f5c5SAndroid Build Coastguard Worker                                        mUniformBufferDescriptorType, &mShaderResourceSetDesc);
1768*8975f5c5SAndroid Build Coastguard Worker     addInterfaceBlockDescriptorSetDesc(mExecutable->getShaderStorageBlocks(), linkedShaderStages,
1769*8975f5c5SAndroid Build Coastguard Worker                                        vk::kStorageBufferDescriptorType, &mShaderResourceSetDesc);
1770*8975f5c5SAndroid Build Coastguard Worker     addAtomicCounterBufferDescriptorSetDesc(mExecutable->getAtomicCounterBuffers(),
1771*8975f5c5SAndroid Build Coastguard Worker                                             &mShaderResourceSetDesc);
1772*8975f5c5SAndroid Build Coastguard Worker     addImageDescriptorSetDesc(&mShaderResourceSetDesc);
1773*8975f5c5SAndroid Build Coastguard Worker     addInputAttachmentDescriptorSetDesc(context, &mShaderResourceSetDesc);
1774*8975f5c5SAndroid Build Coastguard Worker 
1775*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(descriptorSetLayoutCache->getDescriptorSetLayout(
1776*8975f5c5SAndroid Build Coastguard Worker         context, mShaderResourceSetDesc,
1777*8975f5c5SAndroid Build Coastguard Worker         &mDescriptorSetLayouts[DescriptorSetIndex::ShaderResource]));
1778*8975f5c5SAndroid Build Coastguard Worker 
1779*8975f5c5SAndroid Build Coastguard Worker     // Textures:
1780*8975f5c5SAndroid Build Coastguard Worker     mTextureSetDesc = {};
1781*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(addTextureDescriptorSetDesc(context, activeTextures, &mTextureSetDesc));
1782*8975f5c5SAndroid Build Coastguard Worker 
1783*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(descriptorSetLayoutCache->getDescriptorSetLayout(
1784*8975f5c5SAndroid Build Coastguard Worker         context, mTextureSetDesc, &mDescriptorSetLayouts[DescriptorSetIndex::Texture]));
1785*8975f5c5SAndroid Build Coastguard Worker 
1786*8975f5c5SAndroid Build Coastguard Worker     // Create pipeline layout with these 3 descriptor sets.
1787*8975f5c5SAndroid Build Coastguard Worker     vk::PipelineLayoutDesc pipelineLayoutDesc;
1788*8975f5c5SAndroid Build Coastguard Worker     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::UniformsAndXfb,
1789*8975f5c5SAndroid Build Coastguard Worker                                                  mDefaultUniformAndXfbSetDesc);
1790*8975f5c5SAndroid Build Coastguard Worker     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::ShaderResource,
1791*8975f5c5SAndroid Build Coastguard Worker                                                  mShaderResourceSetDesc);
1792*8975f5c5SAndroid Build Coastguard Worker     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Texture, mTextureSetDesc);
1793*8975f5c5SAndroid Build Coastguard Worker 
1794*8975f5c5SAndroid Build Coastguard Worker     // Set up driver uniforms as push constants. The size is set for a graphics pipeline, as there
1795*8975f5c5SAndroid Build Coastguard Worker     // are more driver uniforms for a graphics pipeline than there are for a compute pipeline. As
1796*8975f5c5SAndroid Build Coastguard Worker     // for the shader stages, both graphics and compute stages are used.
1797*8975f5c5SAndroid Build Coastguard Worker     VkShaderStageFlags pushConstantShaderStageFlags =
1798*8975f5c5SAndroid Build Coastguard Worker         context->getRenderer()->getSupportedVulkanShaderStageMask();
1799*8975f5c5SAndroid Build Coastguard Worker 
1800*8975f5c5SAndroid Build Coastguard Worker     uint32_t pushConstantSize = GetDriverUniformSize(context, PipelineType::Graphics);
1801*8975f5c5SAndroid Build Coastguard Worker     pipelineLayoutDesc.updatePushConstantRange(pushConstantShaderStageFlags, 0, pushConstantSize);
1802*8975f5c5SAndroid Build Coastguard Worker 
1803*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(pipelineLayoutCache->getPipelineLayout(context, pipelineLayoutDesc,
1804*8975f5c5SAndroid Build Coastguard Worker                                                      mDescriptorSetLayouts, &mPipelineLayout));
1805*8975f5c5SAndroid Build Coastguard Worker 
1806*8975f5c5SAndroid Build Coastguard Worker     mDynamicUniformDescriptorOffsets.clear();
1807*8975f5c5SAndroid Build Coastguard Worker     mDynamicUniformDescriptorOffsets.resize(mExecutable->getLinkedShaderStageCount(), 0);
1808*8975f5c5SAndroid Build Coastguard Worker 
1809*8975f5c5SAndroid Build Coastguard Worker     initializeWriteDescriptorDesc(context);
1810*8975f5c5SAndroid Build Coastguard Worker 
1811*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1812*8975f5c5SAndroid Build Coastguard Worker }
1813*8975f5c5SAndroid Build Coastguard Worker 
initializeDescriptorPools(vk::Context * context,DescriptorSetLayoutCache * descriptorSetLayoutCache,vk::DescriptorSetArray<vk::MetaDescriptorPool> * metaDescriptorPools)1814*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::initializeDescriptorPools(
1815*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1816*8975f5c5SAndroid Build Coastguard Worker     DescriptorSetLayoutCache *descriptorSetLayoutCache,
1817*8975f5c5SAndroid Build Coastguard Worker     vk::DescriptorSetArray<vk::MetaDescriptorPool> *metaDescriptorPools)
1818*8975f5c5SAndroid Build Coastguard Worker {
1819*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY((*metaDescriptorPools)[DescriptorSetIndex::UniformsAndXfb].bindCachedDescriptorPool(
1820*8975f5c5SAndroid Build Coastguard Worker         context, mDefaultUniformAndXfbSetDesc, 1, descriptorSetLayoutCache,
1821*8975f5c5SAndroid Build Coastguard Worker         &mDynamicDescriptorPools[DescriptorSetIndex::UniformsAndXfb]));
1822*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY((*metaDescriptorPools)[DescriptorSetIndex::Texture].bindCachedDescriptorPool(
1823*8975f5c5SAndroid Build Coastguard Worker         context, mTextureSetDesc, mImmutableSamplersMaxDescriptorCount, descriptorSetLayoutCache,
1824*8975f5c5SAndroid Build Coastguard Worker         &mDynamicDescriptorPools[DescriptorSetIndex::Texture]));
1825*8975f5c5SAndroid Build Coastguard Worker     return (*metaDescriptorPools)[DescriptorSetIndex::ShaderResource].bindCachedDescriptorPool(
1826*8975f5c5SAndroid Build Coastguard Worker         context, mShaderResourceSetDesc, 1, descriptorSetLayoutCache,
1827*8975f5c5SAndroid Build Coastguard Worker         &mDynamicDescriptorPools[DescriptorSetIndex::ShaderResource]);
1828*8975f5c5SAndroid Build Coastguard Worker }
1829*8975f5c5SAndroid Build Coastguard Worker 
resolvePrecisionMismatch(const gl::ProgramMergedVaryings & mergedVaryings)1830*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::resolvePrecisionMismatch(const gl::ProgramMergedVaryings &mergedVaryings)
1831*8975f5c5SAndroid Build Coastguard Worker {
1832*8975f5c5SAndroid Build Coastguard Worker     for (const gl::ProgramVaryingRef &mergedVarying : mergedVaryings)
1833*8975f5c5SAndroid Build Coastguard Worker     {
1834*8975f5c5SAndroid Build Coastguard Worker         if (!mergedVarying.frontShader || !mergedVarying.backShader)
1835*8975f5c5SAndroid Build Coastguard Worker         {
1836*8975f5c5SAndroid Build Coastguard Worker             continue;
1837*8975f5c5SAndroid Build Coastguard Worker         }
1838*8975f5c5SAndroid Build Coastguard Worker 
1839*8975f5c5SAndroid Build Coastguard Worker         GLenum frontPrecision = mergedVarying.frontShader->precision;
1840*8975f5c5SAndroid Build Coastguard Worker         GLenum backPrecision  = mergedVarying.backShader->precision;
1841*8975f5c5SAndroid Build Coastguard Worker         if (frontPrecision == backPrecision)
1842*8975f5c5SAndroid Build Coastguard Worker         {
1843*8975f5c5SAndroid Build Coastguard Worker             continue;
1844*8975f5c5SAndroid Build Coastguard Worker         }
1845*8975f5c5SAndroid Build Coastguard Worker 
1846*8975f5c5SAndroid Build Coastguard Worker         ASSERT(frontPrecision >= GL_LOW_FLOAT && frontPrecision <= GL_HIGH_INT);
1847*8975f5c5SAndroid Build Coastguard Worker         ASSERT(backPrecision >= GL_LOW_FLOAT && backPrecision <= GL_HIGH_INT);
1848*8975f5c5SAndroid Build Coastguard Worker 
1849*8975f5c5SAndroid Build Coastguard Worker         if (frontPrecision > backPrecision)
1850*8975f5c5SAndroid Build Coastguard Worker         {
1851*8975f5c5SAndroid Build Coastguard Worker             // The output is higher precision than the input
1852*8975f5c5SAndroid Build Coastguard Worker             ShaderInterfaceVariableInfo &info = mVariableInfoMap.getMutable(
1853*8975f5c5SAndroid Build Coastguard Worker                 mergedVarying.frontShaderStage, mergedVarying.frontShader->id);
1854*8975f5c5SAndroid Build Coastguard Worker             info.varyingIsOutput     = true;
1855*8975f5c5SAndroid Build Coastguard Worker             info.useRelaxedPrecision = true;
1856*8975f5c5SAndroid Build Coastguard Worker         }
1857*8975f5c5SAndroid Build Coastguard Worker         else
1858*8975f5c5SAndroid Build Coastguard Worker         {
1859*8975f5c5SAndroid Build Coastguard Worker             // The output is lower precision than the input, adjust the input
1860*8975f5c5SAndroid Build Coastguard Worker             ASSERT(backPrecision > frontPrecision);
1861*8975f5c5SAndroid Build Coastguard Worker             ShaderInterfaceVariableInfo &info = mVariableInfoMap.getMutable(
1862*8975f5c5SAndroid Build Coastguard Worker                 mergedVarying.backShaderStage, mergedVarying.backShader->id);
1863*8975f5c5SAndroid Build Coastguard Worker             info.varyingIsInput      = true;
1864*8975f5c5SAndroid Build Coastguard Worker             info.useRelaxedPrecision = true;
1865*8975f5c5SAndroid Build Coastguard Worker         }
1866*8975f5c5SAndroid Build Coastguard Worker     }
1867*8975f5c5SAndroid Build Coastguard Worker }
1868*8975f5c5SAndroid Build Coastguard Worker 
getOrAllocateDescriptorSet(vk::Context * context,uint32_t currentFrame,UpdateDescriptorSetsBuilder * updateBuilder,const vk::DescriptorSetDescBuilder & descriptorSetDesc,const vk::WriteDescriptorDescs & writeDescriptorDescs,DescriptorSetIndex setIndex,vk::SharedDescriptorSetCacheKey * newSharedCacheKeyOut)1869*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::getOrAllocateDescriptorSet(
1870*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1871*8975f5c5SAndroid Build Coastguard Worker     uint32_t currentFrame,
1872*8975f5c5SAndroid Build Coastguard Worker     UpdateDescriptorSetsBuilder *updateBuilder,
1873*8975f5c5SAndroid Build Coastguard Worker     const vk::DescriptorSetDescBuilder &descriptorSetDesc,
1874*8975f5c5SAndroid Build Coastguard Worker     const vk::WriteDescriptorDescs &writeDescriptorDescs,
1875*8975f5c5SAndroid Build Coastguard Worker     DescriptorSetIndex setIndex,
1876*8975f5c5SAndroid Build Coastguard Worker     vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut)
1877*8975f5c5SAndroid Build Coastguard Worker {
1878*8975f5c5SAndroid Build Coastguard Worker     vk::Renderer *renderer = context->getRenderer();
1879*8975f5c5SAndroid Build Coastguard Worker 
1880*8975f5c5SAndroid Build Coastguard Worker     if (renderer->getFeatures().descriptorSetCache.enabled)
1881*8975f5c5SAndroid Build Coastguard Worker     {
1882*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mDynamicDescriptorPools[setIndex]->getOrAllocateDescriptorSet(
1883*8975f5c5SAndroid Build Coastguard Worker             context, currentFrame, descriptorSetDesc.getDesc(), *mDescriptorSetLayouts[setIndex],
1884*8975f5c5SAndroid Build Coastguard Worker             &mDescriptorSets[setIndex], newSharedCacheKeyOut));
1885*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mDescriptorSets[setIndex]);
1886*8975f5c5SAndroid Build Coastguard Worker 
1887*8975f5c5SAndroid Build Coastguard Worker         if (*newSharedCacheKeyOut)
1888*8975f5c5SAndroid Build Coastguard Worker         {
1889*8975f5c5SAndroid Build Coastguard Worker             ASSERT((*newSharedCacheKeyOut)->valid());
1890*8975f5c5SAndroid Build Coastguard Worker             // Cache miss. A new cache entry has been created.
1891*8975f5c5SAndroid Build Coastguard Worker             descriptorSetDesc.updateDescriptorSet(renderer, writeDescriptorDescs, updateBuilder,
1892*8975f5c5SAndroid Build Coastguard Worker                                                   mDescriptorSets[setIndex]->getDescriptorSet());
1893*8975f5c5SAndroid Build Coastguard Worker         }
1894*8975f5c5SAndroid Build Coastguard Worker     }
1895*8975f5c5SAndroid Build Coastguard Worker     else
1896*8975f5c5SAndroid Build Coastguard Worker     {
1897*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mDynamicDescriptorPools[setIndex]->allocateDescriptorSet(
1898*8975f5c5SAndroid Build Coastguard Worker             context, *mDescriptorSetLayouts[setIndex], &mDescriptorSets[setIndex]));
1899*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mDescriptorSets[setIndex]);
1900*8975f5c5SAndroid Build Coastguard Worker 
1901*8975f5c5SAndroid Build Coastguard Worker         descriptorSetDesc.updateDescriptorSet(renderer, writeDescriptorDescs, updateBuilder,
1902*8975f5c5SAndroid Build Coastguard Worker                                               mDescriptorSets[setIndex]->getDescriptorSet());
1903*8975f5c5SAndroid Build Coastguard Worker     }
1904*8975f5c5SAndroid Build Coastguard Worker 
1905*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1906*8975f5c5SAndroid Build Coastguard Worker }
1907*8975f5c5SAndroid Build Coastguard Worker 
updateShaderResourcesDescriptorSet(vk::Context * context,uint32_t currentFrame,UpdateDescriptorSetsBuilder * updateBuilder,const vk::WriteDescriptorDescs & writeDescriptorDescs,const vk::DescriptorSetDescBuilder & shaderResourcesDesc,vk::SharedDescriptorSetCacheKey * newSharedCacheKeyOut)1908*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet(
1909*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1910*8975f5c5SAndroid Build Coastguard Worker     uint32_t currentFrame,
1911*8975f5c5SAndroid Build Coastguard Worker     UpdateDescriptorSetsBuilder *updateBuilder,
1912*8975f5c5SAndroid Build Coastguard Worker     const vk::WriteDescriptorDescs &writeDescriptorDescs,
1913*8975f5c5SAndroid Build Coastguard Worker     const vk::DescriptorSetDescBuilder &shaderResourcesDesc,
1914*8975f5c5SAndroid Build Coastguard Worker     vk::SharedDescriptorSetCacheKey *newSharedCacheKeyOut)
1915*8975f5c5SAndroid Build Coastguard Worker {
1916*8975f5c5SAndroid Build Coastguard Worker     if (!mDynamicDescriptorPools[DescriptorSetIndex::ShaderResource])
1917*8975f5c5SAndroid Build Coastguard Worker     {
1918*8975f5c5SAndroid Build Coastguard Worker         (*newSharedCacheKeyOut).reset();
1919*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
1920*8975f5c5SAndroid Build Coastguard Worker     }
1921*8975f5c5SAndroid Build Coastguard Worker 
1922*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(getOrAllocateDescriptorSet(context, currentFrame, updateBuilder, shaderResourcesDesc,
1923*8975f5c5SAndroid Build Coastguard Worker                                          writeDescriptorDescs, DescriptorSetIndex::ShaderResource,
1924*8975f5c5SAndroid Build Coastguard Worker                                          newSharedCacheKeyOut));
1925*8975f5c5SAndroid Build Coastguard Worker 
1926*8975f5c5SAndroid Build Coastguard Worker     size_t numOffsets = writeDescriptorDescs.getDynamicDescriptorSetCount();
1927*8975f5c5SAndroid Build Coastguard Worker     mDynamicShaderResourceDescriptorOffsets.resize(numOffsets);
1928*8975f5c5SAndroid Build Coastguard Worker     if (numOffsets > 0)
1929*8975f5c5SAndroid Build Coastguard Worker     {
1930*8975f5c5SAndroid Build Coastguard Worker         memcpy(mDynamicShaderResourceDescriptorOffsets.data(),
1931*8975f5c5SAndroid Build Coastguard Worker                shaderResourcesDesc.getDynamicOffsets(), numOffsets * sizeof(uint32_t));
1932*8975f5c5SAndroid Build Coastguard Worker     }
1933*8975f5c5SAndroid Build Coastguard Worker 
1934*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
1935*8975f5c5SAndroid Build Coastguard Worker }
1936*8975f5c5SAndroid Build Coastguard Worker 
updateUniformsAndXfbDescriptorSet(vk::Context * context,uint32_t currentFrame,UpdateDescriptorSetsBuilder * updateBuilder,const vk::WriteDescriptorDescs & writeDescriptorDescs,vk::BufferHelper * defaultUniformBuffer,vk::DescriptorSetDescBuilder * uniformsAndXfbDesc,vk::SharedDescriptorSetCacheKey * sharedCacheKeyOut)1937*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::updateUniformsAndXfbDescriptorSet(
1938*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1939*8975f5c5SAndroid Build Coastguard Worker     uint32_t currentFrame,
1940*8975f5c5SAndroid Build Coastguard Worker     UpdateDescriptorSetsBuilder *updateBuilder,
1941*8975f5c5SAndroid Build Coastguard Worker     const vk::WriteDescriptorDescs &writeDescriptorDescs,
1942*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *defaultUniformBuffer,
1943*8975f5c5SAndroid Build Coastguard Worker     vk::DescriptorSetDescBuilder *uniformsAndXfbDesc,
1944*8975f5c5SAndroid Build Coastguard Worker     vk::SharedDescriptorSetCacheKey *sharedCacheKeyOut)
1945*8975f5c5SAndroid Build Coastguard Worker {
1946*8975f5c5SAndroid Build Coastguard Worker     mCurrentDefaultUniformBufferSerial =
1947*8975f5c5SAndroid Build Coastguard Worker         defaultUniformBuffer ? defaultUniformBuffer->getBufferSerial() : vk::kInvalidBufferSerial;
1948*8975f5c5SAndroid Build Coastguard Worker 
1949*8975f5c5SAndroid Build Coastguard Worker     return getOrAllocateDescriptorSet(context, currentFrame, updateBuilder, *uniformsAndXfbDesc,
1950*8975f5c5SAndroid Build Coastguard Worker                                       writeDescriptorDescs, DescriptorSetIndex::UniformsAndXfb,
1951*8975f5c5SAndroid Build Coastguard Worker                                       sharedCacheKeyOut);
1952*8975f5c5SAndroid Build Coastguard Worker }
1953*8975f5c5SAndroid Build Coastguard Worker 
updateTexturesDescriptorSet(vk::Context * context,uint32_t currentFrame,const gl::ActiveTextureArray<TextureVk * > & textures,const gl::SamplerBindingVector & samplers,PipelineType pipelineType,UpdateDescriptorSetsBuilder * updateBuilder)1954*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(
1955*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
1956*8975f5c5SAndroid Build Coastguard Worker     uint32_t currentFrame,
1957*8975f5c5SAndroid Build Coastguard Worker     const gl::ActiveTextureArray<TextureVk *> &textures,
1958*8975f5c5SAndroid Build Coastguard Worker     const gl::SamplerBindingVector &samplers,
1959*8975f5c5SAndroid Build Coastguard Worker     PipelineType pipelineType,
1960*8975f5c5SAndroid Build Coastguard Worker     UpdateDescriptorSetsBuilder *updateBuilder)
1961*8975f5c5SAndroid Build Coastguard Worker {
1962*8975f5c5SAndroid Build Coastguard Worker     if (context->getFeatures().descriptorSetCache.enabled)
1963*8975f5c5SAndroid Build Coastguard Worker     {
1964*8975f5c5SAndroid Build Coastguard Worker         vk::SharedDescriptorSetCacheKey newSharedCacheKey;
1965*8975f5c5SAndroid Build Coastguard Worker 
1966*8975f5c5SAndroid Build Coastguard Worker         // We use textureSerial to optimize texture binding updates. Each permutation of a
1967*8975f5c5SAndroid Build Coastguard Worker         // {VkImage/VkSampler} generates a unique serial. These object ids are combined to form a
1968*8975f5c5SAndroid Build Coastguard Worker         // unique signature for each descriptor set. This allows us to keep a cache of descriptor
1969*8975f5c5SAndroid Build Coastguard Worker         // sets and avoid calling vkAllocateDesctiporSets each texture update.
1970*8975f5c5SAndroid Build Coastguard Worker         vk::DescriptorSetDescBuilder descriptorBuilder;
1971*8975f5c5SAndroid Build Coastguard Worker         descriptorBuilder.updatePreCacheActiveTextures(context, *mExecutable, textures, samplers);
1972*8975f5c5SAndroid Build Coastguard Worker 
1973*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mDynamicDescriptorPools[DescriptorSetIndex::Texture]->getOrAllocateDescriptorSet(
1974*8975f5c5SAndroid Build Coastguard Worker             context, currentFrame, descriptorBuilder.getDesc(),
1975*8975f5c5SAndroid Build Coastguard Worker             *mDescriptorSetLayouts[DescriptorSetIndex::Texture],
1976*8975f5c5SAndroid Build Coastguard Worker             &mDescriptorSets[DescriptorSetIndex::Texture], &newSharedCacheKey));
1977*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mDescriptorSets[DescriptorSetIndex::Texture]);
1978*8975f5c5SAndroid Build Coastguard Worker 
1979*8975f5c5SAndroid Build Coastguard Worker         if (newSharedCacheKey)
1980*8975f5c5SAndroid Build Coastguard Worker         {
1981*8975f5c5SAndroid Build Coastguard Worker             ASSERT(newSharedCacheKey->valid());
1982*8975f5c5SAndroid Build Coastguard Worker             ANGLE_TRY(UpdateFullTexturesDescriptorSet(
1983*8975f5c5SAndroid Build Coastguard Worker                 context, mVariableInfoMap, mTextureWriteDescriptorDescs, updateBuilder,
1984*8975f5c5SAndroid Build Coastguard Worker                 *mExecutable, textures, samplers,
1985*8975f5c5SAndroid Build Coastguard Worker                 mDescriptorSets[DescriptorSetIndex::Texture]->getDescriptorSet()));
1986*8975f5c5SAndroid Build Coastguard Worker 
1987*8975f5c5SAndroid Build Coastguard Worker             const gl::ActiveTextureMask &activeTextureMask = mExecutable->getActiveSamplersMask();
1988*8975f5c5SAndroid Build Coastguard Worker             for (size_t textureUnit : activeTextureMask)
1989*8975f5c5SAndroid Build Coastguard Worker             {
1990*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(textures[textureUnit] != nullptr);
1991*8975f5c5SAndroid Build Coastguard Worker                 textures[textureUnit]->onNewDescriptorSet(newSharedCacheKey);
1992*8975f5c5SAndroid Build Coastguard Worker             }
1993*8975f5c5SAndroid Build Coastguard Worker         }
1994*8975f5c5SAndroid Build Coastguard Worker     }
1995*8975f5c5SAndroid Build Coastguard Worker     else
1996*8975f5c5SAndroid Build Coastguard Worker     {
1997*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mDynamicDescriptorPools[DescriptorSetIndex::Texture]->allocateDescriptorSet(
1998*8975f5c5SAndroid Build Coastguard Worker             context, *mDescriptorSetLayouts[DescriptorSetIndex::Texture],
1999*8975f5c5SAndroid Build Coastguard Worker             &mDescriptorSets[DescriptorSetIndex::Texture]));
2000*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mDescriptorSets[DescriptorSetIndex::Texture]);
2001*8975f5c5SAndroid Build Coastguard Worker 
2002*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(UpdateFullTexturesDescriptorSet(
2003*8975f5c5SAndroid Build Coastguard Worker             context, mVariableInfoMap, mTextureWriteDescriptorDescs, updateBuilder, *mExecutable,
2004*8975f5c5SAndroid Build Coastguard Worker             textures, samplers, mDescriptorSets[DescriptorSetIndex::Texture]->getDescriptorSet()));
2005*8975f5c5SAndroid Build Coastguard Worker     }
2006*8975f5c5SAndroid Build Coastguard Worker 
2007*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2008*8975f5c5SAndroid Build Coastguard Worker }
2009*8975f5c5SAndroid Build Coastguard Worker 
2010*8975f5c5SAndroid Build Coastguard Worker template <typename CommandBufferT>
bindDescriptorSets(vk::Context * context,uint32_t currentFrame,vk::CommandBufferHelperCommon * commandBufferHelper,CommandBufferT * commandBuffer,PipelineType pipelineType)2011*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::bindDescriptorSets(
2012*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
2013*8975f5c5SAndroid Build Coastguard Worker     uint32_t currentFrame,
2014*8975f5c5SAndroid Build Coastguard Worker     vk::CommandBufferHelperCommon *commandBufferHelper,
2015*8975f5c5SAndroid Build Coastguard Worker     CommandBufferT *commandBuffer,
2016*8975f5c5SAndroid Build Coastguard Worker     PipelineType pipelineType)
2017*8975f5c5SAndroid Build Coastguard Worker {
2018*8975f5c5SAndroid Build Coastguard Worker     // Can probably use better dirty bits here.
2019*8975f5c5SAndroid Build Coastguard Worker 
2020*8975f5c5SAndroid Build Coastguard Worker     // Find the maximum non-null descriptor set.  This is used in conjunction with a driver
2021*8975f5c5SAndroid Build Coastguard Worker     // workaround to bind empty descriptor sets only for gaps in between 0 and max and avoid
2022*8975f5c5SAndroid Build Coastguard Worker     // binding unnecessary empty descriptor sets for the sets beyond max.
2023*8975f5c5SAndroid Build Coastguard Worker     DescriptorSetIndex lastNonNullDescriptorSetIndex = DescriptorSetIndex::InvalidEnum;
2024*8975f5c5SAndroid Build Coastguard Worker     for (DescriptorSetIndex descriptorSetIndex : angle::AllEnums<DescriptorSetIndex>())
2025*8975f5c5SAndroid Build Coastguard Worker     {
2026*8975f5c5SAndroid Build Coastguard Worker         if (mDescriptorSets[descriptorSetIndex])
2027*8975f5c5SAndroid Build Coastguard Worker         {
2028*8975f5c5SAndroid Build Coastguard Worker             lastNonNullDescriptorSetIndex = descriptorSetIndex;
2029*8975f5c5SAndroid Build Coastguard Worker         }
2030*8975f5c5SAndroid Build Coastguard Worker     }
2031*8975f5c5SAndroid Build Coastguard Worker 
2032*8975f5c5SAndroid Build Coastguard Worker     const VkPipelineBindPoint pipelineBindPoint = pipelineType == PipelineType::Compute
2033*8975f5c5SAndroid Build Coastguard Worker                                                       ? VK_PIPELINE_BIND_POINT_COMPUTE
2034*8975f5c5SAndroid Build Coastguard Worker                                                       : VK_PIPELINE_BIND_POINT_GRAPHICS;
2035*8975f5c5SAndroid Build Coastguard Worker 
2036*8975f5c5SAndroid Build Coastguard Worker     for (DescriptorSetIndex descriptorSetIndex : angle::AllEnums<DescriptorSetIndex>())
2037*8975f5c5SAndroid Build Coastguard Worker     {
2038*8975f5c5SAndroid Build Coastguard Worker         if (ToUnderlying(descriptorSetIndex) > ToUnderlying(lastNonNullDescriptorSetIndex))
2039*8975f5c5SAndroid Build Coastguard Worker         {
2040*8975f5c5SAndroid Build Coastguard Worker             continue;
2041*8975f5c5SAndroid Build Coastguard Worker         }
2042*8975f5c5SAndroid Build Coastguard Worker 
2043*8975f5c5SAndroid Build Coastguard Worker         if (!mDescriptorSets[descriptorSetIndex])
2044*8975f5c5SAndroid Build Coastguard Worker         {
2045*8975f5c5SAndroid Build Coastguard Worker             continue;
2046*8975f5c5SAndroid Build Coastguard Worker         }
2047*8975f5c5SAndroid Build Coastguard Worker 
2048*8975f5c5SAndroid Build Coastguard Worker         VkDescriptorSet descSet = mDescriptorSets[descriptorSetIndex]->getDescriptorSet();
2049*8975f5c5SAndroid Build Coastguard Worker         ASSERT(descSet != VK_NULL_HANDLE);
2050*8975f5c5SAndroid Build Coastguard Worker 
2051*8975f5c5SAndroid Build Coastguard Worker         // Default uniforms are encompassed in a block per shader stage, and they are assigned
2052*8975f5c5SAndroid Build Coastguard Worker         // through dynamic uniform buffers (requiring dynamic offsets).  No other descriptor
2053*8975f5c5SAndroid Build Coastguard Worker         // requires a dynamic offset.
2054*8975f5c5SAndroid Build Coastguard Worker         if (descriptorSetIndex == DescriptorSetIndex::UniformsAndXfb)
2055*8975f5c5SAndroid Build Coastguard Worker         {
2056*8975f5c5SAndroid Build Coastguard Worker             commandBuffer->bindDescriptorSets(
2057*8975f5c5SAndroid Build Coastguard Worker                 getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet,
2058*8975f5c5SAndroid Build Coastguard Worker                 static_cast<uint32_t>(mDynamicUniformDescriptorOffsets.size()),
2059*8975f5c5SAndroid Build Coastguard Worker                 mDynamicUniformDescriptorOffsets.data());
2060*8975f5c5SAndroid Build Coastguard Worker         }
2061*8975f5c5SAndroid Build Coastguard Worker         else if (descriptorSetIndex == DescriptorSetIndex::ShaderResource)
2062*8975f5c5SAndroid Build Coastguard Worker         {
2063*8975f5c5SAndroid Build Coastguard Worker             commandBuffer->bindDescriptorSets(
2064*8975f5c5SAndroid Build Coastguard Worker                 getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet,
2065*8975f5c5SAndroid Build Coastguard Worker                 static_cast<uint32_t>(mDynamicShaderResourceDescriptorOffsets.size()),
2066*8975f5c5SAndroid Build Coastguard Worker                 mDynamicShaderResourceDescriptorOffsets.data());
2067*8975f5c5SAndroid Build Coastguard Worker         }
2068*8975f5c5SAndroid Build Coastguard Worker         else
2069*8975f5c5SAndroid Build Coastguard Worker         {
2070*8975f5c5SAndroid Build Coastguard Worker             commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint,
2071*8975f5c5SAndroid Build Coastguard Worker                                               descriptorSetIndex, 1, &descSet, 0, nullptr);
2072*8975f5c5SAndroid Build Coastguard Worker         }
2073*8975f5c5SAndroid Build Coastguard Worker 
2074*8975f5c5SAndroid Build Coastguard Worker         commandBufferHelper->retainResource(mDescriptorSets[descriptorSetIndex].get());
2075*8975f5c5SAndroid Build Coastguard Worker         mDescriptorSets[descriptorSetIndex]->updateLastUsedFrame(currentFrame);
2076*8975f5c5SAndroid Build Coastguard Worker     }
2077*8975f5c5SAndroid Build Coastguard Worker 
2078*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2079*8975f5c5SAndroid Build Coastguard Worker }
2080*8975f5c5SAndroid Build Coastguard Worker 
2081*8975f5c5SAndroid Build Coastguard Worker template angle::Result ProgramExecutableVk::bindDescriptorSets<vk::priv::SecondaryCommandBuffer>(
2082*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
2083*8975f5c5SAndroid Build Coastguard Worker     uint32_t currentFrame,
2084*8975f5c5SAndroid Build Coastguard Worker     vk::CommandBufferHelperCommon *commandBufferHelper,
2085*8975f5c5SAndroid Build Coastguard Worker     vk::priv::SecondaryCommandBuffer *commandBuffer,
2086*8975f5c5SAndroid Build Coastguard Worker     PipelineType pipelineType);
2087*8975f5c5SAndroid Build Coastguard Worker template angle::Result ProgramExecutableVk::bindDescriptorSets<vk::VulkanSecondaryCommandBuffer>(
2088*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
2089*8975f5c5SAndroid Build Coastguard Worker     uint32_t currentFrame,
2090*8975f5c5SAndroid Build Coastguard Worker     vk::CommandBufferHelperCommon *commandBufferHelper,
2091*8975f5c5SAndroid Build Coastguard Worker     vk::VulkanSecondaryCommandBuffer *commandBuffer,
2092*8975f5c5SAndroid Build Coastguard Worker     PipelineType pipelineType);
2093*8975f5c5SAndroid Build Coastguard Worker 
setAllDefaultUniformsDirty()2094*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setAllDefaultUniformsDirty()
2095*8975f5c5SAndroid Build Coastguard Worker {
2096*8975f5c5SAndroid Build Coastguard Worker     mDefaultUniformBlocksDirty.reset();
2097*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
2098*8975f5c5SAndroid Build Coastguard Worker     {
2099*8975f5c5SAndroid Build Coastguard Worker         if (!mDefaultUniformBlocks[shaderType]->uniformData.empty())
2100*8975f5c5SAndroid Build Coastguard Worker         {
2101*8975f5c5SAndroid Build Coastguard Worker             mDefaultUniformBlocksDirty.set(shaderType);
2102*8975f5c5SAndroid Build Coastguard Worker         }
2103*8975f5c5SAndroid Build Coastguard Worker     }
2104*8975f5c5SAndroid Build Coastguard Worker }
2105*8975f5c5SAndroid Build Coastguard Worker 
updateUniforms(vk::Context * context,uint32_t currentFrame,UpdateDescriptorSetsBuilder * updateBuilder,vk::BufferHelper * emptyBuffer,vk::DynamicBuffer * defaultUniformStorage,bool isTransformFeedbackActiveUnpaused,TransformFeedbackVk * transformFeedbackVk)2106*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::updateUniforms(vk::Context *context,
2107*8975f5c5SAndroid Build Coastguard Worker                                                   uint32_t currentFrame,
2108*8975f5c5SAndroid Build Coastguard Worker                                                   UpdateDescriptorSetsBuilder *updateBuilder,
2109*8975f5c5SAndroid Build Coastguard Worker                                                   vk::BufferHelper *emptyBuffer,
2110*8975f5c5SAndroid Build Coastguard Worker                                                   vk::DynamicBuffer *defaultUniformStorage,
2111*8975f5c5SAndroid Build Coastguard Worker                                                   bool isTransformFeedbackActiveUnpaused,
2112*8975f5c5SAndroid Build Coastguard Worker                                                   TransformFeedbackVk *transformFeedbackVk)
2113*8975f5c5SAndroid Build Coastguard Worker {
2114*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mDefaultUniformBlocksDirty.any());
2115*8975f5c5SAndroid Build Coastguard Worker 
2116*8975f5c5SAndroid Build Coastguard Worker     vk::BufferHelper *defaultUniformBuffer;
2117*8975f5c5SAndroid Build Coastguard Worker     bool anyNewBufferAllocated          = false;
2118*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderMap<VkDeviceSize> offsets = {};  // offset to the beginning of bufferData
2119*8975f5c5SAndroid Build Coastguard Worker     uint32_t offsetIndex                = 0;
2120*8975f5c5SAndroid Build Coastguard Worker     size_t requiredSpace;
2121*8975f5c5SAndroid Build Coastguard Worker 
2122*8975f5c5SAndroid Build Coastguard Worker     // We usually only update uniform data for shader stages that are actually dirty. But when the
2123*8975f5c5SAndroid Build Coastguard Worker     // buffer for uniform data have switched, because all shader stages are using the same buffer,
2124*8975f5c5SAndroid Build Coastguard Worker     // we then must update uniform data for all shader stages to keep all shader stages' uniform
2125*8975f5c5SAndroid Build Coastguard Worker     // data in the same buffer.
2126*8975f5c5SAndroid Build Coastguard Worker     requiredSpace = calcUniformUpdateRequiredSpace(context, &offsets);
2127*8975f5c5SAndroid Build Coastguard Worker     ASSERT(requiredSpace > 0);
2128*8975f5c5SAndroid Build Coastguard Worker 
2129*8975f5c5SAndroid Build Coastguard Worker     // Allocate space from dynamicBuffer. Always try to allocate from the current buffer first.
2130*8975f5c5SAndroid Build Coastguard Worker     // If that failed, we deal with fall out and try again.
2131*8975f5c5SAndroid Build Coastguard Worker     if (!defaultUniformStorage->allocateFromCurrentBuffer(requiredSpace, &defaultUniformBuffer))
2132*8975f5c5SAndroid Build Coastguard Worker     {
2133*8975f5c5SAndroid Build Coastguard Worker         setAllDefaultUniformsDirty();
2134*8975f5c5SAndroid Build Coastguard Worker 
2135*8975f5c5SAndroid Build Coastguard Worker         requiredSpace = calcUniformUpdateRequiredSpace(context, &offsets);
2136*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(defaultUniformStorage->allocate(context, requiredSpace, &defaultUniformBuffer,
2137*8975f5c5SAndroid Build Coastguard Worker                                                   &anyNewBufferAllocated));
2138*8975f5c5SAndroid Build Coastguard Worker     }
2139*8975f5c5SAndroid Build Coastguard Worker 
2140*8975f5c5SAndroid Build Coastguard Worker     ASSERT(defaultUniformBuffer);
2141*8975f5c5SAndroid Build Coastguard Worker 
2142*8975f5c5SAndroid Build Coastguard Worker     uint8_t *bufferData       = defaultUniformBuffer->getMappedMemory();
2143*8975f5c5SAndroid Build Coastguard Worker     VkDeviceSize bufferOffset = defaultUniformBuffer->getOffset();
2144*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
2145*8975f5c5SAndroid Build Coastguard Worker     {
2146*8975f5c5SAndroid Build Coastguard Worker         if (mDefaultUniformBlocksDirty[shaderType])
2147*8975f5c5SAndroid Build Coastguard Worker         {
2148*8975f5c5SAndroid Build Coastguard Worker             const angle::MemoryBuffer &uniformData = mDefaultUniformBlocks[shaderType]->uniformData;
2149*8975f5c5SAndroid Build Coastguard Worker             memcpy(&bufferData[offsets[shaderType]], uniformData.data(), uniformData.size());
2150*8975f5c5SAndroid Build Coastguard Worker             mDynamicUniformDescriptorOffsets[offsetIndex] =
2151*8975f5c5SAndroid Build Coastguard Worker                 static_cast<uint32_t>(bufferOffset + offsets[shaderType]);
2152*8975f5c5SAndroid Build Coastguard Worker             mDefaultUniformBlocksDirty.reset(shaderType);
2153*8975f5c5SAndroid Build Coastguard Worker         }
2154*8975f5c5SAndroid Build Coastguard Worker         ++offsetIndex;
2155*8975f5c5SAndroid Build Coastguard Worker     }
2156*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(defaultUniformBuffer->flush(context->getRenderer()));
2157*8975f5c5SAndroid Build Coastguard Worker 
2158*8975f5c5SAndroid Build Coastguard Worker     // Because the uniform buffers are per context, we can't rely on dynamicBuffer's allocate
2159*8975f5c5SAndroid Build Coastguard Worker     // function to tell us if you have got a new buffer or not. Other program's use of the buffer
2160*8975f5c5SAndroid Build Coastguard Worker     // might already pushed dynamicBuffer to a new buffer. We record which buffer (represented by
2161*8975f5c5SAndroid Build Coastguard Worker     // the unique BufferSerial number) we were using with the current descriptor set and then we
2162*8975f5c5SAndroid Build Coastguard Worker     // use that recorded BufferSerial compare to the current uniform buffer to quickly detect if
2163*8975f5c5SAndroid Build Coastguard Worker     // there is a buffer switch or not. We need to retrieve from the descriptor set cache or
2164*8975f5c5SAndroid Build Coastguard Worker     // allocate a new descriptor set whenever there is uniform buffer switch.
2165*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentDefaultUniformBufferSerial != defaultUniformBuffer->getBufferSerial())
2166*8975f5c5SAndroid Build Coastguard Worker     {
2167*8975f5c5SAndroid Build Coastguard Worker         // We need to reinitialize the descriptor sets if we newly allocated buffers since we can't
2168*8975f5c5SAndroid Build Coastguard Worker         // modify the descriptor sets once initialized.
2169*8975f5c5SAndroid Build Coastguard Worker         const vk::WriteDescriptorDescs &writeDescriptorDescs =
2170*8975f5c5SAndroid Build Coastguard Worker             getDefaultUniformWriteDescriptorDescs(transformFeedbackVk);
2171*8975f5c5SAndroid Build Coastguard Worker 
2172*8975f5c5SAndroid Build Coastguard Worker         vk::DescriptorSetDescBuilder uniformsAndXfbDesc(
2173*8975f5c5SAndroid Build Coastguard Worker             writeDescriptorDescs.getTotalDescriptorCount());
2174*8975f5c5SAndroid Build Coastguard Worker         uniformsAndXfbDesc.updateUniformsAndXfb(
2175*8975f5c5SAndroid Build Coastguard Worker             context, *mExecutable, writeDescriptorDescs, defaultUniformBuffer, *emptyBuffer,
2176*8975f5c5SAndroid Build Coastguard Worker             isTransformFeedbackActiveUnpaused,
2177*8975f5c5SAndroid Build Coastguard Worker             mExecutable->hasTransformFeedbackOutput() ? transformFeedbackVk : nullptr);
2178*8975f5c5SAndroid Build Coastguard Worker 
2179*8975f5c5SAndroid Build Coastguard Worker         vk::SharedDescriptorSetCacheKey newSharedCacheKey;
2180*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(updateUniformsAndXfbDescriptorSet(context, currentFrame, updateBuilder,
2181*8975f5c5SAndroid Build Coastguard Worker                                                     writeDescriptorDescs, defaultUniformBuffer,
2182*8975f5c5SAndroid Build Coastguard Worker                                                     &uniformsAndXfbDesc, &newSharedCacheKey));
2183*8975f5c5SAndroid Build Coastguard Worker         if (newSharedCacheKey)
2184*8975f5c5SAndroid Build Coastguard Worker         {
2185*8975f5c5SAndroid Build Coastguard Worker             defaultUniformBuffer->getBufferBlock()->onNewDescriptorSet(newSharedCacheKey);
2186*8975f5c5SAndroid Build Coastguard Worker             if (mExecutable->hasTransformFeedbackOutput() &&
2187*8975f5c5SAndroid Build Coastguard Worker                 context->getFeatures().emulateTransformFeedback.enabled)
2188*8975f5c5SAndroid Build Coastguard Worker             {
2189*8975f5c5SAndroid Build Coastguard Worker                 transformFeedbackVk->onNewDescriptorSet(*mExecutable, newSharedCacheKey);
2190*8975f5c5SAndroid Build Coastguard Worker             }
2191*8975f5c5SAndroid Build Coastguard Worker         }
2192*8975f5c5SAndroid Build Coastguard Worker     }
2193*8975f5c5SAndroid Build Coastguard Worker 
2194*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2195*8975f5c5SAndroid Build Coastguard Worker }
2196*8975f5c5SAndroid Build Coastguard Worker 
calcUniformUpdateRequiredSpace(vk::Context * context,gl::ShaderMap<VkDeviceSize> * uniformOffsets) const2197*8975f5c5SAndroid Build Coastguard Worker size_t ProgramExecutableVk::calcUniformUpdateRequiredSpace(
2198*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
2199*8975f5c5SAndroid Build Coastguard Worker     gl::ShaderMap<VkDeviceSize> *uniformOffsets) const
2200*8975f5c5SAndroid Build Coastguard Worker {
2201*8975f5c5SAndroid Build Coastguard Worker     size_t requiredSpace = 0;
2202*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
2203*8975f5c5SAndroid Build Coastguard Worker     {
2204*8975f5c5SAndroid Build Coastguard Worker         if (mDefaultUniformBlocksDirty[shaderType])
2205*8975f5c5SAndroid Build Coastguard Worker         {
2206*8975f5c5SAndroid Build Coastguard Worker             (*uniformOffsets)[shaderType] = requiredSpace;
2207*8975f5c5SAndroid Build Coastguard Worker             requiredSpace += getDefaultUniformAlignedSize(context, shaderType);
2208*8975f5c5SAndroid Build Coastguard Worker         }
2209*8975f5c5SAndroid Build Coastguard Worker     }
2210*8975f5c5SAndroid Build Coastguard Worker     return requiredSpace;
2211*8975f5c5SAndroid Build Coastguard Worker }
2212*8975f5c5SAndroid Build Coastguard Worker 
onProgramBind()2213*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::onProgramBind()
2214*8975f5c5SAndroid Build Coastguard Worker {
2215*8975f5c5SAndroid Build Coastguard Worker     // Because all programs share default uniform buffers, when we switch programs, we have to
2216*8975f5c5SAndroid Build Coastguard Worker     // re-update all uniform data. We could do more tracking to avoid update if the context's
2217*8975f5c5SAndroid Build Coastguard Worker     // current uniform buffer is still the same buffer we last time used and buffer has not been
2218*8975f5c5SAndroid Build Coastguard Worker     // recycled. But statistics gathered on gfxbench shows that app always update uniform data on
2219*8975f5c5SAndroid Build Coastguard Worker     // program bind anyway, so not really worth it to add more tracking logic here.
2220*8975f5c5SAndroid Build Coastguard Worker     //
2221*8975f5c5SAndroid Build Coastguard Worker     // Note: if this is changed, PPO uniform checks need to be updated as well
2222*8975f5c5SAndroid Build Coastguard Worker     setAllDefaultUniformsDirty();
2223*8975f5c5SAndroid Build Coastguard Worker }
2224*8975f5c5SAndroid Build Coastguard Worker 
resizeUniformBlockMemory(vk::Context * context,const gl::ShaderMap<size_t> & requiredBufferSize)2225*8975f5c5SAndroid Build Coastguard Worker angle::Result ProgramExecutableVk::resizeUniformBlockMemory(
2226*8975f5c5SAndroid Build Coastguard Worker     vk::Context *context,
2227*8975f5c5SAndroid Build Coastguard Worker     const gl::ShaderMap<size_t> &requiredBufferSize)
2228*8975f5c5SAndroid Build Coastguard Worker {
2229*8975f5c5SAndroid Build Coastguard Worker     for (gl::ShaderType shaderType : mExecutable->getLinkedShaderStages())
2230*8975f5c5SAndroid Build Coastguard Worker     {
2231*8975f5c5SAndroid Build Coastguard Worker         if (requiredBufferSize[shaderType] > 0)
2232*8975f5c5SAndroid Build Coastguard Worker         {
2233*8975f5c5SAndroid Build Coastguard Worker             if (!mDefaultUniformBlocks[shaderType]->uniformData.resize(
2234*8975f5c5SAndroid Build Coastguard Worker                     requiredBufferSize[shaderType]))
2235*8975f5c5SAndroid Build Coastguard Worker             {
2236*8975f5c5SAndroid Build Coastguard Worker                 ANGLE_VK_CHECK(context, false, VK_ERROR_OUT_OF_HOST_MEMORY);
2237*8975f5c5SAndroid Build Coastguard Worker             }
2238*8975f5c5SAndroid Build Coastguard Worker 
2239*8975f5c5SAndroid Build Coastguard Worker             // Initialize uniform buffer memory to zero by default.
2240*8975f5c5SAndroid Build Coastguard Worker             mDefaultUniformBlocks[shaderType]->uniformData.fill(0);
2241*8975f5c5SAndroid Build Coastguard Worker             mDefaultUniformBlocksDirty.set(shaderType);
2242*8975f5c5SAndroid Build Coastguard Worker         }
2243*8975f5c5SAndroid Build Coastguard Worker     }
2244*8975f5c5SAndroid Build Coastguard Worker 
2245*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
2246*8975f5c5SAndroid Build Coastguard Worker }
2247*8975f5c5SAndroid Build Coastguard Worker 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)2248*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
2249*8975f5c5SAndroid Build Coastguard Worker {
2250*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_FLOAT, &mDefaultUniformBlocks,
2251*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2252*8975f5c5SAndroid Build Coastguard Worker }
2253*8975f5c5SAndroid Build Coastguard Worker 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)2254*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2255*8975f5c5SAndroid Build Coastguard Worker {
2256*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_FLOAT_VEC2, &mDefaultUniformBlocks,
2257*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2258*8975f5c5SAndroid Build Coastguard Worker }
2259*8975f5c5SAndroid Build Coastguard Worker 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)2260*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2261*8975f5c5SAndroid Build Coastguard Worker {
2262*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_FLOAT_VEC3, &mDefaultUniformBlocks,
2263*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2264*8975f5c5SAndroid Build Coastguard Worker }
2265*8975f5c5SAndroid Build Coastguard Worker 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)2266*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2267*8975f5c5SAndroid Build Coastguard Worker {
2268*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_FLOAT_VEC4, &mDefaultUniformBlocks,
2269*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2270*8975f5c5SAndroid Build Coastguard Worker }
2271*8975f5c5SAndroid Build Coastguard Worker 
setUniform1iv(GLint location,GLsizei count,const GLint * v)2272*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform1iv(GLint location, GLsizei count, const GLint *v)
2273*8975f5c5SAndroid Build Coastguard Worker {
2274*8975f5c5SAndroid Build Coastguard Worker     const gl::VariableLocation &locationInfo = mExecutable->getUniformLocations()[location];
2275*8975f5c5SAndroid Build Coastguard Worker     const gl::LinkedUniform &linkedUniform   = mExecutable->getUniforms()[locationInfo.index];
2276*8975f5c5SAndroid Build Coastguard Worker     if (linkedUniform.isSampler())
2277*8975f5c5SAndroid Build Coastguard Worker     {
2278*8975f5c5SAndroid Build Coastguard Worker         // We could potentially cache some indexing here. For now this is a no-op since the mapping
2279*8975f5c5SAndroid Build Coastguard Worker         // is handled entirely in ContextVk.
2280*8975f5c5SAndroid Build Coastguard Worker         return;
2281*8975f5c5SAndroid Build Coastguard Worker     }
2282*8975f5c5SAndroid Build Coastguard Worker 
2283*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_INT, &mDefaultUniformBlocks,
2284*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2285*8975f5c5SAndroid Build Coastguard Worker }
2286*8975f5c5SAndroid Build Coastguard Worker 
setUniform2iv(GLint location,GLsizei count,const GLint * v)2287*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform2iv(GLint location, GLsizei count, const GLint *v)
2288*8975f5c5SAndroid Build Coastguard Worker {
2289*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_INT_VEC2, &mDefaultUniformBlocks,
2290*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2291*8975f5c5SAndroid Build Coastguard Worker }
2292*8975f5c5SAndroid Build Coastguard Worker 
setUniform3iv(GLint location,GLsizei count,const GLint * v)2293*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform3iv(GLint location, GLsizei count, const GLint *v)
2294*8975f5c5SAndroid Build Coastguard Worker {
2295*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_INT_VEC3, &mDefaultUniformBlocks,
2296*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2297*8975f5c5SAndroid Build Coastguard Worker }
2298*8975f5c5SAndroid Build Coastguard Worker 
setUniform4iv(GLint location,GLsizei count,const GLint * v)2299*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform4iv(GLint location, GLsizei count, const GLint *v)
2300*8975f5c5SAndroid Build Coastguard Worker {
2301*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_INT_VEC4, &mDefaultUniformBlocks,
2302*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2303*8975f5c5SAndroid Build Coastguard Worker }
2304*8975f5c5SAndroid Build Coastguard Worker 
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)2305*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
2306*8975f5c5SAndroid Build Coastguard Worker {
2307*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_UNSIGNED_INT, &mDefaultUniformBlocks,
2308*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2309*8975f5c5SAndroid Build Coastguard Worker }
2310*8975f5c5SAndroid Build Coastguard Worker 
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)2311*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
2312*8975f5c5SAndroid Build Coastguard Worker {
2313*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_UNSIGNED_INT_VEC2, &mDefaultUniformBlocks,
2314*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2315*8975f5c5SAndroid Build Coastguard Worker }
2316*8975f5c5SAndroid Build Coastguard Worker 
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)2317*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
2318*8975f5c5SAndroid Build Coastguard Worker {
2319*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_UNSIGNED_INT_VEC3, &mDefaultUniformBlocks,
2320*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2321*8975f5c5SAndroid Build Coastguard Worker }
2322*8975f5c5SAndroid Build Coastguard Worker 
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)2323*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
2324*8975f5c5SAndroid Build Coastguard Worker {
2325*8975f5c5SAndroid Build Coastguard Worker     SetUniform(mExecutable, location, count, v, GL_UNSIGNED_INT_VEC4, &mDefaultUniformBlocks,
2326*8975f5c5SAndroid Build Coastguard Worker                &mDefaultUniformBlocksDirty);
2327*8975f5c5SAndroid Build Coastguard Worker }
2328*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2329*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniformMatrix2fv(GLint location,
2330*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
2331*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
2332*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *value)
2333*8975f5c5SAndroid Build Coastguard Worker {
2334*8975f5c5SAndroid Build Coastguard Worker     SetUniformMatrixfv<2, 2>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
2335*8975f5c5SAndroid Build Coastguard Worker                              &mDefaultUniformBlocksDirty);
2336*8975f5c5SAndroid Build Coastguard Worker }
2337*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2338*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniformMatrix3fv(GLint location,
2339*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
2340*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
2341*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *value)
2342*8975f5c5SAndroid Build Coastguard Worker {
2343*8975f5c5SAndroid Build Coastguard Worker     SetUniformMatrixfv<3, 3>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
2344*8975f5c5SAndroid Build Coastguard Worker                              &mDefaultUniformBlocksDirty);
2345*8975f5c5SAndroid Build Coastguard Worker }
2346*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2347*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniformMatrix4fv(GLint location,
2348*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei count,
2349*8975f5c5SAndroid Build Coastguard Worker                                               GLboolean transpose,
2350*8975f5c5SAndroid Build Coastguard Worker                                               const GLfloat *value)
2351*8975f5c5SAndroid Build Coastguard Worker {
2352*8975f5c5SAndroid Build Coastguard Worker     SetUniformMatrixfv<4, 4>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
2353*8975f5c5SAndroid Build Coastguard Worker                              &mDefaultUniformBlocksDirty);
2354*8975f5c5SAndroid Build Coastguard Worker }
2355*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2356*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniformMatrix2x3fv(GLint location,
2357*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
2358*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
2359*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
2360*8975f5c5SAndroid Build Coastguard Worker {
2361*8975f5c5SAndroid Build Coastguard Worker     SetUniformMatrixfv<2, 3>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
2362*8975f5c5SAndroid Build Coastguard Worker                              &mDefaultUniformBlocksDirty);
2363*8975f5c5SAndroid Build Coastguard Worker }
2364*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2365*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniformMatrix3x2fv(GLint location,
2366*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
2367*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
2368*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
2369*8975f5c5SAndroid Build Coastguard Worker {
2370*8975f5c5SAndroid Build Coastguard Worker     SetUniformMatrixfv<3, 2>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
2371*8975f5c5SAndroid Build Coastguard Worker                              &mDefaultUniformBlocksDirty);
2372*8975f5c5SAndroid Build Coastguard Worker }
2373*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2374*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniformMatrix2x4fv(GLint location,
2375*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
2376*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
2377*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
2378*8975f5c5SAndroid Build Coastguard Worker {
2379*8975f5c5SAndroid Build Coastguard Worker     SetUniformMatrixfv<2, 4>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
2380*8975f5c5SAndroid Build Coastguard Worker                              &mDefaultUniformBlocksDirty);
2381*8975f5c5SAndroid Build Coastguard Worker }
2382*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2383*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniformMatrix4x2fv(GLint location,
2384*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
2385*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
2386*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
2387*8975f5c5SAndroid Build Coastguard Worker {
2388*8975f5c5SAndroid Build Coastguard Worker     SetUniformMatrixfv<4, 2>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
2389*8975f5c5SAndroid Build Coastguard Worker                              &mDefaultUniformBlocksDirty);
2390*8975f5c5SAndroid Build Coastguard Worker }
2391*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2392*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniformMatrix3x4fv(GLint location,
2393*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
2394*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
2395*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
2396*8975f5c5SAndroid Build Coastguard Worker {
2397*8975f5c5SAndroid Build Coastguard Worker     SetUniformMatrixfv<3, 4>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
2398*8975f5c5SAndroid Build Coastguard Worker                              &mDefaultUniformBlocksDirty);
2399*8975f5c5SAndroid Build Coastguard Worker }
2400*8975f5c5SAndroid Build Coastguard Worker 
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)2401*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::setUniformMatrix4x3fv(GLint location,
2402*8975f5c5SAndroid Build Coastguard Worker                                                 GLsizei count,
2403*8975f5c5SAndroid Build Coastguard Worker                                                 GLboolean transpose,
2404*8975f5c5SAndroid Build Coastguard Worker                                                 const GLfloat *value)
2405*8975f5c5SAndroid Build Coastguard Worker {
2406*8975f5c5SAndroid Build Coastguard Worker     SetUniformMatrixfv<4, 3>(mExecutable, location, count, transpose, value, &mDefaultUniformBlocks,
2407*8975f5c5SAndroid Build Coastguard Worker                              &mDefaultUniformBlocksDirty);
2408*8975f5c5SAndroid Build Coastguard Worker }
2409*8975f5c5SAndroid Build Coastguard Worker 
getUniformfv(const gl::Context * context,GLint location,GLfloat * params) const2410*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::getUniformfv(const gl::Context *context,
2411*8975f5c5SAndroid Build Coastguard Worker                                        GLint location,
2412*8975f5c5SAndroid Build Coastguard Worker                                        GLfloat *params) const
2413*8975f5c5SAndroid Build Coastguard Worker {
2414*8975f5c5SAndroid Build Coastguard Worker     GetUniform(mExecutable, location, params, GL_FLOAT, &mDefaultUniformBlocks);
2415*8975f5c5SAndroid Build Coastguard Worker }
2416*8975f5c5SAndroid Build Coastguard Worker 
getUniformiv(const gl::Context * context,GLint location,GLint * params) const2417*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::getUniformiv(const gl::Context *context,
2418*8975f5c5SAndroid Build Coastguard Worker                                        GLint location,
2419*8975f5c5SAndroid Build Coastguard Worker                                        GLint *params) const
2420*8975f5c5SAndroid Build Coastguard Worker {
2421*8975f5c5SAndroid Build Coastguard Worker     GetUniform(mExecutable, location, params, GL_INT, &mDefaultUniformBlocks);
2422*8975f5c5SAndroid Build Coastguard Worker }
2423*8975f5c5SAndroid Build Coastguard Worker 
getUniformuiv(const gl::Context * context,GLint location,GLuint * params) const2424*8975f5c5SAndroid Build Coastguard Worker void ProgramExecutableVk::getUniformuiv(const gl::Context *context,
2425*8975f5c5SAndroid Build Coastguard Worker                                         GLint location,
2426*8975f5c5SAndroid Build Coastguard Worker                                         GLuint *params) const
2427*8975f5c5SAndroid Build Coastguard Worker {
2428*8975f5c5SAndroid Build Coastguard Worker     GetUniform(mExecutable, location, params, GL_UNSIGNED_INT, &mDefaultUniformBlocks);
2429*8975f5c5SAndroid Build Coastguard Worker }
2430*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
2431