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