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