• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2020 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ProgramExecutableVk.cpp: Collects the information and interfaces common to both ProgramVks and
7 // ProgramPipelineVks in order to execute/draw with either.
8 
9 #include "libANGLE/renderer/vulkan/ProgramExecutableVk.h"
10 
11 #include "libANGLE/renderer/glslang_wrapper_utils.h"
12 #include "libANGLE/renderer/vulkan/BufferVk.h"
13 #include "libANGLE/renderer/vulkan/DisplayVk.h"
14 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
15 #include "libANGLE/renderer/vulkan/GlslangWrapperVk.h"
16 #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
17 #include "libANGLE/renderer/vulkan/ProgramVk.h"
18 #include "libANGLE/renderer/vulkan/TextureVk.h"
19 #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
20 #include "libANGLE/renderer/vulkan/vk_helpers.h"
21 #include "libANGLE/renderer/vulkan/vk_utils.h"
22 
23 namespace rx
24 {
25 namespace
26 {
LoadShaderInterfaceVariableXfbInfo(gl::BinaryInputStream * stream,ShaderInterfaceVariableXfbInfo * xfb)27 void LoadShaderInterfaceVariableXfbInfo(gl::BinaryInputStream *stream,
28                                         ShaderInterfaceVariableXfbInfo *xfb)
29 {
30     xfb->buffer        = stream->readInt<uint32_t>();
31     xfb->offset        = stream->readInt<uint32_t>();
32     xfb->stride        = stream->readInt<uint32_t>();
33     xfb->arraySize     = stream->readInt<uint32_t>();
34     xfb->columnCount   = stream->readInt<uint32_t>();
35     xfb->rowCount      = stream->readInt<uint32_t>();
36     xfb->arrayIndex    = stream->readInt<uint32_t>();
37     xfb->componentType = stream->readInt<uint32_t>();
38     xfb->arrayElements.resize(stream->readInt<size_t>());
39     for (ShaderInterfaceVariableXfbInfo &arrayElement : xfb->arrayElements)
40     {
41         LoadShaderInterfaceVariableXfbInfo(stream, &arrayElement);
42     }
43 }
44 
SaveShaderInterfaceVariableXfbInfo(const ShaderInterfaceVariableXfbInfo & xfb,gl::BinaryOutputStream * stream)45 void SaveShaderInterfaceVariableXfbInfo(const ShaderInterfaceVariableXfbInfo &xfb,
46                                         gl::BinaryOutputStream *stream)
47 {
48     stream->writeInt(xfb.buffer);
49     stream->writeInt(xfb.offset);
50     stream->writeInt(xfb.stride);
51     stream->writeInt(xfb.arraySize);
52     stream->writeInt(xfb.columnCount);
53     stream->writeInt(xfb.rowCount);
54     stream->writeInt(xfb.arrayIndex);
55     stream->writeInt(xfb.componentType);
56     stream->writeInt(xfb.arrayElements.size());
57     for (const ShaderInterfaceVariableXfbInfo &arrayElement : xfb.arrayElements)
58     {
59         SaveShaderInterfaceVariableXfbInfo(arrayElement, stream);
60     }
61 }
62 
ValidateTransformedSpirV(const gl::ShaderBitSet & linkedShaderStages,const ShaderInterfaceVariableInfoMap & variableInfoMap,const gl::ShaderMap<angle::spirv::Blob> & spirvBlobs)63 bool ValidateTransformedSpirV(const gl::ShaderBitSet &linkedShaderStages,
64                               const ShaderInterfaceVariableInfoMap &variableInfoMap,
65                               const gl::ShaderMap<angle::spirv::Blob> &spirvBlobs)
66 {
67     const gl::ShaderType lastPreFragmentStage = gl::GetLastPreFragmentStage(linkedShaderStages);
68 
69     for (gl::ShaderType shaderType : linkedShaderStages)
70     {
71         GlslangSpirvOptions options;
72         options.shaderType                         = shaderType;
73         options.preRotation                        = SurfaceRotation::FlippedRotated90Degrees;
74         options.negativeViewportSupported          = false;
75         options.transformPositionToVulkanClipSpace = true;
76         options.removeDebugInfo                    = true;
77         options.isTransformFeedbackStage           = shaderType == lastPreFragmentStage;
78 
79         angle::spirv::Blob transformed;
80         if (GlslangWrapperVk::TransformSpirV(options, variableInfoMap, spirvBlobs[shaderType],
81                                              &transformed) != angle::Result::Continue)
82         {
83             return false;
84         }
85     }
86     return true;
87 }
88 
IsDynamicDescriptor(VkDescriptorType descriptorType)89 constexpr bool IsDynamicDescriptor(VkDescriptorType descriptorType)
90 {
91     switch (descriptorType)
92     {
93         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
94         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
95             return true;
96         default:
97             return false;
98     }
99 }
100 
101 constexpr VkDescriptorType kStorageBufferDescriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
102 
CacheTypeToDescriptorSetIndex(VulkanCacheType cacheType)103 DescriptorSetIndex CacheTypeToDescriptorSetIndex(VulkanCacheType cacheType)
104 {
105     switch (cacheType)
106     {
107         case VulkanCacheType::TextureDescriptors:
108             return DescriptorSetIndex::Texture;
109         case VulkanCacheType::ShaderBuffersDescriptors:
110             return DescriptorSetIndex::ShaderResource;
111         case VulkanCacheType::UniformsAndXfbDescriptors:
112             return DescriptorSetIndex::UniformsAndXfb;
113         case VulkanCacheType::DriverUniformsDescriptors:
114             return DescriptorSetIndex::Internal;
115         default:
116             UNREACHABLE();
117             return DescriptorSetIndex::InvalidEnum;
118     }
119 }
120 }  // namespace
121 
122 DefaultUniformBlock::DefaultUniformBlock() = default;
123 
124 DefaultUniformBlock::~DefaultUniformBlock() = default;
125 
126 // ShaderInfo implementation.
ShaderInfo()127 ShaderInfo::ShaderInfo() {}
128 
129 ShaderInfo::~ShaderInfo() = default;
130 
initShaders(const gl::ShaderBitSet & linkedShaderStages,const gl::ShaderMap<const angle::spirv::Blob * > & spirvBlobs,const ShaderInterfaceVariableInfoMap & variableInfoMap)131 angle::Result ShaderInfo::initShaders(const gl::ShaderBitSet &linkedShaderStages,
132                                       const gl::ShaderMap<const angle::spirv::Blob *> &spirvBlobs,
133                                       const ShaderInterfaceVariableInfoMap &variableInfoMap)
134 {
135     ASSERT(!valid());
136 
137     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
138     {
139         if (spirvBlobs[shaderType] != nullptr)
140         {
141             mSpirvBlobs[shaderType] = *spirvBlobs[shaderType];
142         }
143     }
144 
145     // Assert that SPIR-V transformation is correct, even if the test never issues a draw call.
146     ASSERT(ValidateTransformedSpirV(linkedShaderStages, variableInfoMap, mSpirvBlobs));
147 
148     mIsInitialized = true;
149     return angle::Result::Continue;
150 }
151 
release(ContextVk * contextVk)152 void ShaderInfo::release(ContextVk *contextVk)
153 {
154     for (angle::spirv::Blob &spirvBlob : mSpirvBlobs)
155     {
156         spirvBlob.clear();
157     }
158     mIsInitialized = false;
159 }
160 
load(gl::BinaryInputStream * stream)161 void ShaderInfo::load(gl::BinaryInputStream *stream)
162 {
163     // Read in shader codes for all shader types
164     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
165     {
166         angle::spirv::Blob *spirvBlob = &mSpirvBlobs[shaderType];
167 
168         // Read the SPIR-V
169         stream->readIntVector<uint32_t>(spirvBlob);
170     }
171 
172     mIsInitialized = true;
173 }
174 
save(gl::BinaryOutputStream * stream)175 void ShaderInfo::save(gl::BinaryOutputStream *stream)
176 {
177     ASSERT(valid());
178 
179     // Write out shader codes for all shader types
180     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
181     {
182         const angle::spirv::Blob &spirvBlob = mSpirvBlobs[shaderType];
183 
184         // Write the SPIR-V
185         stream->writeIntVector(spirvBlob);
186     }
187 }
188 
189 // ProgramInfo implementation.
ProgramInfo()190 ProgramInfo::ProgramInfo() {}
191 
192 ProgramInfo::~ProgramInfo() = default;
193 
initProgram(ContextVk * contextVk,const gl::ShaderType shaderType,bool isLastPreFragmentStage,bool isTransformFeedbackProgram,const ShaderInfo & shaderInfo,ProgramTransformOptions optionBits,const ShaderInterfaceVariableInfoMap & variableInfoMap)194 angle::Result ProgramInfo::initProgram(ContextVk *contextVk,
195                                        const gl::ShaderType shaderType,
196                                        bool isLastPreFragmentStage,
197                                        bool isTransformFeedbackProgram,
198                                        const ShaderInfo &shaderInfo,
199                                        ProgramTransformOptions optionBits,
200                                        const ShaderInterfaceVariableInfoMap &variableInfoMap)
201 {
202     const gl::ShaderMap<angle::spirv::Blob> &originalSpirvBlobs = shaderInfo.getSpirvBlobs();
203     const angle::spirv::Blob &originalSpirvBlob                 = originalSpirvBlobs[shaderType];
204     gl::ShaderMap<angle::spirv::Blob> transformedSpirvBlobs;
205     angle::spirv::Blob &transformedSpirvBlob = transformedSpirvBlobs[shaderType];
206 
207     GlslangSpirvOptions options;
208     options.shaderType = shaderType;
209     options.removeEarlyFragmentTestsOptimization =
210         shaderType == gl::ShaderType::Fragment && optionBits.removeEarlyFragmentTestsOptimization;
211     options.removeDebugInfo          = !contextVk->getRenderer()->getEnableValidationLayers();
212     options.isTransformFeedbackStage = isLastPreFragmentStage && isTransformFeedbackProgram &&
213                                        !optionBits.removeTransformFeedbackEmulation;
214     options.isTransformFeedbackEmulated = contextVk->getFeatures().emulateTransformFeedback.enabled;
215     options.negativeViewportSupported   = contextVk->getFeatures().supportsNegativeViewport.enabled;
216 
217     if (isLastPreFragmentStage)
218     {
219         options.preRotation = static_cast<SurfaceRotation>(optionBits.surfaceRotation);
220         options.transformPositionToVulkanClipSpace = optionBits.enableDepthCorrection;
221     }
222 
223     ANGLE_TRY(GlslangWrapperVk::TransformSpirV(options, variableInfoMap, originalSpirvBlob,
224                                                &transformedSpirvBlob));
225     ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
226                                       transformedSpirvBlob.data(),
227                                       transformedSpirvBlob.size() * sizeof(uint32_t)));
228 
229     mProgramHelper.setShader(shaderType, &mShaders[shaderType]);
230 
231     mProgramHelper.setSpecializationConstant(sh::vk::SpecializationConstantId::LineRasterEmulation,
232                                              optionBits.enableLineRasterEmulation);
233     mProgramHelper.setSpecializationConstant(sh::vk::SpecializationConstantId::SurfaceRotation,
234                                              optionBits.surfaceRotation);
235 
236     return angle::Result::Continue;
237 }
238 
release(ContextVk * contextVk)239 void ProgramInfo::release(ContextVk *contextVk)
240 {
241     mProgramHelper.release(contextVk);
242 
243     for (vk::RefCounted<vk::ShaderAndSerial> &shader : mShaders)
244     {
245         shader.get().destroy(contextVk->getDevice());
246     }
247 }
248 
ProgramExecutableVk()249 ProgramExecutableVk::ProgramExecutableVk()
250     : mEmptyDescriptorSets{},
251       mNumDefaultUniformDescriptors(0),
252       mImmutableSamplersMaxDescriptorCount(1),
253       mUniformBufferDescriptorType(VK_DESCRIPTOR_TYPE_MAX_ENUM),
254       mProgram(nullptr),
255       mProgramPipeline(nullptr),
256       mPerfCounters{},
257       mCumulativePerfCounters{}
258 {}
259 
~ProgramExecutableVk()260 ProgramExecutableVk::~ProgramExecutableVk()
261 {
262     outputCumulativePerfCounters();
263 }
264 
reset(ContextVk * contextVk)265 void ProgramExecutableVk::reset(ContextVk *contextVk)
266 {
267     for (auto &descriptorSetLayout : mDescriptorSetLayouts)
268     {
269         descriptorSetLayout.reset();
270     }
271     mImmutableSamplersMaxDescriptorCount = 1;
272     mImmutableSamplerIndexMap.clear();
273     mPipelineLayout.reset();
274 
275     mDescriptorSets.fill(VK_NULL_HANDLE);
276     mEmptyDescriptorSets.fill(VK_NULL_HANDLE);
277     mNumDefaultUniformDescriptors = 0;
278     mTransformOptions             = {};
279 
280     for (vk::RefCountedDescriptorPoolBinding &binding : mDescriptorPoolBindings)
281     {
282         binding.reset();
283     }
284 
285     for (vk::DynamicDescriptorPool &descriptorPool : mDynamicDescriptorPools)
286     {
287         descriptorPool.release(contextVk);
288     }
289 
290     RendererVk *rendererVk = contextVk->getRenderer();
291     mTextureDescriptorsCache.destroy(rendererVk);
292     mUniformsAndXfbDescriptorsCache.destroy(rendererVk);
293     mShaderBufferDescriptorsCache.destroy(rendererVk);
294 
295     // Initialize with a unique BufferSerial
296     vk::ResourceSerialFactory &factory = rendererVk->getResourceSerialFactory();
297     mCurrentDefaultUniformBufferSerial = factory.generateBufferSerial();
298 
299     for (ProgramInfo &programInfo : mGraphicsProgramInfos)
300     {
301         programInfo.release(contextVk);
302     }
303     mComputeProgramInfo.release(contextVk);
304 
305     contextVk->onProgramExecutableReset(this);
306 }
307 
load(gl::BinaryInputStream * stream)308 std::unique_ptr<rx::LinkEvent> ProgramExecutableVk::load(gl::BinaryInputStream *stream)
309 {
310     clearVariableInfoMap();
311 
312     for (gl::ShaderType shaderType : gl::AllShaderTypes())
313     {
314         size_t variableInfoMapSize = stream->readInt<size_t>();
315 
316         for (size_t i = 0; i < variableInfoMapSize; ++i)
317         {
318             const std::string variableName    = stream->readString();
319             ShaderInterfaceVariableInfo &info = mVariableInfoMap.add(shaderType, variableName);
320 
321             info.descriptorSet = stream->readInt<uint32_t>();
322             info.binding       = stream->readInt<uint32_t>();
323             info.location      = stream->readInt<uint32_t>();
324             info.component     = stream->readInt<uint32_t>();
325             info.index         = stream->readInt<uint32_t>();
326             // PackedEnumBitSet uses uint8_t
327             info.activeStages = gl::ShaderBitSet(stream->readInt<uint8_t>());
328             LoadShaderInterfaceVariableXfbInfo(stream, &info.xfb);
329             info.fieldXfb.resize(stream->readInt<size_t>());
330             for (ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
331             {
332                 LoadShaderInterfaceVariableXfbInfo(stream, &xfb);
333             }
334             info.useRelaxedPrecision     = stream->readBool();
335             info.varyingIsInput          = stream->readBool();
336             info.varyingIsOutput         = stream->readBool();
337             info.attributeComponentCount = stream->readInt<uint8_t>();
338             info.attributeLocationCount  = stream->readInt<uint8_t>();
339             info.isDuplicate             = stream->readBool();
340         }
341     }
342 
343     return std::make_unique<LinkEventDone>(angle::Result::Continue);
344 }
345 
save(gl::BinaryOutputStream * stream)346 void ProgramExecutableVk::save(gl::BinaryOutputStream *stream)
347 {
348     for (gl::ShaderType shaderType : gl::AllShaderTypes())
349     {
350         stream->writeInt(mVariableInfoMap.variableCount(shaderType));
351         for (const auto &it : mVariableInfoMap.getIterator(shaderType))
352         {
353             const std::string &name                 = it.first;
354             const ShaderInterfaceVariableInfo &info = it.second;
355 
356             stream->writeString(name);
357             stream->writeInt(info.descriptorSet);
358             stream->writeInt(info.binding);
359             stream->writeInt(info.location);
360             stream->writeInt(info.component);
361             stream->writeInt(info.index);
362             // PackedEnumBitSet uses uint8_t
363             stream->writeInt(info.activeStages.bits());
364             SaveShaderInterfaceVariableXfbInfo(info.xfb, stream);
365             stream->writeInt(info.fieldXfb.size());
366             for (const ShaderInterfaceVariableXfbInfo &xfb : info.fieldXfb)
367             {
368                 SaveShaderInterfaceVariableXfbInfo(xfb, stream);
369             }
370             stream->writeBool(info.useRelaxedPrecision);
371             stream->writeBool(info.varyingIsInput);
372             stream->writeBool(info.varyingIsOutput);
373             stream->writeInt(info.attributeComponentCount);
374             stream->writeInt(info.attributeLocationCount);
375             stream->writeBool(info.isDuplicate);
376         }
377     }
378 }
379 
clearVariableInfoMap()380 void ProgramExecutableVk::clearVariableInfoMap()
381 {
382     mVariableInfoMap.clear();
383 }
384 
getShaderProgram(const gl::State & glState,gl::ShaderType shaderType) const385 ProgramVk *ProgramExecutableVk::getShaderProgram(const gl::State &glState,
386                                                  gl::ShaderType shaderType) const
387 {
388     if (mProgram)
389     {
390         const gl::ProgramExecutable &glExecutable = mProgram->getState().getExecutable();
391         if (glExecutable.hasLinkedShaderStage(shaderType))
392         {
393             return mProgram;
394         }
395     }
396     else if (mProgramPipeline)
397     {
398         return mProgramPipeline->getShaderProgram(shaderType);
399     }
400 
401     return nullptr;
402 }
403 
404 // TODO: http://anglebug.com/3570: Move/Copy all of the necessary information into
405 // the ProgramExecutable, so this function can be removed.
fillProgramStateMap(const ContextVk * contextVk,gl::ShaderMap<const gl::ProgramState * > * programStatesOut)406 void ProgramExecutableVk::fillProgramStateMap(
407     const ContextVk *contextVk,
408     gl::ShaderMap<const gl::ProgramState *> *programStatesOut)
409 {
410     ASSERT(mProgram || mProgramPipeline);
411     if (mProgram)
412     {
413         mProgram->fillProgramStateMap(programStatesOut);
414     }
415     else if (mProgramPipeline)
416     {
417         mProgramPipeline->fillProgramStateMap(programStatesOut);
418     }
419 }
420 
getGlExecutable()421 const gl::ProgramExecutable &ProgramExecutableVk::getGlExecutable()
422 {
423     ASSERT(mProgram || mProgramPipeline);
424     if (mProgram)
425     {
426         return mProgram->getState().getExecutable();
427     }
428     return mProgramPipeline->getState().getExecutable();
429 }
430 
GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> & blocks,uint32_t bufferIndex)431 uint32_t GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> &blocks,
432                                     uint32_t bufferIndex)
433 {
434     const gl::InterfaceBlock &block = blocks[bufferIndex];
435 
436     if (!block.isArray)
437     {
438         return 1;
439     }
440 
441     ASSERT(block.arrayElement == 0);
442 
443     // Search consecutively until all array indices of this block are visited.
444     uint32_t arraySize;
445     for (arraySize = 1; bufferIndex + arraySize < blocks.size(); ++arraySize)
446     {
447         const gl::InterfaceBlock &nextBlock = blocks[bufferIndex + arraySize];
448 
449         if (nextBlock.arrayElement != arraySize)
450         {
451             break;
452         }
453 
454         // It's unexpected for an array to start at a non-zero array size, so we can always rely on
455         // the sequential `arrayElement`s to belong to the same block.
456         ASSERT(nextBlock.name == block.name);
457         ASSERT(nextBlock.isArray);
458     }
459 
460     return arraySize;
461 }
462 
allocUniformAndXfbDescriptorSet(ContextVk * contextVk,const vk::UniformsAndXfbDescriptorDesc & xfbBufferDesc,bool * newDescriptorSetAllocated)463 angle::Result ProgramExecutableVk::allocUniformAndXfbDescriptorSet(
464     ContextVk *contextVk,
465     const vk::UniformsAndXfbDescriptorDesc &xfbBufferDesc,
466     bool *newDescriptorSetAllocated)
467 {
468     mCurrentDefaultUniformBufferSerial = xfbBufferDesc.getDefaultUniformBufferSerial();
469 
470     // Look up in the cache first
471     VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
472     if (mUniformsAndXfbDescriptorsCache.get(xfbBufferDesc, &descriptorSet))
473     {
474         *newDescriptorSetAllocated                          = false;
475         mDescriptorSets[DescriptorSetIndex::UniformsAndXfb] = descriptorSet;
476         // The descriptor pool that this descriptor set was allocated from needs to be retained each
477         // time the descriptor set is used in a new command.
478         mDescriptorPoolBindings[DescriptorSetIndex::UniformsAndXfb].get().retain(
479             &contextVk->getResourceUseList());
480         return angle::Result::Continue;
481     }
482 
483     bool newPoolAllocated;
484     ANGLE_TRY(allocateDescriptorSetAndGetInfo(contextVk, DescriptorSetIndex::UniformsAndXfb,
485                                               &newPoolAllocated));
486 
487     // Clear descriptor set cache. It may no longer be valid.
488     if (newPoolAllocated)
489     {
490         mUniformsAndXfbDescriptorsCache.destroy(contextVk->getRenderer());
491     }
492 
493     // Add the descriptor set into cache
494     mUniformsAndXfbDescriptorsCache.insert(xfbBufferDesc,
495                                            mDescriptorSets[DescriptorSetIndex::UniformsAndXfb]);
496     *newDescriptorSetAllocated = true;
497 
498     return angle::Result::Continue;
499 }
500 
allocateDescriptorSet(ContextVk * contextVk,DescriptorSetIndex descriptorSetIndex)501 angle::Result ProgramExecutableVk::allocateDescriptorSet(ContextVk *contextVk,
502                                                          DescriptorSetIndex descriptorSetIndex)
503 {
504     bool ignoreNewPoolAllocated;
505     return allocateDescriptorSetAndGetInfo(contextVk, descriptorSetIndex, &ignoreNewPoolAllocated);
506 }
507 
allocateDescriptorSetAndGetInfo(ContextVk * contextVk,DescriptorSetIndex descriptorSetIndex,bool * newPoolAllocatedOut)508 angle::Result ProgramExecutableVk::allocateDescriptorSetAndGetInfo(
509     ContextVk *contextVk,
510     DescriptorSetIndex descriptorSetIndex,
511     bool *newPoolAllocatedOut)
512 {
513     vk::DynamicDescriptorPool &dynamicDescriptorPool = mDynamicDescriptorPools[descriptorSetIndex];
514 
515     const vk::DescriptorSetLayout &descriptorSetLayout =
516         mDescriptorSetLayouts[descriptorSetIndex].get();
517     ANGLE_TRY(dynamicDescriptorPool.allocateSetsAndGetInfo(
518         contextVk, descriptorSetLayout.ptr(), 1, &mDescriptorPoolBindings[descriptorSetIndex],
519         &mDescriptorSets[descriptorSetIndex], newPoolAllocatedOut));
520     mEmptyDescriptorSets[descriptorSetIndex] = VK_NULL_HANDLE;
521 
522     ++mPerfCounters.descriptorSetAllocations[descriptorSetIndex];
523 
524     return angle::Result::Continue;
525 }
526 
addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> & blocks,const gl::ShaderType shaderType,VkDescriptorType descType,vk::DescriptorSetLayoutDesc * descOut)527 void ProgramExecutableVk::addInterfaceBlockDescriptorSetDesc(
528     const std::vector<gl::InterfaceBlock> &blocks,
529     const gl::ShaderType shaderType,
530     VkDescriptorType descType,
531     vk::DescriptorSetLayoutDesc *descOut)
532 {
533     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size();)
534     {
535         gl::InterfaceBlock block = blocks[bufferIndex];
536         const uint32_t arraySize = GetInterfaceBlockArraySize(blocks, bufferIndex);
537         bufferIndex += arraySize;
538 
539         if (!block.isActive(shaderType))
540         {
541             continue;
542         }
543 
544         const std::string blockName = block.mappedName;
545 
546         const ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, blockName);
547         if (info.isDuplicate)
548         {
549             continue;
550         }
551 
552         VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
553 
554         descOut->update(info.binding, descType, arraySize, activeStages, nullptr);
555     }
556 }
557 
addAtomicCounterBufferDescriptorSetDesc(const std::vector<gl::AtomicCounterBuffer> & atomicCounterBuffers,const gl::ShaderType shaderType,vk::DescriptorSetLayoutDesc * descOut)558 void ProgramExecutableVk::addAtomicCounterBufferDescriptorSetDesc(
559     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
560     const gl::ShaderType shaderType,
561     vk::DescriptorSetLayoutDesc *descOut)
562 {
563     if (atomicCounterBuffers.empty())
564     {
565         return;
566     }
567 
568     std::string blockName(sh::vk::kAtomicCountersBlockName);
569 
570     const ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, blockName);
571     if (info.isDuplicate || !info.activeStages[shaderType])
572     {
573         return;
574     }
575 
576     VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
577 
578     // A single storage buffer array is used for all stages for simplicity.
579     descOut->update(info.binding, kStorageBufferDescriptorType,
580                     gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, activeStages, nullptr);
581 }
582 
addImageDescriptorSetDesc(const gl::ProgramExecutable & executable,vk::DescriptorSetLayoutDesc * descOut)583 void ProgramExecutableVk::addImageDescriptorSetDesc(const gl::ProgramExecutable &executable,
584                                                     vk::DescriptorSetLayoutDesc *descOut)
585 {
586     const std::vector<gl::ImageBinding> &imageBindings = executable.getImageBindings();
587     const std::vector<gl::LinkedUniform> &uniforms     = executable.getUniforms();
588 
589     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
590     {
591         const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
592         uint32_t uniformIndex                = executable.getUniformIndexFromImageIndex(imageIndex);
593         const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
594 
595         std::string imageName = GlslangGetMappedSamplerName(imageUniform.name);
596 
597         // The front-end always binds array image units sequentially.
598         uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
599 
600         // 2D arrays are split into multiple 1D arrays when generating LinkedUniforms. Since they
601         // are flattened into one array, ignore the nonzero elements and expand the array to the
602         // total array size.
603         if (gl::SamplerNameContainsNonZeroArrayElement(imageUniform.name))
604         {
605             continue;
606         }
607 
608         for (unsigned int outerArraySize : imageUniform.outerArraySizes)
609         {
610             arraySize *= outerArraySize;
611         }
612 
613         for (const gl::ShaderType shaderType : executable.getLinkedShaderStages())
614         {
615             if (!imageUniform.isActive(shaderType))
616             {
617                 continue;
618             }
619 
620             GetImageNameWithoutIndices(&imageName);
621             const ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, imageName);
622             if (info.isDuplicate)
623             {
624                 continue;
625             }
626 
627             VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
628 
629             const VkDescriptorType descType = imageBinding.textureType == gl::TextureType::Buffer
630                                                   ? VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
631                                                   : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
632             descOut->update(info.binding, descType, arraySize, activeStages, nullptr);
633         }
634     }
635 }
636 
addInputAttachmentDescriptorSetDesc(const gl::ProgramExecutable & executable,const gl::ShaderType shaderType,vk::DescriptorSetLayoutDesc * descOut)637 void ProgramExecutableVk::addInputAttachmentDescriptorSetDesc(
638     const gl::ProgramExecutable &executable,
639     const gl::ShaderType shaderType,
640     vk::DescriptorSetLayoutDesc *descOut)
641 {
642     if (shaderType != gl::ShaderType::Fragment)
643     {
644         return;
645     }
646 
647     const std::vector<gl::LinkedUniform> &uniforms = executable.getUniforms();
648 
649     if (!executable.usesFramebufferFetch())
650     {
651         return;
652     }
653 
654     const uint32_t baseUniformIndex              = executable.getFragmentInoutRange().low();
655     const gl::LinkedUniform &baseInputAttachment = uniforms.at(baseUniformIndex);
656     std::string baseMappedName                   = baseInputAttachment.mappedName;
657     ShaderInterfaceVariableInfo &baseInfo        = mVariableInfoMap.get(shaderType, baseMappedName);
658 
659     if (baseInfo.isDuplicate)
660     {
661         return;
662     }
663 
664     uint32_t baseBinding = baseInfo.binding - baseInputAttachment.location;
665 
666     for (uint32_t colorIndex = 0; colorIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorIndex)
667     {
668         descOut->update(baseBinding, VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1,
669                         VK_SHADER_STAGE_FRAGMENT_BIT, nullptr);
670         baseBinding++;
671     }
672 }
673 
addTextureDescriptorSetDesc(ContextVk * contextVk,const gl::ProgramState & programState,const gl::ActiveTextureArray<vk::TextureUnit> * activeTextures,vk::DescriptorSetLayoutDesc * descOut)674 void ProgramExecutableVk::addTextureDescriptorSetDesc(
675     ContextVk *contextVk,
676     const gl::ProgramState &programState,
677     const gl::ActiveTextureArray<vk::TextureUnit> *activeTextures,
678     vk::DescriptorSetLayoutDesc *descOut)
679 {
680     const std::vector<gl::SamplerBinding> &samplerBindings = programState.getSamplerBindings();
681     const std::vector<gl::LinkedUniform> &uniforms         = programState.getUniforms();
682 
683     for (uint32_t textureIndex = 0; textureIndex < samplerBindings.size(); ++textureIndex)
684     {
685         const gl::SamplerBinding &samplerBinding = samplerBindings[textureIndex];
686 
687         uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(textureIndex);
688         const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
689 
690         const std::string samplerName = GlslangGetMappedSamplerName(samplerUniform.name);
691 
692         // The front-end always binds array sampler units sequentially.
693         uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
694 
695         // 2D arrays are split into multiple 1D arrays when generating LinkedUniforms. Since they
696         // are flattened into one array, ignore the nonzero elements and expand the array to the
697         // total array size.
698         if (gl::SamplerNameContainsNonZeroArrayElement(samplerUniform.name))
699         {
700             continue;
701         }
702 
703         for (unsigned int outerArraySize : samplerUniform.outerArraySizes)
704         {
705             arraySize *= outerArraySize;
706         }
707 
708         for (const gl::ShaderType shaderType : programState.getExecutable().getLinkedShaderStages())
709         {
710             if (!samplerUniform.isActive(shaderType))
711             {
712                 continue;
713             }
714 
715             const ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, samplerName);
716             if (info.isDuplicate)
717             {
718                 continue;
719             }
720 
721             VkShaderStageFlags activeStages = gl_vk::GetShaderStageFlags(info.activeStages);
722 
723             // TODO: https://issuetracker.google.com/issues/158215272: how do we handle array of
724             // immutable samplers?
725             GLuint textureUnit = samplerBinding.boundTextureUnits[0];
726             if (activeTextures &&
727                 ((*activeTextures)[textureUnit].texture->getImage().hasImmutableSampler()))
728             {
729                 ASSERT(samplerBinding.boundTextureUnits.size() == 1);
730                 // Always take the texture's sampler, that's only way to get to yuv conversion for
731                 // externalFormat
732                 const TextureVk *textureVk          = (*activeTextures)[textureUnit].texture;
733                 const vk::Sampler &immutableSampler = textureVk->getSampler().get();
734                 descOut->update(info.binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize,
735                                 activeStages, &immutableSampler);
736                 mImmutableSamplerIndexMap[*textureVk->getImage().getYcbcrConversionDesc()] =
737                     textureIndex;
738                 // The Vulkan spec has the following note -
739                 // All descriptors in a binding use the same maximum
740                 // combinedImageSamplerDescriptorCount descriptors to allow implementations to use a
741                 // uniform stride for dynamic indexing of the descriptors in the binding.
742                 uint64_t externalFormat        = textureVk->getImage().getExternalFormat();
743                 VkFormat vkFormat              = textureVk->getImage().getActualVkFormat();
744                 uint32_t formatDescriptorCount = 0;
745                 angle::Result result           = angle::Result::Stop;
746 
747                 if (externalFormat != 0)
748                 {
749                     result = contextVk->getRenderer()->getFormatDescriptorCountForExternalFormat(
750                         contextVk, externalFormat, &formatDescriptorCount);
751                 }
752                 else
753                 {
754                     ASSERT(vkFormat != 0);
755                     result = contextVk->getRenderer()->getFormatDescriptorCountForVkFormat(
756                         contextVk, vkFormat, &formatDescriptorCount);
757                 }
758 
759                 if (result != angle::Result::Continue)
760                 {
761                     // There was an error querying the descriptor count for this format, treat it as
762                     // a non-fatal error and move on.
763                     formatDescriptorCount = 1;
764                 }
765 
766                 ASSERT(formatDescriptorCount > 0);
767                 mImmutableSamplersMaxDescriptorCount =
768                     std::max(mImmutableSamplersMaxDescriptorCount, formatDescriptorCount);
769             }
770             else
771             {
772                 const VkDescriptorType descType =
773                     samplerBinding.textureType == gl::TextureType::Buffer
774                         ? VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
775                         : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
776                 descOut->update(info.binding, descType, arraySize, activeStages, nullptr);
777             }
778         }
779     }
780 }
781 
WriteBufferDescriptorSetBinding(const vk::BufferHelper & buffer,VkDeviceSize offset,VkDeviceSize size,VkDescriptorSet descSet,VkDescriptorType descType,uint32_t bindingIndex,uint32_t arrayElement,VkDeviceSize requiredOffsetAlignment,VkDescriptorBufferInfo * bufferInfoOut,VkWriteDescriptorSet * writeInfoOut)782 void WriteBufferDescriptorSetBinding(const vk::BufferHelper &buffer,
783                                      VkDeviceSize offset,
784                                      VkDeviceSize size,
785                                      VkDescriptorSet descSet,
786                                      VkDescriptorType descType,
787                                      uint32_t bindingIndex,
788                                      uint32_t arrayElement,
789                                      VkDeviceSize requiredOffsetAlignment,
790                                      VkDescriptorBufferInfo *bufferInfoOut,
791                                      VkWriteDescriptorSet *writeInfoOut)
792 {
793     // If requiredOffsetAlignment is 0, the buffer offset is guaranteed to have the necessary
794     // alignment through other means (the backend specifying the alignment through a GLES limit that
795     // the frontend then enforces).  If it's not 0, we need to bind the buffer at an offset that's
796     // aligned.  The difference in offsets is communicated to the shader via driver uniforms.
797     if (requiredOffsetAlignment)
798     {
799         VkDeviceSize alignedOffset = (offset / requiredOffsetAlignment) * requiredOffsetAlignment;
800         VkDeviceSize offsetDiff    = offset - alignedOffset;
801 
802         offset = alignedOffset;
803         size += offsetDiff;
804     }
805 
806     bufferInfoOut->buffer = buffer.getBuffer().getHandle();
807     bufferInfoOut->offset = offset;
808     bufferInfoOut->range  = size;
809 
810     writeInfoOut->sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
811     writeInfoOut->pNext            = nullptr;
812     writeInfoOut->dstSet           = descSet;
813     writeInfoOut->dstBinding       = bindingIndex;
814     writeInfoOut->dstArrayElement  = arrayElement;
815     writeInfoOut->descriptorCount  = 1;
816     writeInfoOut->descriptorType   = descType;
817     writeInfoOut->pImageInfo       = nullptr;
818     writeInfoOut->pBufferInfo      = bufferInfoOut;
819     writeInfoOut->pTexelBufferView = nullptr;
820     ASSERT(writeInfoOut->pBufferInfo[0].buffer != VK_NULL_HANDLE);
821 }
822 
updateEarlyFragmentTestsOptimization(ContextVk * contextVk)823 void ProgramExecutableVk::updateEarlyFragmentTestsOptimization(ContextVk *contextVk)
824 {
825     const gl::State &glState = contextVk->getState();
826 
827     mTransformOptions.removeEarlyFragmentTestsOptimization = false;
828     if (!glState.canEnableEarlyFragmentTestsOptimization())
829     {
830         ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Fragment);
831         if (programVk && programVk->getState().hasEarlyFragmentTestsOptimization())
832         {
833             mTransformOptions.removeEarlyFragmentTestsOptimization = true;
834         }
835     }
836 }
837 
getGraphicsPipeline(ContextVk * contextVk,gl::PrimitiveMode mode,const vk::GraphicsPipelineDesc & desc,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)838 angle::Result ProgramExecutableVk::getGraphicsPipeline(ContextVk *contextVk,
839                                                        gl::PrimitiveMode mode,
840                                                        const vk::GraphicsPipelineDesc &desc,
841                                                        const vk::GraphicsPipelineDesc **descPtrOut,
842                                                        vk::PipelineHelper **pipelineOut)
843 {
844     const gl::State &glState                  = contextVk->getState();
845     RendererVk *renderer                      = contextVk->getRenderer();
846     vk::PipelineCache *pipelineCache          = nullptr;
847     const gl::ProgramExecutable *glExecutable = glState.getProgramExecutable();
848     ASSERT(glExecutable && glExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex));
849 
850     mTransformOptions.enableLineRasterEmulation = contextVk->isBresenhamEmulationEnabled(mode);
851     mTransformOptions.surfaceRotation           = ToUnderlying(desc.getSurfaceRotation());
852     mTransformOptions.enableDepthCorrection     = !glState.isClipControlDepthZeroToOne();
853     mTransformOptions.removeTransformFeedbackEmulation =
854         contextVk->getFeatures().emulateTransformFeedback.enabled &&
855         !glState.isTransformFeedbackActiveUnpaused();
856 
857     // This must be called after mTransformOptions have been set.
858     ProgramInfo &programInfo                  = getGraphicsProgramInfo(mTransformOptions);
859     const gl::ShaderBitSet linkedShaderStages = glExecutable->getLinkedShaderStages();
860     const gl::ShaderType lastPreFragmentStage = gl::GetLastPreFragmentStage(linkedShaderStages);
861 
862     for (const gl::ShaderType shaderType : linkedShaderStages)
863     {
864         ProgramVk *programVk = getShaderProgram(glState, shaderType);
865         if (programVk)
866         {
867             ANGLE_TRY(programVk->initGraphicsShaderProgram(
868                 contextVk, shaderType, shaderType == lastPreFragmentStage, mTransformOptions,
869                 &programInfo, mVariableInfoMap));
870         }
871     }
872 
873     vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
874     ASSERT(shaderProgram);
875 
876     // Drawable size is part of specialization constant, but does not have its own dedicated
877     // programInfo entry. We pick the programInfo entry based on the mTransformOptions and then
878     // update drawable width/height specialization constant. It will go through desc matching and if
879     // spec constant does not match, it will recompile pipeline program.
880     const vk::PackedExtent &dimensions = desc.getDrawableSize();
881     shaderProgram->setSpecializationConstant(sh::vk::SpecializationConstantId::DrawableWidth,
882                                              dimensions.width);
883     shaderProgram->setSpecializationConstant(sh::vk::SpecializationConstantId::DrawableHeight,
884                                              dimensions.height);
885 
886     // Compare the fragment output interface with the framebuffer interface.
887     const gl::ProgramExecutable &executable = *glState.getProgramExecutable();
888 
889     const gl::AttributesMask &activeAttribLocations = executable.getNonBuiltinAttribLocationsMask();
890 
891     // Calculate missing shader outputs.
892     const gl::DrawBufferMask &shaderOutMask = executable.getActiveOutputVariablesMask();
893     gl::DrawBufferMask framebufferMask      = glState.getDrawFramebuffer()->getDrawBufferMask();
894     gl::DrawBufferMask missingOutputsMask   = ~shaderOutMask & framebufferMask;
895 
896     ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
897     return shaderProgram->getGraphicsPipeline(
898         contextVk, &contextVk->getRenderPassCache(), *pipelineCache, getPipelineLayout(), desc,
899         activeAttribLocations, executable.getAttributesTypeMask(), missingOutputsMask, descPtrOut,
900         pipelineOut);
901 }
902 
getComputePipeline(ContextVk * contextVk,vk::PipelineHelper ** pipelineOut)903 angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk,
904                                                       vk::PipelineHelper **pipelineOut)
905 {
906     const gl::State &glState                  = contextVk->getState();
907     const gl::ProgramExecutable *glExecutable = glState.getProgramExecutable();
908     ASSERT(glExecutable && glExecutable->hasLinkedShaderStage(gl::ShaderType::Compute));
909 
910     ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Compute);
911     ASSERT(programVk);
912     ProgramInfo &programInfo = getComputeProgramInfo();
913     ANGLE_TRY(programVk->initComputeProgram(contextVk, &programInfo, mVariableInfoMap));
914 
915     vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
916     ASSERT(shaderProgram);
917     return shaderProgram->getComputePipeline(contextVk, getPipelineLayout(), pipelineOut);
918 }
919 
initDynamicDescriptorPools(ContextVk * contextVk,vk::DescriptorSetLayoutDesc & descriptorSetLayoutDesc,DescriptorSetIndex descriptorSetIndex,VkDescriptorSetLayout descriptorSetLayout)920 angle::Result ProgramExecutableVk::initDynamicDescriptorPools(
921     ContextVk *contextVk,
922     vk::DescriptorSetLayoutDesc &descriptorSetLayoutDesc,
923     DescriptorSetIndex descriptorSetIndex,
924     VkDescriptorSetLayout descriptorSetLayout)
925 {
926     std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
927     vk::DescriptorSetLayoutBindingVector bindingVector;
928     std::vector<VkSampler> immutableSamplers;
929 
930     descriptorSetLayoutDesc.unpackBindings(&bindingVector, &immutableSamplers);
931 
932     for (const VkDescriptorSetLayoutBinding &binding : bindingVector)
933     {
934         if (binding.descriptorCount > 0)
935         {
936             VkDescriptorPoolSize poolSize = {};
937             poolSize.type                 = binding.descriptorType;
938             poolSize.descriptorCount =
939                 binding.descriptorCount * mImmutableSamplersMaxDescriptorCount;
940             descriptorPoolSizes.emplace_back(poolSize);
941         }
942     }
943 
944     RendererVk *renderer = contextVk->getRenderer();
945     if (renderer->getFeatures().bindEmptyForUnusedDescriptorSets.enabled &&
946         descriptorPoolSizes.empty())
947     {
948         // For this workaround, we have to create an empty descriptor set for each descriptor set
949         // index, so make sure their pools are initialized.
950         VkDescriptorPoolSize poolSize = {};
951         // The type doesn't matter, since it's not actually used for anything.
952         poolSize.type            = mUniformBufferDescriptorType;
953         poolSize.descriptorCount = 1;
954         descriptorPoolSizes.emplace_back(poolSize);
955     }
956 
957     if (!descriptorPoolSizes.empty())
958     {
959         ANGLE_TRY(mDynamicDescriptorPools[descriptorSetIndex].init(
960             contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
961             descriptorSetLayout));
962     }
963 
964     return angle::Result::Continue;
965 }
966 
createPipelineLayout(ContextVk * contextVk,const gl::ProgramExecutable & glExecutable,gl::ActiveTextureArray<vk::TextureUnit> * activeTextures)967 angle::Result ProgramExecutableVk::createPipelineLayout(
968     ContextVk *contextVk,
969     const gl::ProgramExecutable &glExecutable,
970     gl::ActiveTextureArray<vk::TextureUnit> *activeTextures)
971 {
972     gl::TransformFeedback *transformFeedback = contextVk->getState().getCurrentTransformFeedback();
973     const gl::ShaderBitSet &linkedShaderStages = glExecutable.getLinkedShaderStages();
974     gl::ShaderMap<const gl::ProgramState *> programStates;
975     fillProgramStateMap(contextVk, &programStates);
976 
977     reset(contextVk);
978 
979     // Store a reference to the pipeline and descriptor set layouts. This will create them if they
980     // don't already exist in the cache.
981 
982     // Default uniforms and transform feedback:
983     vk::DescriptorSetLayoutDesc uniformsAndXfbSetDesc;
984     mNumDefaultUniformDescriptors = 0;
985     for (const gl::ShaderType shaderType : linkedShaderStages)
986     {
987         const std::string uniformBlockName = kDefaultUniformNames[shaderType];
988         const ShaderInterfaceVariableInfo &info =
989             mVariableInfoMap.get(shaderType, uniformBlockName);
990         if (info.isDuplicate || !info.activeStages[shaderType])
991         {
992             continue;
993         }
994 
995         uniformsAndXfbSetDesc.update(info.binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
996                                      gl_vk::kShaderStageMap[shaderType], nullptr);
997         mNumDefaultUniformDescriptors++;
998     }
999 
1000     gl::ShaderType linkedTransformFeedbackStage = glExecutable.getLinkedTransformFeedbackStage();
1001     bool hasXfbVaryings =
1002         linkedTransformFeedbackStage != gl::ShaderType::InvalidEnum &&
1003         !programStates[linkedTransformFeedbackStage]->getLinkedTransformFeedbackVaryings().empty();
1004     if (transformFeedback && hasXfbVaryings)
1005     {
1006         const gl::ProgramExecutable &executable =
1007             programStates[linkedTransformFeedbackStage]->getExecutable();
1008         size_t xfbBufferCount                    = executable.getTransformFeedbackBufferCount();
1009         TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
1010         transformFeedbackVk->updateDescriptorSetLayout(contextVk, mVariableInfoMap, xfbBufferCount,
1011                                                        &uniformsAndXfbSetDesc);
1012     }
1013 
1014     ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1015         contextVk, uniformsAndXfbSetDesc,
1016         &mDescriptorSetLayouts[DescriptorSetIndex::UniformsAndXfb]));
1017 
1018     // Uniform and storage buffers, atomic counter buffers and images:
1019     vk::DescriptorSetLayoutDesc resourcesSetDesc;
1020 
1021     // Count the number of active uniform buffer descriptors.
1022     uint32_t numActiveUniformBufferDescriptors = 0;
1023     for (const gl::ShaderType shaderType : linkedShaderStages)
1024     {
1025         const gl::ProgramState *programState = programStates[shaderType];
1026         ASSERT(programState);
1027 
1028         const std::vector<gl::InterfaceBlock> &blocks = programState->getUniformBlocks();
1029         for (uint32_t bufferIndex = 0; bufferIndex < blocks.size();)
1030         {
1031             const gl::InterfaceBlock &block = blocks[bufferIndex];
1032             const uint32_t arraySize        = GetInterfaceBlockArraySize(blocks, bufferIndex);
1033             bufferIndex += arraySize;
1034 
1035             if (!block.isActive(shaderType))
1036             {
1037                 continue;
1038             }
1039 
1040             numActiveUniformBufferDescriptors += arraySize;
1041         }
1042     }
1043 
1044     // Decide if we should use dynamic or fixed descriptor types.
1045     VkPhysicalDeviceLimits limits = contextVk->getRenderer()->getPhysicalDeviceProperties().limits;
1046     uint32_t totalDynamicUniformBufferCount = numActiveUniformBufferDescriptors +
1047                                               mNumDefaultUniformDescriptors +
1048                                               kReservedDriverUniformBindingCount;
1049     if (totalDynamicUniformBufferCount <= limits.maxDescriptorSetUniformBuffersDynamic)
1050     {
1051         mUniformBufferDescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
1052     }
1053     else
1054     {
1055         mUniformBufferDescriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1056     }
1057 
1058     for (const gl::ShaderType shaderType : linkedShaderStages)
1059     {
1060         const gl::ProgramState *programState = programStates[shaderType];
1061         ASSERT(programState);
1062 
1063         addInterfaceBlockDescriptorSetDesc(programState->getUniformBlocks(), shaderType,
1064                                            mUniformBufferDescriptorType, &resourcesSetDesc);
1065         addInterfaceBlockDescriptorSetDesc(programState->getShaderStorageBlocks(), shaderType,
1066                                            kStorageBufferDescriptorType, &resourcesSetDesc);
1067         addAtomicCounterBufferDescriptorSetDesc(programState->getAtomicCounterBuffers(), shaderType,
1068                                                 &resourcesSetDesc);
1069     }
1070 
1071     for (const gl::ShaderType shaderType : linkedShaderStages)
1072     {
1073         const gl::ProgramState *programState = programStates[shaderType];
1074         ASSERT(programState);
1075         addImageDescriptorSetDesc(programState->getExecutable(), &resourcesSetDesc);
1076         addInputAttachmentDescriptorSetDesc(programState->getExecutable(), shaderType,
1077                                             &resourcesSetDesc);
1078     }
1079 
1080     ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1081         contextVk, resourcesSetDesc, &mDescriptorSetLayouts[DescriptorSetIndex::ShaderResource]));
1082 
1083     // Textures:
1084     vk::DescriptorSetLayoutDesc texturesSetDesc;
1085 
1086     for (const gl::ShaderType shaderType : linkedShaderStages)
1087     {
1088         const gl::ProgramState *programState = programStates[shaderType];
1089         ASSERT(programState);
1090         addTextureDescriptorSetDesc(contextVk, *programState, activeTextures, &texturesSetDesc);
1091     }
1092 
1093     ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1094         contextVk, texturesSetDesc, &mDescriptorSetLayouts[DescriptorSetIndex::Texture]));
1095 
1096     // Driver uniforms
1097     vk::DescriptorSetLayoutDesc driverUniformsSetDesc =
1098         contextVk->getDriverUniformsDescriptorSetDesc();
1099     ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1100         contextVk, driverUniformsSetDesc, &mDescriptorSetLayouts[DescriptorSetIndex::Internal]));
1101 
1102     // Create pipeline layout with these 4 descriptor sets.
1103     vk::PipelineLayoutDesc pipelineLayoutDesc;
1104     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::UniformsAndXfb,
1105                                                  uniformsAndXfbSetDesc);
1106     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::ShaderResource,
1107                                                  resourcesSetDesc);
1108     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Texture, texturesSetDesc);
1109     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Internal,
1110                                                  driverUniformsSetDesc);
1111 
1112     ANGLE_TRY(contextVk->getPipelineLayoutCache().getPipelineLayout(
1113         contextVk, pipelineLayoutDesc, mDescriptorSetLayouts, &mPipelineLayout));
1114 
1115     // Initialize descriptor pools.
1116     ANGLE_TRY(initDynamicDescriptorPools(
1117         contextVk, uniformsAndXfbSetDesc, DescriptorSetIndex::UniformsAndXfb,
1118         mDescriptorSetLayouts[DescriptorSetIndex::UniformsAndXfb].get().getHandle()));
1119     ANGLE_TRY(initDynamicDescriptorPools(
1120         contextVk, resourcesSetDesc, DescriptorSetIndex::ShaderResource,
1121         mDescriptorSetLayouts[DescriptorSetIndex::ShaderResource].get().getHandle()));
1122     ANGLE_TRY(initDynamicDescriptorPools(
1123         contextVk, texturesSetDesc, DescriptorSetIndex::Texture,
1124         mDescriptorSetLayouts[DescriptorSetIndex::Texture].get().getHandle()));
1125     ANGLE_TRY(initDynamicDescriptorPools(
1126         contextVk, driverUniformsSetDesc, DescriptorSetIndex::Internal,
1127         mDescriptorSetLayouts[DescriptorSetIndex::Internal].get().getHandle()));
1128 
1129     mDynamicUniformDescriptorOffsets.clear();
1130     mDynamicUniformDescriptorOffsets.resize(glExecutable.getLinkedShaderStageCount(), 0);
1131 
1132     return angle::Result::Continue;
1133 }
1134 
resolvePrecisionMismatch(const gl::ProgramMergedVaryings & mergedVaryings)1135 void ProgramExecutableVk::resolvePrecisionMismatch(const gl::ProgramMergedVaryings &mergedVaryings)
1136 {
1137     for (const gl::ProgramVaryingRef &mergedVarying : mergedVaryings)
1138     {
1139         if (!mergedVarying.frontShader || !mergedVarying.backShader)
1140         {
1141             continue;
1142         }
1143 
1144         GLenum frontPrecision = mergedVarying.frontShader->precision;
1145         GLenum backPrecision  = mergedVarying.backShader->precision;
1146         if (frontPrecision == backPrecision)
1147         {
1148             continue;
1149         }
1150 
1151         ASSERT(frontPrecision >= GL_LOW_FLOAT && frontPrecision <= GL_HIGH_INT);
1152         ASSERT(backPrecision >= GL_LOW_FLOAT && backPrecision <= GL_HIGH_INT);
1153 
1154         if (frontPrecision > backPrecision)
1155         {
1156             // The output is higher precision than the input
1157             ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(
1158                 mergedVarying.frontShaderStage, mergedVarying.frontShader->mappedName);
1159             info.varyingIsOutput     = true;
1160             info.useRelaxedPrecision = true;
1161         }
1162         else
1163         {
1164             // The output is lower precision than the input, adjust the input
1165             ASSERT(backPrecision > frontPrecision);
1166             ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(
1167                 mergedVarying.backShaderStage, mergedVarying.backShader->mappedName);
1168             info.varyingIsInput      = true;
1169             info.useRelaxedPrecision = true;
1170         }
1171     }
1172 }
1173 
updateDefaultUniformsDescriptorSet(const gl::ShaderType shaderType,const DefaultUniformBlock & defaultUniformBlock,vk::BufferHelper * defaultUniformBuffer,ContextVk * contextVk)1174 void ProgramExecutableVk::updateDefaultUniformsDescriptorSet(
1175     const gl::ShaderType shaderType,
1176     const DefaultUniformBlock &defaultUniformBlock,
1177     vk::BufferHelper *defaultUniformBuffer,
1178     ContextVk *contextVk)
1179 {
1180     const std::string uniformBlockName = kDefaultUniformNames[shaderType];
1181 
1182     const ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, uniformBlockName);
1183     if (info.isDuplicate || !info.activeStages[shaderType])
1184     {
1185         return;
1186     }
1187 
1188     VkWriteDescriptorSet &writeInfo    = contextVk->allocWriteDescriptorSet();
1189     VkDescriptorBufferInfo &bufferInfo = contextVk->allocDescriptorBufferInfo();
1190 
1191     // Size is set to the size of the empty buffer for shader stages with no uniform data,
1192     // otherwise it is set to the total size of the uniform data in the current shader stage
1193     VkDeviceSize size              = defaultUniformBlock.uniformData.size();
1194     vk::BufferHelper *bufferHelper = defaultUniformBuffer;
1195     if (defaultUniformBlock.uniformData.empty())
1196     {
1197         bufferHelper = &contextVk->getEmptyBuffer();
1198         bufferHelper->retainReadOnly(&contextVk->getResourceUseList());
1199         size = bufferHelper->getSize();
1200     }
1201 
1202     WriteBufferDescriptorSetBinding(
1203         *bufferHelper, 0, size, mDescriptorSets[DescriptorSetIndex::UniformsAndXfb],
1204         VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, info.binding, 0, 0, &bufferInfo, &writeInfo);
1205 }
1206 
1207 // Lazily allocate the descriptor set. We may not need one if all of the buffers are inactive.
getOrAllocateShaderResourcesDescriptorSet(ContextVk * contextVk,const vk::ShaderBuffersDescriptorDesc * shaderBuffersDesc,VkDescriptorSet * descriptorSetOut)1208 angle::Result ProgramExecutableVk::getOrAllocateShaderResourcesDescriptorSet(
1209     ContextVk *contextVk,
1210     const vk::ShaderBuffersDescriptorDesc *shaderBuffersDesc,
1211     VkDescriptorSet *descriptorSetOut)
1212 {
1213     if (mDescriptorSets[DescriptorSetIndex::ShaderResource] == VK_NULL_HANDLE)
1214     {
1215         bool newPoolAllocated = false;
1216         ANGLE_TRY(allocateDescriptorSetAndGetInfo(contextVk, DescriptorSetIndex::ShaderResource,
1217                                                   &newPoolAllocated));
1218 
1219         if (shaderBuffersDesc)
1220         {
1221             // Clear descriptor set cache. It may no longer be valid.
1222             if (newPoolAllocated)
1223             {
1224                 mShaderBufferDescriptorsCache.destroy(contextVk->getRenderer());
1225             }
1226 
1227             mShaderBufferDescriptorsCache.insert(
1228                 *shaderBuffersDesc, mDescriptorSets[DescriptorSetIndex::ShaderResource]);
1229         }
1230     }
1231     *descriptorSetOut = mDescriptorSets[DescriptorSetIndex::ShaderResource];
1232     ASSERT(*descriptorSetOut != VK_NULL_HANDLE);
1233     return angle::Result::Continue;
1234 }
1235 
updateBuffersDescriptorSet(ContextVk * contextVk,const gl::ShaderType shaderType,const vk::ShaderBuffersDescriptorDesc & shaderBuffersDesc,const std::vector<gl::InterfaceBlock> & blocks,VkDescriptorType descriptorType,bool cacheHit)1236 angle::Result ProgramExecutableVk::updateBuffersDescriptorSet(
1237     ContextVk *contextVk,
1238     const gl::ShaderType shaderType,
1239     const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc,
1240     const std::vector<gl::InterfaceBlock> &blocks,
1241     VkDescriptorType descriptorType,
1242     bool cacheHit)
1243 {
1244     // Early exit if no blocks or no update needed.
1245     if (blocks.empty() || (cacheHit && !IsDynamicDescriptor(descriptorType)))
1246     {
1247         return angle::Result::Continue;
1248     }
1249 
1250     ASSERT(descriptorType == mUniformBufferDescriptorType ||
1251            descriptorType == kStorageBufferDescriptorType);
1252     const bool isStorageBuffer = descriptorType == kStorageBufferDescriptorType;
1253 
1254     // Write uniform or storage buffers.
1255     const gl::State &glState = contextVk->getState();
1256     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
1257     {
1258         const gl::InterfaceBlock &block = blocks[bufferIndex];
1259         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1260             isStorageBuffer ? glState.getIndexedShaderStorageBuffer(block.binding)
1261                             : glState.getIndexedUniformBuffer(block.binding);
1262 
1263         if (!block.isActive(shaderType))
1264         {
1265             continue;
1266         }
1267 
1268         if (bufferBinding.get() == nullptr)
1269         {
1270             continue;
1271         }
1272 
1273         const ShaderInterfaceVariableInfo &info =
1274             mVariableInfoMap.get(shaderType, block.mappedName);
1275         if (info.isDuplicate)
1276         {
1277             continue;
1278         }
1279 
1280         uint32_t binding      = info.binding;
1281         uint32_t arrayElement = block.isArray ? block.arrayElement : 0;
1282 
1283         VkDeviceSize size;
1284         if (!isStorageBuffer)
1285         {
1286             size = block.dataSize;
1287         }
1288         else
1289         {
1290             size = gl::GetBoundBufferAvailableSize(bufferBinding);
1291         }
1292 
1293         // Make sure there's no possible under/overflow with binding size.
1294         static_assert(sizeof(VkDeviceSize) >= sizeof(bufferBinding.getSize()),
1295                       "VkDeviceSize too small");
1296         ASSERT(bufferBinding.getSize() >= 0);
1297 
1298         BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
1299         VkDeviceSize bufferOffset      = 0;
1300         vk::BufferHelper &bufferHelper = bufferVk->getBufferAndOffset(&bufferOffset);
1301 
1302         if (!cacheHit)
1303         {
1304             VkDescriptorBufferInfo &bufferInfo = contextVk->allocDescriptorBufferInfo();
1305             VkWriteDescriptorSet &writeInfo    = contextVk->allocWriteDescriptorSet();
1306 
1307             VkDescriptorSet descriptorSet;
1308             ANGLE_TRY(getOrAllocateShaderResourcesDescriptorSet(contextVk, &shaderBuffersDesc,
1309                                                                 &descriptorSet));
1310             VkDeviceSize offset =
1311                 IsDynamicDescriptor(descriptorType) ? 0 : bufferOffset + bufferBinding.getOffset();
1312             WriteBufferDescriptorSetBinding(bufferHelper, offset, size, descriptorSet,
1313                                             descriptorType, binding, arrayElement, 0, &bufferInfo,
1314                                             &writeInfo);
1315         }
1316         if (IsDynamicDescriptor(descriptorType))
1317         {
1318             mDynamicShaderBufferDescriptorOffsets.push_back(
1319                 static_cast<uint32_t>(bufferOffset + bufferBinding.getOffset()));
1320         }
1321     }
1322 
1323     return angle::Result::Continue;
1324 }
1325 
updateAtomicCounterBuffersDescriptorSet(ContextVk * contextVk,const gl::ProgramState & programState,const gl::ShaderType shaderType,const vk::ShaderBuffersDescriptorDesc & shaderBuffersDesc,bool cacheHit)1326 angle::Result ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet(
1327     ContextVk *contextVk,
1328     const gl::ProgramState &programState,
1329     const gl::ShaderType shaderType,
1330     const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc,
1331     bool cacheHit)
1332 {
1333     const gl::State &glState = contextVk->getState();
1334     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
1335         programState.getAtomicCounterBuffers();
1336 
1337     if (atomicCounterBuffers.empty() || cacheHit)
1338     {
1339         return angle::Result::Continue;
1340     }
1341 
1342     std::string blockName(sh::vk::kAtomicCountersBlockName);
1343     const ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, blockName);
1344     if (info.isDuplicate || !info.activeStages[shaderType])
1345     {
1346         return angle::Result::Continue;
1347     }
1348 
1349     gl::AtomicCounterBufferMask writtenBindings;
1350 
1351     RendererVk *rendererVk = contextVk->getRenderer();
1352     const VkDeviceSize requiredOffsetAlignment =
1353         rendererVk->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
1354 
1355     VkDescriptorSet descriptorSet;
1356     ANGLE_TRY(
1357         getOrAllocateShaderResourcesDescriptorSet(contextVk, &shaderBuffersDesc, &descriptorSet));
1358 
1359     // Write atomic counter buffers.
1360     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBuffers.size(); ++bufferIndex)
1361     {
1362         const gl::AtomicCounterBuffer &atomicCounterBuffer = atomicCounterBuffers[bufferIndex];
1363         uint32_t binding                                   = atomicCounterBuffer.binding;
1364         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
1365             glState.getIndexedAtomicCounterBuffer(binding);
1366 
1367         if (bufferBinding.get() == nullptr)
1368         {
1369             continue;
1370         }
1371 
1372         static_assert(!IsDynamicDescriptor(kStorageBufferDescriptorType),
1373                       "updateAtomicCounterBuffersDescriptorSet needs an update to handle dynamic "
1374                       "descriptors");
1375 
1376         VkDescriptorBufferInfo &bufferInfo = contextVk->allocDescriptorBufferInfo();
1377         VkWriteDescriptorSet &writeInfo    = contextVk->allocWriteDescriptorSet();
1378 
1379         BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
1380         VkDeviceSize bufferOffset      = 0;
1381         vk::BufferHelper &bufferHelper = bufferVk->getBufferAndOffset(&bufferOffset);
1382 
1383         VkDeviceSize size = gl::GetBoundBufferAvailableSize(bufferBinding);
1384         WriteBufferDescriptorSetBinding(
1385             bufferHelper, static_cast<uint32_t>(bufferOffset + bufferBinding.getOffset()), size,
1386             descriptorSet, kStorageBufferDescriptorType, info.binding, binding,
1387             requiredOffsetAlignment, &bufferInfo, &writeInfo);
1388 
1389         writtenBindings.set(binding);
1390     }
1391 
1392     // Bind the empty buffer to every array slot that's unused.
1393     vk::BufferHelper &emptyBuffer = contextVk->getEmptyBuffer();
1394     emptyBuffer.retainReadOnly(&contextVk->getResourceUseList());
1395     size_t count                        = (~writtenBindings).count();
1396     VkDescriptorBufferInfo *bufferInfos = contextVk->allocDescriptorBufferInfos(count);
1397     VkWriteDescriptorSet *writeInfos    = contextVk->allocWriteDescriptorSets(count);
1398     size_t writeCount                   = 0;
1399     for (size_t binding : ~writtenBindings)
1400     {
1401         WriteBufferDescriptorSetBinding(emptyBuffer, 0, VK_WHOLE_SIZE, descriptorSet,
1402                                         kStorageBufferDescriptorType, info.binding,
1403                                         static_cast<uint32_t>(binding), 0, &bufferInfos[writeCount],
1404                                         &writeInfos[writeCount]);
1405         writeCount++;
1406     }
1407 
1408     return angle::Result::Continue;
1409 }
1410 
updateImagesDescriptorSet(ContextVk * contextVk,const gl::ProgramExecutable & executable,const gl::ShaderType shaderType)1411 angle::Result ProgramExecutableVk::updateImagesDescriptorSet(
1412     ContextVk *contextVk,
1413     const gl::ProgramExecutable &executable,
1414     const gl::ShaderType shaderType)
1415 {
1416     const gl::State &glState                           = contextVk->getState();
1417     RendererVk *renderer                               = contextVk->getRenderer();
1418     const std::vector<gl::ImageBinding> &imageBindings = executable.getImageBindings();
1419     const std::vector<gl::LinkedUniform> &uniforms     = executable.getUniforms();
1420 
1421     if (imageBindings.empty())
1422     {
1423         return angle::Result::Continue;
1424     }
1425 
1426     const gl::ActiveTextureArray<TextureVk *> &activeImages = contextVk->getActiveImages();
1427 
1428     angle::HashMap<std::string, uint32_t> mappedImageNameToArrayOffset;
1429 
1430     // Write images.
1431     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
1432     {
1433         const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
1434         uint32_t uniformIndex                = executable.getUniformIndexFromImageIndex(imageIndex);
1435         const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
1436 
1437         if (!imageUniform.isActive(shaderType))
1438         {
1439             continue;
1440         }
1441 
1442         VkDescriptorSet descriptorSet;
1443         ANGLE_TRY(getOrAllocateShaderResourcesDescriptorSet(contextVk, nullptr, &descriptorSet));
1444 
1445         std::string mappedImageName = GlslangGetMappedSamplerName(imageUniform.name);
1446 
1447         GetImageNameWithoutIndices(&mappedImageName);
1448 
1449         uint32_t arrayOffset = 0;
1450         uint32_t arraySize   = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
1451 
1452         arrayOffset = mappedImageNameToArrayOffset[mappedImageName];
1453         // Front-end generates array elements in order, so we can just increment the offset each
1454         // time we process a nested array.
1455         mappedImageNameToArrayOffset[mappedImageName] += arraySize;
1456 
1457         // Texture buffers use buffer views, so they are especially handled.
1458         if (imageBinding.textureType == gl::TextureType::Buffer)
1459         {
1460             // Handle format reinterpration by looking for a view with the format specified in
1461             // the shader (if any, instead of the format specified to glTexBuffer).
1462             const vk::Format *format = nullptr;
1463             if (imageUniform.imageUnitFormat != GL_NONE)
1464             {
1465                 format = &renderer->getFormat(imageUniform.imageUnitFormat);
1466             }
1467 
1468             const ShaderInterfaceVariableInfo &info =
1469                 mVariableInfoMap.get(shaderType, mappedImageName);
1470             if (info.isDuplicate)
1471             {
1472                 continue;
1473             }
1474 
1475             VkWriteDescriptorSet *writeInfos = contextVk->allocWriteDescriptorSets(arraySize);
1476 
1477             for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
1478             {
1479                 GLuint imageUnit     = imageBinding.boundImageUnits[arrayElement];
1480                 TextureVk *textureVk = activeImages[imageUnit];
1481 
1482                 const vk::BufferView *view = nullptr;
1483                 ANGLE_TRY(textureVk->getBufferViewAndRecordUse(contextVk, format, true, &view));
1484 
1485                 writeInfos[arrayElement].sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1486                 writeInfos[arrayElement].pNext            = nullptr;
1487                 writeInfos[arrayElement].dstSet           = descriptorSet;
1488                 writeInfos[arrayElement].dstBinding       = info.binding;
1489                 writeInfos[arrayElement].dstArrayElement  = arrayOffset + arrayElement;
1490                 writeInfos[arrayElement].descriptorCount  = 1;
1491                 writeInfos[arrayElement].descriptorType   = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
1492                 writeInfos[arrayElement].pImageInfo       = nullptr;
1493                 writeInfos[arrayElement].pBufferInfo      = nullptr;
1494                 writeInfos[arrayElement].pTexelBufferView = view->ptr();
1495             }
1496             continue;
1497         }
1498 
1499         const std::string imageName             = GlslangGetMappedSamplerName(imageUniform.name);
1500         const ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, imageName);
1501         if (info.isDuplicate)
1502         {
1503             continue;
1504         }
1505 
1506         VkWriteDescriptorSet *writeInfos  = contextVk->allocWriteDescriptorSets(arraySize);
1507         VkDescriptorImageInfo *imageInfos = contextVk->allocDescriptorImageInfos(arraySize);
1508         for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
1509         {
1510             GLuint imageUnit             = imageBinding.boundImageUnits[arrayElement];
1511             const gl::ImageUnit &binding = glState.getImageUnit(imageUnit);
1512             TextureVk *textureVk         = activeImages[imageUnit];
1513 
1514             vk::ImageHelper *image         = &textureVk->getImage();
1515             const vk::ImageView *imageView = nullptr;
1516 
1517             ANGLE_TRY(textureVk->getStorageImageView(contextVk, binding, &imageView));
1518 
1519             // Note: binding.access is unused because it is implied by the shader.
1520 
1521             imageInfos[arrayElement].sampler     = VK_NULL_HANDLE;
1522             imageInfos[arrayElement].imageView   = imageView->getHandle();
1523             imageInfos[arrayElement].imageLayout = image->getCurrentLayout();
1524 
1525             writeInfos[arrayElement].sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1526             writeInfos[arrayElement].pNext            = nullptr;
1527             writeInfos[arrayElement].dstSet           = descriptorSet;
1528             writeInfos[arrayElement].dstBinding       = info.binding;
1529             writeInfos[arrayElement].dstArrayElement  = arrayOffset + arrayElement;
1530             writeInfos[arrayElement].descriptorCount  = 1;
1531             writeInfos[arrayElement].descriptorType   = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1532             writeInfos[arrayElement].pImageInfo       = &imageInfos[arrayElement];
1533             writeInfos[arrayElement].pBufferInfo      = nullptr;
1534             writeInfos[arrayElement].pTexelBufferView = nullptr;
1535         }
1536     }
1537 
1538     return angle::Result::Continue;
1539 }
1540 
updateShaderResourcesDescriptorSet(ContextVk * contextVk,FramebufferVk * framebufferVk,const vk::ShaderBuffersDescriptorDesc & shaderBuffersDesc,vk::CommandBufferHelper * commandBufferHelper)1541 angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet(
1542     ContextVk *contextVk,
1543     FramebufferVk *framebufferVk,
1544     const vk::ShaderBuffersDescriptorDesc &shaderBuffersDesc,
1545     vk::CommandBufferHelper *commandBufferHelper)
1546 {
1547     const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
1548     ASSERT(executable);
1549 
1550     // Reset the descriptor set handles so we only allocate a new one when necessary.
1551     mDescriptorSets[DescriptorSetIndex::ShaderResource]      = VK_NULL_HANDLE;
1552     mEmptyDescriptorSets[DescriptorSetIndex::ShaderResource] = VK_NULL_HANDLE;
1553     mDynamicShaderBufferDescriptorOffsets.clear();
1554 
1555     if (!executable->hasImages() && !executable->usesFramebufferFetch())
1556     {
1557         VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
1558         if (mShaderBufferDescriptorsCache.get(shaderBuffersDesc, &descriptorSet))
1559         {
1560             mDescriptorSets[DescriptorSetIndex::ShaderResource] = descriptorSet;
1561             // The descriptor pool that this descriptor set was allocated from needs to be retained
1562             // each time the descriptor set is used in a new command.
1563             mDescriptorPoolBindings[DescriptorSetIndex::ShaderResource].get().retain(
1564                 &contextVk->getResourceUseList());
1565         }
1566     }
1567 
1568     bool cacheHit = mDescriptorSets[DescriptorSetIndex::ShaderResource] != VK_NULL_HANDLE;
1569 
1570     gl::ShaderMap<const gl::ProgramState *> programStates;
1571     fillProgramStateMap(contextVk, &programStates);
1572 
1573     for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
1574     {
1575         const gl::ProgramState *programState = programStates[shaderType];
1576         ASSERT(programState);
1577 
1578         ANGLE_TRY(updateBuffersDescriptorSet(contextVk, shaderType, shaderBuffersDesc,
1579                                              programState->getUniformBlocks(),
1580                                              mUniformBufferDescriptorType, cacheHit));
1581         ANGLE_TRY(updateBuffersDescriptorSet(contextVk, shaderType, shaderBuffersDesc,
1582                                              programState->getShaderStorageBlocks(),
1583                                              kStorageBufferDescriptorType, cacheHit));
1584         ANGLE_TRY(updateAtomicCounterBuffersDescriptorSet(contextVk, *programState, shaderType,
1585                                                           shaderBuffersDesc, cacheHit));
1586         ANGLE_TRY(updateImagesDescriptorSet(contextVk, programState->getExecutable(), shaderType));
1587         ANGLE_TRY(updateInputAttachmentDescriptorSet(programState->getExecutable(), shaderType,
1588                                                      contextVk, framebufferVk));
1589     }
1590 
1591     return angle::Result::Continue;
1592 }
1593 
updateInputAttachmentDescriptorSet(const gl::ProgramExecutable & executable,const gl::ShaderType shaderType,ContextVk * contextVk,FramebufferVk * framebufferVk)1594 angle::Result ProgramExecutableVk::updateInputAttachmentDescriptorSet(
1595     const gl::ProgramExecutable &executable,
1596     const gl::ShaderType shaderType,
1597     ContextVk *contextVk,
1598     FramebufferVk *framebufferVk)
1599 {
1600     if (shaderType != gl::ShaderType::Fragment)
1601     {
1602         return angle::Result::Continue;
1603     }
1604 
1605     const std::vector<gl::LinkedUniform> &uniforms = executable.getUniforms();
1606 
1607     if (!executable.usesFramebufferFetch())
1608     {
1609         return angle::Result::Continue;
1610     }
1611 
1612     const uint32_t baseUniformIndex              = executable.getFragmentInoutRange().low();
1613     const gl::LinkedUniform &baseInputAttachment = uniforms.at(baseUniformIndex);
1614     std::string baseMappedName                   = baseInputAttachment.mappedName;
1615 
1616     ShaderInterfaceVariableInfo &baseInfo = mVariableInfoMap.get(shaderType, baseMappedName);
1617     if (baseInfo.isDuplicate)
1618     {
1619         return angle::Result::Continue;
1620     }
1621 
1622     uint32_t baseBinding = baseInfo.binding - baseInputAttachment.location;
1623 
1624     for (size_t colorIndex : framebufferVk->getState().getColorAttachmentsMask())
1625     {
1626         VkDescriptorSet descriptorSet;
1627         ANGLE_TRY(getOrAllocateShaderResourcesDescriptorSet(contextVk, nullptr, &descriptorSet));
1628 
1629         VkWriteDescriptorSet *writeInfos  = contextVk->allocWriteDescriptorSets(1);
1630         VkDescriptorImageInfo *imageInfos = contextVk->allocDescriptorImageInfos(1);
1631         RenderTargetVk *renderTargetVk    = framebufferVk->getColorDrawRenderTarget(colorIndex);
1632         const vk::ImageView *imageView    = nullptr;
1633 
1634         ANGLE_TRY(renderTargetVk->getImageView(contextVk, &imageView));
1635 
1636         imageInfos[0].sampler     = VK_NULL_HANDLE;
1637         imageInfos[0].imageView   = imageView->getHandle();
1638         imageInfos[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
1639 
1640         writeInfos[0].sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1641         writeInfos[0].pNext            = nullptr;
1642         writeInfos[0].dstSet           = descriptorSet;
1643         writeInfos[0].dstBinding       = baseBinding + static_cast<uint32_t>(colorIndex);
1644         writeInfos[0].dstArrayElement  = 0;
1645         writeInfos[0].descriptorCount  = 1;
1646         writeInfos[0].descriptorType   = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
1647         writeInfos[0].pImageInfo       = &imageInfos[0];
1648         writeInfos[0].pBufferInfo      = nullptr;
1649         writeInfos[0].pTexelBufferView = nullptr;
1650     }
1651 
1652     return angle::Result::Continue;
1653 }
1654 
updateTransformFeedbackDescriptorSet(const gl::ProgramState & programState,gl::ShaderMap<DefaultUniformBlock> & defaultUniformBlocks,vk::BufferHelper * defaultUniformBuffer,ContextVk * contextVk,const vk::UniformsAndXfbDescriptorDesc & xfbBufferDesc)1655 angle::Result ProgramExecutableVk::updateTransformFeedbackDescriptorSet(
1656     const gl::ProgramState &programState,
1657     gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
1658     vk::BufferHelper *defaultUniformBuffer,
1659     ContextVk *contextVk,
1660     const vk::UniformsAndXfbDescriptorDesc &xfbBufferDesc)
1661 {
1662     const gl::ProgramExecutable &executable = programState.getExecutable();
1663     ASSERT(executable.hasTransformFeedbackOutput());
1664 
1665     bool newDescriptorSetAllocated;
1666     ANGLE_TRY(
1667         allocUniformAndXfbDescriptorSet(contextVk, xfbBufferDesc, &newDescriptorSetAllocated));
1668 
1669     if (newDescriptorSetAllocated)
1670     {
1671         for (const gl::ShaderType shaderType : executable.getLinkedShaderStages())
1672         {
1673             updateDefaultUniformsDescriptorSet(shaderType, defaultUniformBlocks[shaderType],
1674                                                defaultUniformBuffer, contextVk);
1675         }
1676         updateTransformFeedbackDescriptorSetImpl(programState, contextVk);
1677     }
1678 
1679     return angle::Result::Continue;
1680 }
1681 
updateTransformFeedbackDescriptorSetImpl(const gl::ProgramState & programState,ContextVk * contextVk)1682 void ProgramExecutableVk::updateTransformFeedbackDescriptorSetImpl(
1683     const gl::ProgramState &programState,
1684     ContextVk *contextVk)
1685 {
1686     const gl::State &glState                 = contextVk->getState();
1687     gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
1688     const gl::ProgramExecutable &executable  = programState.getExecutable();
1689 
1690     if (!executable.hasTransformFeedbackOutput())
1691     {
1692         // If xfb has no output there is no need to update descriptor set.
1693         return;
1694     }
1695     if (!glState.isTransformFeedbackActiveUnpaused())
1696     {
1697         // We set empty Buffer to xfb descriptor set because xfb descriptor set
1698         // requires valid buffer bindings, even if they are empty buffer,
1699         // otherwise Vulkan validation layer generates errors.
1700         if (transformFeedback)
1701         {
1702             TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
1703             transformFeedbackVk->initDescriptorSet(
1704                 contextVk, mVariableInfoMap, executable.getTransformFeedbackBufferCount(),
1705                 mDescriptorSets[DescriptorSetIndex::UniformsAndXfb]);
1706         }
1707         return;
1708     }
1709 
1710     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(glState.getCurrentTransformFeedback());
1711     transformFeedbackVk->updateDescriptorSet(contextVk, programState, mVariableInfoMap,
1712                                              mDescriptorSets[DescriptorSetIndex::UniformsAndXfb]);
1713 }
1714 
updateTexturesDescriptorSet(ContextVk * contextVk,const vk::TextureDescriptorDesc & texturesDesc)1715 angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(
1716     ContextVk *contextVk,
1717     const vk::TextureDescriptorDesc &texturesDesc)
1718 {
1719     const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
1720     ASSERT(executable);
1721 
1722     if (!executable->hasTextures())
1723     {
1724         return angle::Result::Continue;
1725     }
1726 
1727     VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
1728     if (mTextureDescriptorsCache.get(texturesDesc, &descriptorSet))
1729     {
1730         mDescriptorSets[DescriptorSetIndex::Texture] = descriptorSet;
1731         // The descriptor pool that this descriptor set was allocated from needs to be retained each
1732         // time the descriptor set is used in a new command.
1733         mDescriptorPoolBindings[DescriptorSetIndex::Texture].get().retain(
1734             &contextVk->getResourceUseList());
1735         return angle::Result::Continue;
1736     }
1737 
1738     const gl::ActiveTextureArray<vk::TextureUnit> &activeTextures = contextVk->getActiveTextures();
1739     bool emulateSeamfulCubeMapSampling = contextVk->emulateSeamfulCubeMapSampling();
1740 
1741     gl::ShaderMap<const gl::ProgramState *> programStates;
1742     fillProgramStateMap(contextVk, &programStates);
1743 
1744     for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
1745     {
1746         angle::HashMap<std::string, uint32_t> mappedSamplerNameToArrayOffset;
1747         const gl::ProgramState *programState = programStates[shaderType];
1748         ASSERT(programState);
1749         for (uint32_t textureIndex = 0; textureIndex < programState->getSamplerBindings().size();
1750              ++textureIndex)
1751         {
1752             const gl::SamplerBinding &samplerBinding =
1753                 programState->getSamplerBindings()[textureIndex];
1754             uint32_t uniformIndex = programState->getUniformIndexFromSamplerIndex(textureIndex);
1755             const gl::LinkedUniform &samplerUniform = programState->getUniforms()[uniformIndex];
1756             std::string mappedSamplerName = GlslangGetMappedSamplerName(samplerUniform.name);
1757 
1758             if (!samplerUniform.isActive(shaderType))
1759             {
1760                 continue;
1761             }
1762 
1763             const std::string samplerName = GlslangGetMappedSamplerName(samplerUniform.name);
1764 
1765             const ShaderInterfaceVariableInfo &info = mVariableInfoMap.get(shaderType, samplerName);
1766             if (info.isDuplicate)
1767             {
1768                 continue;
1769             }
1770 
1771             // Lazily allocate the descriptor set, since we may not need one if all of the
1772             // sampler uniforms are inactive.
1773             if (descriptorSet == VK_NULL_HANDLE)
1774             {
1775                 bool newPoolAllocated;
1776                 ANGLE_TRY(allocateDescriptorSetAndGetInfo(contextVk, DescriptorSetIndex::Texture,
1777                                                           &newPoolAllocated));
1778 
1779                 // Clear descriptor set cache. It may no longer be valid.
1780                 if (newPoolAllocated)
1781                 {
1782                     mTextureDescriptorsCache.destroy(contextVk->getRenderer());
1783                 }
1784 
1785                 descriptorSet = mDescriptorSets[DescriptorSetIndex::Texture];
1786                 mTextureDescriptorsCache.insert(texturesDesc, descriptorSet);
1787             }
1788             ASSERT(descriptorSet != VK_NULL_HANDLE);
1789 
1790             uint32_t arrayOffset = 0;
1791             uint32_t arraySize   = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
1792 
1793             arrayOffset = mappedSamplerNameToArrayOffset[mappedSamplerName];
1794             // Front-end generates array elements in order, so we can just increment the offset each
1795             // time we process a nested array.
1796             mappedSamplerNameToArrayOffset[mappedSamplerName] += arraySize;
1797 
1798             VkWriteDescriptorSet *writeInfos = contextVk->allocWriteDescriptorSets(arraySize);
1799 
1800             // Texture buffers use buffer views, so they are especially handled.
1801             if (samplerBinding.textureType == gl::TextureType::Buffer)
1802             {
1803                 for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
1804                 {
1805                     GLuint textureUnit         = samplerBinding.boundTextureUnits[arrayElement];
1806                     TextureVk *textureVk       = activeTextures[textureUnit].texture;
1807                     const vk::BufferView *view = nullptr;
1808                     ANGLE_TRY(
1809                         textureVk->getBufferViewAndRecordUse(contextVk, nullptr, false, &view));
1810 
1811                     writeInfos[arrayElement].sType      = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1812                     writeInfos[arrayElement].pNext      = nullptr;
1813                     writeInfos[arrayElement].dstSet     = descriptorSet;
1814                     writeInfos[arrayElement].dstBinding = info.binding;
1815                     writeInfos[arrayElement].dstArrayElement = arrayOffset + arrayElement;
1816                     writeInfos[arrayElement].descriptorCount = 1;
1817                     writeInfos[arrayElement].descriptorType =
1818                         VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
1819                     writeInfos[arrayElement].pImageInfo       = nullptr;
1820                     writeInfos[arrayElement].pBufferInfo      = nullptr;
1821                     writeInfos[arrayElement].pTexelBufferView = view->ptr();
1822                 }
1823                 continue;
1824             }
1825 
1826             VkDescriptorImageInfo *imageInfos = contextVk->allocDescriptorImageInfos(arraySize);
1827             for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
1828             {
1829                 GLuint textureUnit          = samplerBinding.boundTextureUnits[arrayElement];
1830                 const vk::TextureUnit &unit = activeTextures[textureUnit];
1831                 TextureVk *textureVk        = unit.texture;
1832                 const vk::SamplerHelper &samplerHelper = *unit.sampler;
1833 
1834                 vk::ImageHelper &image = textureVk->getImage();
1835 
1836                 imageInfos[arrayElement].sampler     = samplerHelper.get().getHandle();
1837                 imageInfos[arrayElement].imageLayout = image.getCurrentLayout();
1838 
1839                 if (emulateSeamfulCubeMapSampling)
1840                 {
1841                     // If emulating seamful cubemapping, use the fetch image view.  This is
1842                     // basically the same image view as read, except it's a 2DArray view for
1843                     // cube maps.
1844                     const vk::ImageView &imageView = textureVk->getFetchImageViewAndRecordUse(
1845                         contextVk, unit.srgbDecode, samplerUniform.texelFetchStaticUse);
1846                     imageInfos[arrayElement].imageView = imageView.getHandle();
1847                 }
1848                 else
1849                 {
1850                     const vk::ImageView &imageView = textureVk->getReadImageViewAndRecordUse(
1851                         contextVk, unit.srgbDecode, samplerUniform.texelFetchStaticUse);
1852                     imageInfos[arrayElement].imageView = imageView.getHandle();
1853                 }
1854 
1855                 if (textureVk->getImage().hasImmutableSampler())
1856                 {
1857                     imageInfos[arrayElement].sampler = textureVk->getSampler().get().getHandle();
1858                 }
1859 
1860                 writeInfos[arrayElement].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1861                 writeInfos[arrayElement].pNext           = nullptr;
1862                 writeInfos[arrayElement].dstSet          = descriptorSet;
1863                 writeInfos[arrayElement].dstBinding      = info.binding;
1864                 writeInfos[arrayElement].dstArrayElement = arrayOffset + arrayElement;
1865                 writeInfos[arrayElement].descriptorCount = 1;
1866                 writeInfos[arrayElement].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1867                 writeInfos[arrayElement].pImageInfo     = &imageInfos[arrayElement];
1868                 writeInfos[arrayElement].pBufferInfo    = nullptr;
1869                 writeInfos[arrayElement].pTexelBufferView = nullptr;
1870             }
1871         }
1872     }
1873 
1874     return angle::Result::Continue;
1875 }
1876 
updateDescriptorSets(ContextVk * contextVk,vk::CommandBuffer * commandBuffer,PipelineType pipelineType)1877 angle::Result ProgramExecutableVk::updateDescriptorSets(ContextVk *contextVk,
1878                                                         vk::CommandBuffer *commandBuffer,
1879                                                         PipelineType pipelineType)
1880 {
1881     // Can probably use better dirty bits here.
1882 
1883     // Find the maximum non-null descriptor set.  This is used in conjunction with a driver
1884     // workaround to bind empty descriptor sets only for gaps in between 0 and max and avoid
1885     // binding unnecessary empty descriptor sets for the sets beyond max.
1886     DescriptorSetIndex lastNonNullDescriptorSetIndex = DescriptorSetIndex::InvalidEnum;
1887     for (DescriptorSetIndex descriptorSetIndex : angle::AllEnums<DescriptorSetIndex>())
1888     {
1889         if (descriptorSetIndex == DescriptorSetIndex::Internal)
1890         {
1891             continue;
1892         }
1893         if (mDescriptorSets[descriptorSetIndex] != VK_NULL_HANDLE)
1894         {
1895             lastNonNullDescriptorSetIndex = descriptorSetIndex;
1896         }
1897     }
1898 
1899     const VkPipelineBindPoint pipelineBindPoint = pipelineType == PipelineType::Compute
1900                                                       ? VK_PIPELINE_BIND_POINT_COMPUTE
1901                                                       : VK_PIPELINE_BIND_POINT_GRAPHICS;
1902 
1903     for (DescriptorSetIndex descriptorSetIndex : angle::AllEnums<DescriptorSetIndex>())
1904     {
1905         if (descriptorSetIndex == DescriptorSetIndex::Internal ||
1906             ToUnderlying(descriptorSetIndex) > ToUnderlying(lastNonNullDescriptorSetIndex))
1907         {
1908             continue;
1909         }
1910 
1911         VkDescriptorSet descSet = mDescriptorSets[descriptorSetIndex];
1912         if (descSet == VK_NULL_HANDLE)
1913         {
1914             if (!contextVk->getRenderer()->getFeatures().bindEmptyForUnusedDescriptorSets.enabled)
1915             {
1916                 continue;
1917             }
1918 
1919             // Workaround a driver bug where missing (though unused) descriptor sets indices cause
1920             // later sets to misbehave.
1921             if (mEmptyDescriptorSets[descriptorSetIndex] == VK_NULL_HANDLE)
1922             {
1923                 const vk::DescriptorSetLayout &descriptorSetLayout =
1924                     mDescriptorSetLayouts[descriptorSetIndex].get();
1925 
1926                 ANGLE_TRY(mDynamicDescriptorPools[descriptorSetIndex].allocateSets(
1927                     contextVk, descriptorSetLayout.ptr(), 1,
1928                     &mDescriptorPoolBindings[descriptorSetIndex],
1929                     &mEmptyDescriptorSets[descriptorSetIndex]));
1930 
1931                 ++mPerfCounters.descriptorSetAllocations[descriptorSetIndex];
1932             }
1933             descSet = mEmptyDescriptorSets[descriptorSetIndex];
1934         }
1935 
1936         // Default uniforms are encompassed in a block per shader stage, and they are assigned
1937         // through dynamic uniform buffers (requiring dynamic offsets).  No other descriptor
1938         // requires a dynamic offset.
1939         if (descriptorSetIndex == DescriptorSetIndex::UniformsAndXfb)
1940         {
1941             commandBuffer->bindDescriptorSets(
1942                 getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet,
1943                 static_cast<uint32_t>(mDynamicUniformDescriptorOffsets.size()),
1944                 mDynamicUniformDescriptorOffsets.data());
1945         }
1946         else if (descriptorSetIndex == DescriptorSetIndex::ShaderResource)
1947         {
1948             commandBuffer->bindDescriptorSets(
1949                 getPipelineLayout(), pipelineBindPoint, descriptorSetIndex, 1, &descSet,
1950                 static_cast<uint32_t>(mDynamicShaderBufferDescriptorOffsets.size()),
1951                 mDynamicShaderBufferDescriptorOffsets.data());
1952         }
1953         else
1954         {
1955             commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint,
1956                                               descriptorSetIndex, 1, &descSet, 0, nullptr);
1957         }
1958     }
1959 
1960     return angle::Result::Continue;
1961 }
1962 
1963 // Requires that trace is enabled to see the output, which is supported with is_debug=true
outputCumulativePerfCounters()1964 void ProgramExecutableVk::outputCumulativePerfCounters()
1965 {
1966     if (!vk::kOutputCumulativePerfCounters)
1967     {
1968         return;
1969     }
1970 
1971     std::ostringstream text;
1972 
1973     for (DescriptorSetIndex descriptorSetIndex : angle::AllEnums<DescriptorSetIndex>())
1974     {
1975         uint32_t count = mCumulativePerfCounters.descriptorSetAllocations[descriptorSetIndex];
1976         if (count > 0)
1977         {
1978             text << "    DescriptorSetIndex " << ToUnderlying(descriptorSetIndex) << ": " << count
1979                  << "\n";
1980         }
1981     }
1982 
1983     // Only output information for programs that allocated descriptor sets.
1984     std::string textStr = text.str();
1985     if (!textStr.empty())
1986     {
1987         INFO() << "ProgramExecutable: " << this << ":";
1988 
1989         // Output each descriptor set allocation on a single line, so they're prefixed with the
1990         // INFO information (file, line number, etc.).
1991         // https://stackoverflow.com/a/12514641
1992         std::istringstream iss(textStr);
1993         for (std::string line; std::getline(iss, line);)
1994         {
1995             INFO() << line;
1996         }
1997     }
1998 }
1999 
getAndResetObjectPerfCounters()2000 ProgramExecutablePerfCounters ProgramExecutableVk::getAndResetObjectPerfCounters()
2001 {
2002     mUniformsAndXfbDescriptorsCache.accumulateCacheStats(this);
2003     mTextureDescriptorsCache.accumulateCacheStats(this);
2004     mShaderBufferDescriptorsCache.accumulateCacheStats(this);
2005 
2006     mCumulativePerfCounters.descriptorSetAllocations += mPerfCounters.descriptorSetAllocations;
2007     mCumulativePerfCounters.descriptorSetCacheHits += mPerfCounters.descriptorSetCacheHits;
2008     mCumulativePerfCounters.descriptorSetCacheMisses += mPerfCounters.descriptorSetCacheMisses;
2009 
2010     ProgramExecutablePerfCounters counters = mPerfCounters;
2011     mPerfCounters.descriptorSetAllocations = {};
2012     mPerfCounters.descriptorSetCacheHits   = {};
2013     mPerfCounters.descriptorSetCacheMisses = {};
2014     return counters;
2015 }
2016 
accumulateCacheStats(VulkanCacheType cacheType,const CacheStats & cacheStats)2017 void ProgramExecutableVk::accumulateCacheStats(VulkanCacheType cacheType,
2018                                                const CacheStats &cacheStats)
2019 {
2020     DescriptorSetIndex dsIndex = CacheTypeToDescriptorSetIndex(cacheType);
2021 
2022     mPerfCounters.descriptorSetCacheHits[dsIndex] +=
2023         static_cast<uint32_t>(cacheStats.getHitCount());
2024     mPerfCounters.descriptorSetCacheMisses[dsIndex] +=
2025         static_cast<uint32_t>(cacheStats.getMissCount());
2026 }
2027 }  // namespace rx
2028