• 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/GlslangWrapperVk.h"
14 #include "libANGLE/renderer/vulkan/ProgramPipelineVk.h"
15 #include "libANGLE/renderer/vulkan/ProgramVk.h"
16 #include "libANGLE/renderer/vulkan/TextureVk.h"
17 #include "libANGLE/renderer/vulkan/TransformFeedbackVk.h"
18 #include "libANGLE/renderer/vulkan/vk_helpers.h"
19 #include "libANGLE/renderer/vulkan/vk_utils.h"
20 
21 namespace rx
22 {
23 
24 DefaultUniformBlock::DefaultUniformBlock() = default;
25 
26 DefaultUniformBlock::~DefaultUniformBlock() = default;
27 
28 // ShaderInfo implementation.
ShaderInfo()29 ShaderInfo::ShaderInfo() {}
30 
31 ShaderInfo::~ShaderInfo() = default;
32 
initShaders(ContextVk * contextVk,const gl::ShaderMap<std::string> & shaderSources,const ShaderMapInterfaceVariableInfoMap & variableInfoMap)33 angle::Result ShaderInfo::initShaders(ContextVk *contextVk,
34                                       const gl::ShaderMap<std::string> &shaderSources,
35                                       const ShaderMapInterfaceVariableInfoMap &variableInfoMap)
36 {
37     ASSERT(!valid());
38 
39     ANGLE_TRY(GlslangWrapperVk::GetShaderCode(contextVk, contextVk->getCaps(), shaderSources,
40                                               variableInfoMap, &mSpirvBlobs));
41 
42     mIsInitialized = true;
43     return angle::Result::Continue;
44 }
45 
release(ContextVk * contextVk)46 void ShaderInfo::release(ContextVk *contextVk)
47 {
48     for (SpirvBlob &spirvBlob : mSpirvBlobs)
49     {
50         spirvBlob.clear();
51     }
52     mIsInitialized = false;
53 }
54 
load(gl::BinaryInputStream * stream)55 void ShaderInfo::load(gl::BinaryInputStream *stream)
56 {
57     // Read in shader codes for all shader types
58     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
59     {
60         SpirvBlob *spirvBlob = &mSpirvBlobs[shaderType];
61 
62         // Read the SPIR-V
63         stream->readIntVector<uint32_t>(spirvBlob);
64     }
65 
66     mIsInitialized = true;
67 }
68 
save(gl::BinaryOutputStream * stream)69 void ShaderInfo::save(gl::BinaryOutputStream *stream)
70 {
71     ASSERT(valid());
72 
73     // Write out shader codes for all shader types
74     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
75     {
76         const SpirvBlob &spirvBlob = mSpirvBlobs[shaderType];
77 
78         // Write the SPIR-V
79         stream->writeIntVector(spirvBlob);
80     }
81 }
82 
83 // ProgramInfo implementation.
ProgramInfo()84 ProgramInfo::ProgramInfo() {}
85 
86 ProgramInfo::~ProgramInfo() = default;
87 
initProgram(ContextVk * contextVk,const gl::ShaderType shaderType,const ShaderInfo & shaderInfo,const ShaderMapInterfaceVariableInfoMap & variableInfoMap,ProgramTransformOptionBits optionBits)88 angle::Result ProgramInfo::initProgram(ContextVk *contextVk,
89                                        const gl::ShaderType shaderType,
90                                        const ShaderInfo &shaderInfo,
91                                        const ShaderMapInterfaceVariableInfoMap &variableInfoMap,
92                                        ProgramTransformOptionBits optionBits)
93 {
94     const gl::ShaderMap<SpirvBlob> &spirvBlobs = shaderInfo.getSpirvBlobs();
95 
96     const SpirvBlob &spirvBlob = spirvBlobs[shaderType];
97 
98     if (!spirvBlob.empty())
99     {
100         if (shaderType == gl::ShaderType::Fragment &&
101             optionBits[ProgramTransformOption::RemoveEarlyFragmentTestsOptimization])
102         {
103             SpirvBlob spirvBlobTransformed;
104             ANGLE_TRY(GlslangWrapperVk::TransformSpirV(contextVk, shaderType, true,
105                                                        variableInfoMap[shaderType], spirvBlob,
106                                                        &spirvBlobTransformed));
107             ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
108                                               spirvBlobTransformed.data(),
109                                               spirvBlobTransformed.size() * sizeof(uint32_t)));
110         }
111         else
112         {
113             ANGLE_TRY(vk::InitShaderAndSerial(contextVk, &mShaders[shaderType].get(),
114                                               spirvBlob.data(),
115                                               spirvBlob.size() * sizeof(uint32_t)));
116         }
117 
118         mProgramHelper.setShader(shaderType, &mShaders[shaderType]);
119     }
120 
121     if (optionBits[ProgramTransformOption::EnableLineRasterEmulation])
122     {
123         mProgramHelper.enableSpecializationConstant(
124             sh::vk::SpecializationConstantId::LineRasterEmulation);
125     }
126 
127     return angle::Result::Continue;
128 }
129 
release(ContextVk * contextVk)130 void ProgramInfo::release(ContextVk *contextVk)
131 {
132     mProgramHelper.release(contextVk);
133 
134     for (vk::RefCounted<vk::ShaderAndSerial> &shader : mShaders)
135     {
136         shader.get().destroy(contextVk->getDevice());
137     }
138 }
139 
ProgramExecutableVk()140 ProgramExecutableVk::ProgramExecutableVk()
141     : mEmptyDescriptorSets{},
142       mNumDefaultUniformDescriptors(0),
143       mPipelineLayoutCreated(false),
144       mDynamicBufferOffsets{},
145       mProgram(nullptr),
146       mProgramPipeline(nullptr)
147 {}
148 
149 ProgramExecutableVk::~ProgramExecutableVk() = default;
150 
reset(ContextVk * contextVk)151 void ProgramExecutableVk::reset(ContextVk *contextVk)
152 {
153     RendererVk *renderer = contextVk->getRenderer();
154 
155     for (auto &descriptorSetLayout : mDescriptorSetLayouts)
156     {
157         descriptorSetLayout.reset();
158     }
159     mPipelineLayout.reset();
160 
161     mEmptyBuffer.release(renderer);
162 
163     mDescriptorSets.clear();
164     mEmptyDescriptorSets.fill(VK_NULL_HANDLE);
165     mPipelineLayoutCreated        = false;
166     mNumDefaultUniformDescriptors = 0;
167     mTransformOptionBits.reset();
168 
169     for (vk::RefCountedDescriptorPoolBinding &binding : mDescriptorPoolBindings)
170     {
171         binding.reset();
172     }
173 
174     for (vk::DynamicDescriptorPool &descriptorPool : mDynamicDescriptorPools)
175     {
176         descriptorPool.release(contextVk);
177     }
178 
179     mTextureDescriptorsCache.clear();
180     mDescriptorBuffersCache.clear();
181 
182     for (ProgramInfo &programInfo : mProgramInfos)
183     {
184         programInfo.release(contextVk);
185     }
186 }
187 
load(gl::BinaryInputStream * stream)188 std::unique_ptr<rx::LinkEvent> ProgramExecutableVk::load(gl::BinaryInputStream *stream)
189 {
190     clearVariableInfoMap();
191 
192     for (gl::ShaderType shaderType : gl::AllShaderTypes())
193     {
194         size_t variableInfoMapSize = stream->readInt<size_t>();
195 
196         for (size_t i = 0; i < variableInfoMapSize; ++i)
197         {
198             const std::string variableName    = stream->readString();
199             ShaderInterfaceVariableInfo *info = &mVariableInfoMap[shaderType][variableName];
200 
201             info->descriptorSet = stream->readInt<uint32_t>();
202             info->binding       = stream->readInt<uint32_t>();
203             info->location      = stream->readInt<uint32_t>();
204             info->component     = stream->readInt<uint32_t>();
205             // PackedEnumBitSet uses uint8_t
206             info->activeStages = gl::ShaderBitSet(stream->readInt<uint8_t>());
207             info->xfbBuffer    = stream->readInt<uint32_t>();
208             info->xfbOffset    = stream->readInt<uint32_t>();
209             info->xfbStride    = stream->readInt<uint32_t>();
210         }
211     }
212 
213     return std::make_unique<LinkEventDone>(angle::Result::Continue);
214 }
215 
save(gl::BinaryOutputStream * stream)216 void ProgramExecutableVk::save(gl::BinaryOutputStream *stream)
217 {
218     for (gl::ShaderType shaderType : gl::AllShaderTypes())
219     {
220         stream->writeInt<size_t>(mVariableInfoMap[shaderType].size());
221         for (const auto &it : mVariableInfoMap[shaderType])
222         {
223             stream->writeString(it.first);
224             stream->writeInt<uint32_t>(it.second.descriptorSet);
225             stream->writeInt<uint32_t>(it.second.binding);
226             stream->writeInt<uint32_t>(it.second.location);
227             stream->writeInt<uint32_t>(it.second.component);
228             // PackedEnumBitSet uses uint8_t
229             stream->writeInt<uint8_t>(it.second.activeStages.bits());
230             stream->writeInt<uint32_t>(it.second.xfbBuffer);
231             stream->writeInt<uint32_t>(it.second.xfbOffset);
232             stream->writeInt<uint32_t>(it.second.xfbStride);
233         }
234     }
235 }
236 
clearVariableInfoMap()237 void ProgramExecutableVk::clearVariableInfoMap()
238 {
239     for (const gl::ShaderType shaderType : gl::AllShaderTypes())
240     {
241         mVariableInfoMap[shaderType].clear();
242     }
243 }
244 
getShaderProgram(const gl::State & glState,gl::ShaderType shaderType) const245 ProgramVk *ProgramExecutableVk::getShaderProgram(const gl::State &glState,
246                                                  gl::ShaderType shaderType) const
247 {
248     if (mProgram)
249     {
250         const gl::ProgramExecutable &glExecutable = mProgram->getState().getProgramExecutable();
251         if (glExecutable.hasLinkedShaderStage(shaderType))
252         {
253             return mProgram;
254         }
255     }
256     else if (mProgramPipeline)
257     {
258         return mProgramPipeline->getShaderProgram(glState, shaderType);
259     }
260 
261     return nullptr;
262 }
263 
264 // TODO: http://anglebug.com/3570: Move/Copy all of the necessary information into
265 // the ProgramExecutable, so this function can be removed.
fillProgramStateMap(const ContextVk * contextVk,gl::ShaderMap<const gl::ProgramState * > * programStatesOut)266 void ProgramExecutableVk::fillProgramStateMap(
267     const ContextVk *contextVk,
268     gl::ShaderMap<const gl::ProgramState *> *programStatesOut)
269 {
270     ASSERT(mProgram || mProgramPipeline);
271     if (mProgram)
272     {
273         mProgram->fillProgramStateMap(programStatesOut);
274     }
275     else if (mProgramPipeline)
276     {
277         mProgramPipeline->fillProgramStateMap(contextVk, programStatesOut);
278     }
279 }
280 
getGlExecutable()281 const gl::ProgramExecutable &ProgramExecutableVk::getGlExecutable()
282 {
283     ASSERT(mProgram || mProgramPipeline);
284     if (mProgram)
285     {
286         return mProgram->getState().getProgramExecutable();
287     }
288     return mProgramPipeline->getState().getProgramExecutable();
289 }
290 
GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> & blocks,uint32_t bufferIndex)291 uint32_t GetInterfaceBlockArraySize(const std::vector<gl::InterfaceBlock> &blocks,
292                                     uint32_t bufferIndex)
293 {
294     const gl::InterfaceBlock &block = blocks[bufferIndex];
295 
296     if (!block.isArray)
297     {
298         return 1;
299     }
300 
301     ASSERT(block.arrayElement == 0);
302 
303     // Search consecutively until all array indices of this block are visited.
304     uint32_t arraySize;
305     for (arraySize = 1; bufferIndex + arraySize < blocks.size(); ++arraySize)
306     {
307         const gl::InterfaceBlock &nextBlock = blocks[bufferIndex + arraySize];
308 
309         if (nextBlock.arrayElement != arraySize)
310         {
311             break;
312         }
313 
314         // It's unexpected for an array to start at a non-zero array size, so we can always rely on
315         // the sequential `arrayElement`s to belong to the same block.
316         ASSERT(nextBlock.name == block.name);
317         ASSERT(nextBlock.isArray);
318     }
319 
320     return arraySize;
321 }
322 
allocateDescriptorSet(ContextVk * contextVk,uint32_t descriptorSetIndex)323 angle::Result ProgramExecutableVk::allocateDescriptorSet(ContextVk *contextVk,
324                                                          uint32_t descriptorSetIndex)
325 {
326     bool ignoreNewPoolAllocated;
327     return allocateDescriptorSetAndGetInfo(contextVk, descriptorSetIndex, &ignoreNewPoolAllocated);
328 }
329 
allocateDescriptorSetAndGetInfo(ContextVk * contextVk,uint32_t descriptorSetIndex,bool * newPoolAllocatedOut)330 angle::Result ProgramExecutableVk::allocateDescriptorSetAndGetInfo(ContextVk *contextVk,
331                                                                    uint32_t descriptorSetIndex,
332                                                                    bool *newPoolAllocatedOut)
333 {
334     vk::DynamicDescriptorPool &dynamicDescriptorPool = mDynamicDescriptorPools[descriptorSetIndex];
335 
336     uint32_t potentialNewCount = descriptorSetIndex + 1;
337     if (potentialNewCount > mDescriptorSets.size())
338     {
339         mDescriptorSets.resize(potentialNewCount, VK_NULL_HANDLE);
340     }
341 
342     const vk::DescriptorSetLayout &descriptorSetLayout =
343         mDescriptorSetLayouts[descriptorSetIndex].get();
344     ANGLE_TRY(dynamicDescriptorPool.allocateSetsAndGetInfo(
345         contextVk, descriptorSetLayout.ptr(), 1, &mDescriptorPoolBindings[descriptorSetIndex],
346         &mDescriptorSets[descriptorSetIndex], newPoolAllocatedOut));
347     mEmptyDescriptorSets[descriptorSetIndex] = VK_NULL_HANDLE;
348 
349     return angle::Result::Continue;
350 }
351 
addInterfaceBlockDescriptorSetDesc(const std::vector<gl::InterfaceBlock> & blocks,const gl::ShaderType shaderType,VkDescriptorType descType,vk::DescriptorSetLayoutDesc * descOut)352 void ProgramExecutableVk::addInterfaceBlockDescriptorSetDesc(
353     const std::vector<gl::InterfaceBlock> &blocks,
354     const gl::ShaderType shaderType,
355     VkDescriptorType descType,
356     vk::DescriptorSetLayoutDesc *descOut)
357 {
358     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size();)
359     {
360         gl::InterfaceBlock block = blocks[bufferIndex];
361         const uint32_t arraySize = GetInterfaceBlockArraySize(blocks, bufferIndex);
362         bufferIndex += arraySize;
363 
364         if (!block.isActive(shaderType))
365         {
366             continue;
367         }
368 
369         const std::string blockName             = block.mappedName;
370         const ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][blockName];
371 
372         descOut->update(info.binding, descType, arraySize, gl_vk::kShaderStageMap[shaderType]);
373     }
374 }
375 
addAtomicCounterBufferDescriptorSetDesc(const std::vector<gl::AtomicCounterBuffer> & atomicCounterBuffers,const gl::ShaderType shaderType,vk::DescriptorSetLayoutDesc * descOut)376 void ProgramExecutableVk::addAtomicCounterBufferDescriptorSetDesc(
377     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers,
378     const gl::ShaderType shaderType,
379     vk::DescriptorSetLayoutDesc *descOut)
380 {
381     if (atomicCounterBuffers.empty())
382     {
383         return;
384     }
385 
386     std::string blockName(sh::vk::kAtomicCountersBlockName);
387     const ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][blockName];
388 
389     if (!info.activeStages[shaderType])
390     {
391         return;
392     }
393 
394     // A single storage buffer array is used for all stages for simplicity.
395     descOut->update(info.binding, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
396                     gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS,
397                     gl_vk::kShaderStageMap[shaderType]);
398 }
399 
addImageDescriptorSetDesc(const gl::ProgramState & programState,vk::DescriptorSetLayoutDesc * descOut)400 void ProgramExecutableVk::addImageDescriptorSetDesc(const gl::ProgramState &programState,
401                                                     vk::DescriptorSetLayoutDesc *descOut)
402 {
403     const std::vector<gl::ImageBinding> &imageBindings = programState.getImageBindings();
404     const std::vector<gl::LinkedUniform> &uniforms     = programState.getUniforms();
405 
406     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
407     {
408         const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
409 
410         uint32_t uniformIndex = programState.getUniformIndexFromImageIndex(imageIndex);
411         const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
412 
413         // The front-end always binds array image units sequentially.
414         uint32_t arraySize = static_cast<uint32_t>(imageBinding.boundImageUnits.size());
415 
416         for (const gl::ShaderType shaderType :
417              programState.getProgramExecutable().getLinkedShaderStages())
418         {
419             if (!imageUniform.isActive(shaderType))
420             {
421                 continue;
422             }
423 
424             std::string name = imageUniform.mappedName;
425             GetImageNameWithoutIndices(&name);
426             ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][name];
427             VkShaderStageFlags activeStages   = gl_vk::kShaderStageMap[shaderType];
428             descOut->update(info.binding, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, arraySize,
429                             activeStages);
430         }
431     }
432 }
433 
addTextureDescriptorSetDesc(const gl::ProgramState & programState,bool useOldRewriteStructSamplers,vk::DescriptorSetLayoutDesc * descOut)434 void ProgramExecutableVk::addTextureDescriptorSetDesc(const gl::ProgramState &programState,
435                                                       bool useOldRewriteStructSamplers,
436                                                       vk::DescriptorSetLayoutDesc *descOut)
437 {
438     const std::vector<gl::SamplerBinding> &samplerBindings = programState.getSamplerBindings();
439     const std::vector<gl::LinkedUniform> &uniforms         = programState.getUniforms();
440 
441     for (uint32_t textureIndex = 0; textureIndex < samplerBindings.size(); ++textureIndex)
442     {
443         const gl::SamplerBinding &samplerBinding = samplerBindings[textureIndex];
444 
445         uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(textureIndex);
446         const gl::LinkedUniform &samplerUniform = uniforms[uniformIndex];
447 
448         const std::string samplerName = useOldRewriteStructSamplers
449                                             ? GetMappedSamplerNameOld(samplerUniform.name)
450                                             : GlslangGetMappedSamplerName(samplerUniform.name);
451 
452         // The front-end always binds array sampler units sequentially.
453         uint32_t arraySize = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
454 
455         if (!useOldRewriteStructSamplers)
456         {
457             // 2D arrays are split into multiple 1D arrays when generating
458             // LinkedUniforms. Since they are flattened into one array, ignore the
459             // nonzero elements and expand the array to the total array size.
460             if (gl::SamplerNameContainsNonZeroArrayElement(samplerUniform.name))
461             {
462                 continue;
463             }
464 
465             for (unsigned int outerArraySize : samplerUniform.outerArraySizes)
466             {
467                 arraySize *= outerArraySize;
468             }
469         }
470 
471         for (const gl::ShaderType shaderType :
472              programState.getProgramExecutable().getLinkedShaderStages())
473         {
474             if (!samplerUniform.isActive(shaderType))
475             {
476                 continue;
477             }
478 
479             ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][samplerName];
480             VkShaderStageFlags activeStages   = gl_vk::kShaderStageMap[shaderType];
481 
482             descOut->update(info.binding, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize,
483                             activeStages);
484         }
485     }
486 }
487 
WriteBufferDescriptorSetBinding(const gl::OffsetBindingPointer<gl::Buffer> & bufferBinding,VkDeviceSize maxSize,VkDescriptorSet descSet,VkDescriptorType descType,uint32_t bindingIndex,uint32_t arrayElement,VkDeviceSize requiredOffsetAlignment,VkDescriptorBufferInfo * bufferInfoOut,VkWriteDescriptorSet * writeInfoOut)488 void WriteBufferDescriptorSetBinding(const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding,
489                                      VkDeviceSize maxSize,
490                                      VkDescriptorSet descSet,
491                                      VkDescriptorType descType,
492                                      uint32_t bindingIndex,
493                                      uint32_t arrayElement,
494                                      VkDeviceSize requiredOffsetAlignment,
495                                      VkDescriptorBufferInfo *bufferInfoOut,
496                                      VkWriteDescriptorSet *writeInfoOut)
497 {
498     gl::Buffer *buffer = bufferBinding.get();
499     ASSERT(buffer != nullptr);
500 
501     // Make sure there's no possible under/overflow with binding size.
502     static_assert(sizeof(VkDeviceSize) >= sizeof(bufferBinding.getSize()),
503                   "VkDeviceSize too small");
504     ASSERT(bufferBinding.getSize() >= 0);
505 
506     BufferVk *bufferVk             = vk::GetImpl(buffer);
507     VkDeviceSize offset            = bufferBinding.getOffset();
508     VkDeviceSize size              = bufferBinding.getSize();
509     vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
510 
511     // If size is 0, we can't always use VK_WHOLE_SIZE (or bufferHelper.getSize()), as the
512     // backing buffer may be larger than max*BufferRange.  In that case, we use the minimum of
513     // the backing buffer size (what's left after offset) and the buffer size as defined by the
514     // shader.  That latter is only valid for UBOs, as SSBOs may have variable length arrays.
515     size = size > 0 ? size : (bufferHelper.getSize() - offset);
516     if (maxSize > 0)
517     {
518         size = std::min(size, maxSize);
519     }
520 
521     // If requiredOffsetAlignment is 0, the buffer offset is guaranteed to have the necessary
522     // alignment through other means (the backend specifying the alignment through a GLES limit that
523     // the frontend then enforces).  If it's not 0, we need to bind the buffer at an offset that's
524     // aligned.  The difference in offsets is communicated to the shader via driver uniforms.
525     if (requiredOffsetAlignment)
526     {
527         VkDeviceSize alignedOffset = (offset / requiredOffsetAlignment) * requiredOffsetAlignment;
528         VkDeviceSize offsetDiff    = offset - alignedOffset;
529 
530         offset = alignedOffset;
531         size += offsetDiff;
532     }
533 
534     bufferInfoOut->buffer = bufferHelper.getBuffer().getHandle();
535     bufferInfoOut->offset = offset;
536     bufferInfoOut->range  = size;
537 
538     writeInfoOut->sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
539     writeInfoOut->pNext            = nullptr;
540     writeInfoOut->dstSet           = descSet;
541     writeInfoOut->dstBinding       = bindingIndex;
542     writeInfoOut->dstArrayElement  = arrayElement;
543     writeInfoOut->descriptorCount  = 1;
544     writeInfoOut->descriptorType   = descType;
545     writeInfoOut->pImageInfo       = nullptr;
546     writeInfoOut->pBufferInfo      = bufferInfoOut;
547     writeInfoOut->pTexelBufferView = nullptr;
548     ASSERT(writeInfoOut->pBufferInfo[0].buffer != VK_NULL_HANDLE);
549 }
550 
updateEarlyFragmentTestsOptimization(ContextVk * contextVk)551 void ProgramExecutableVk::updateEarlyFragmentTestsOptimization(ContextVk *contextVk)
552 {
553     const gl::State &glState = contextVk->getState();
554 
555     mTransformOptionBits[ProgramTransformOption::RemoveEarlyFragmentTestsOptimization] = false;
556     if (!glState.isEarlyFragmentTestsOptimizationAllowed())
557     {
558         ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Fragment);
559         if (programVk->getState().hasEarlyFragmentTestsOptimization())
560         {
561             mTransformOptionBits[ProgramTransformOption::RemoveEarlyFragmentTestsOptimization] =
562                 true;
563         }
564     }
565 }
566 
getGraphicsPipeline(ContextVk * contextVk,gl::PrimitiveMode mode,const vk::GraphicsPipelineDesc & desc,const gl::AttributesMask & activeAttribLocations,const vk::GraphicsPipelineDesc ** descPtrOut,vk::PipelineHelper ** pipelineOut)567 angle::Result ProgramExecutableVk::getGraphicsPipeline(
568     ContextVk *contextVk,
569     gl::PrimitiveMode mode,
570     const vk::GraphicsPipelineDesc &desc,
571     const gl::AttributesMask &activeAttribLocations,
572     const vk::GraphicsPipelineDesc **descPtrOut,
573     vk::PipelineHelper **pipelineOut)
574 {
575     const gl::State &glState = contextVk->getState();
576     mTransformOptionBits[ProgramTransformOption::EnableLineRasterEmulation] =
577         contextVk->isBresenhamEmulationEnabled(mode);
578     ProgramInfo &programInfo         = getProgramInfo(mTransformOptionBits);
579     RendererVk *renderer             = contextVk->getRenderer();
580     vk::PipelineCache *pipelineCache = nullptr;
581 
582     const gl::ProgramExecutable *executable = glState.getProgramExecutable();
583     ASSERT(executable);
584 
585     for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
586     {
587         ProgramVk *programVk = getShaderProgram(glState, shaderType);
588         if (programVk)
589         {
590             ANGLE_TRY(programVk->initGraphicsShaderProgram(contextVk, shaderType,
591                                                            mTransformOptionBits, programInfo));
592         }
593     }
594 
595     vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
596     ASSERT(shaderProgram && shaderProgram->isGraphicsProgram());
597     ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
598     return shaderProgram->getGraphicsPipeline(
599         contextVk, &contextVk->getRenderPassCache(), *pipelineCache,
600         contextVk->getCurrentQueueSerial(), getPipelineLayout(), desc, activeAttribLocations,
601         glState.getProgramExecutable()->getAttributesTypeMask(), descPtrOut, pipelineOut);
602 }
603 
getComputePipeline(ContextVk * contextVk,vk::PipelineAndSerial ** pipelineOut)604 angle::Result ProgramExecutableVk::getComputePipeline(ContextVk *contextVk,
605                                                       vk::PipelineAndSerial **pipelineOut)
606 {
607     const gl::State &glState = contextVk->getState();
608     ProgramInfo &programInfo = getDefaultProgramInfo();
609 
610     ProgramVk *programVk = getShaderProgram(glState, gl::ShaderType::Compute);
611     ASSERT(programVk);
612     ANGLE_TRY(programVk->initComputeProgram(contextVk, programInfo));
613 
614     vk::ShaderProgramHelper *shaderProgram = programInfo.getShaderProgram();
615     ASSERT(shaderProgram && !shaderProgram->isGraphicsProgram());
616     return shaderProgram->getComputePipeline(contextVk, getPipelineLayout(), pipelineOut);
617 }
618 
createPipelineLayout(const gl::Context * glContext)619 angle::Result ProgramExecutableVk::createPipelineLayout(const gl::Context *glContext)
620 {
621     if (mPipelineLayoutCreated)
622     {
623         return angle::Result::Continue;
624     }
625 
626     const gl::State &glState                   = glContext->getState();
627     ContextVk *contextVk                       = vk::GetImpl(glContext);
628     RendererVk *renderer                       = contextVk->getRenderer();
629     gl::TransformFeedback *transformFeedback   = glState.getCurrentTransformFeedback();
630     const gl::ProgramExecutable &glExecutable  = getGlExecutable();
631     const gl::ShaderBitSet &linkedShaderStages = glExecutable.getLinkedShaderStages();
632     gl::ShaderMap<const gl::ProgramState *> programStates;
633     fillProgramStateMap(contextVk, &programStates);
634 
635     reset(contextVk);
636 
637     // Store a reference to the pipeline and descriptor set layouts. This will create them if they
638     // don't already exist in the cache.
639 
640     // Default uniforms and transform feedback:
641     vk::DescriptorSetLayoutDesc uniformsAndXfbSetDesc;
642     for (const gl::ShaderType shaderType : linkedShaderStages)
643     {
644         const std::string uniformBlockName = kDefaultUniformNames[shaderType];
645         ShaderInterfaceVariableInfo &info  = mVariableInfoMap[shaderType][uniformBlockName];
646         if (!info.activeStages[shaderType])
647         {
648             continue;
649         }
650 
651         uniformsAndXfbSetDesc.update(info.binding, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1,
652                                      gl_vk::kShaderStageMap[shaderType]);
653         mNumDefaultUniformDescriptors++;
654     }
655     bool hasVertexShader = glExecutable.hasLinkedShaderStage(gl::ShaderType::Vertex);
656     bool hasXfbVaryings =
657         (programStates[gl::ShaderType::Vertex] &&
658          !programStates[gl::ShaderType::Vertex]->getLinkedTransformFeedbackVaryings().empty());
659     if (hasVertexShader && transformFeedback && hasXfbVaryings)
660     {
661         size_t xfbBufferCount =
662             programStates[gl::ShaderType::Vertex]->getTransformFeedbackBufferCount();
663         TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
664         transformFeedbackVk->updateDescriptorSetLayout(contextVk,
665                                                        mVariableInfoMap[gl::ShaderType::Vertex],
666                                                        xfbBufferCount, &uniformsAndXfbSetDesc);
667     }
668 
669     ANGLE_TRY(renderer->getDescriptorSetLayout(
670         contextVk, uniformsAndXfbSetDesc,
671         &mDescriptorSetLayouts[kUniformsAndXfbDescriptorSetIndex]));
672 
673     // Uniform and storage buffers, atomic counter buffers and images:
674     vk::DescriptorSetLayoutDesc resourcesSetDesc;
675 
676     for (const gl::ShaderType shaderType : linkedShaderStages)
677     {
678         addInterfaceBlockDescriptorSetDesc(programStates[shaderType]->getUniformBlocks(),
679                                            shaderType, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
680                                            &resourcesSetDesc);
681         addInterfaceBlockDescriptorSetDesc(programStates[shaderType]->getShaderStorageBlocks(),
682                                            shaderType, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
683                                            &resourcesSetDesc);
684         addAtomicCounterBufferDescriptorSetDesc(
685             programStates[shaderType]->getAtomicCounterBuffers(), shaderType, &resourcesSetDesc);
686     }
687 
688     for (const gl::ShaderType shaderType : linkedShaderStages)
689     {
690         const gl::ProgramState *programState = programStates[shaderType];
691         ASSERT(programState);
692         addImageDescriptorSetDesc(*programState, &resourcesSetDesc);
693     }
694 
695     ANGLE_TRY(renderer->getDescriptorSetLayout(
696         contextVk, resourcesSetDesc, &mDescriptorSetLayouts[kShaderResourceDescriptorSetIndex]));
697 
698     // Textures:
699     vk::DescriptorSetLayoutDesc texturesSetDesc;
700 
701     for (const gl::ShaderType shaderType : linkedShaderStages)
702     {
703         const gl::ProgramState *programState = programStates[shaderType];
704         ASSERT(programState);
705         addTextureDescriptorSetDesc(*programState, contextVk->useOldRewriteStructSamplers(),
706                                     &texturesSetDesc);
707     }
708 
709     ANGLE_TRY(renderer->getDescriptorSetLayout(contextVk, texturesSetDesc,
710                                                &mDescriptorSetLayouts[kTextureDescriptorSetIndex]));
711 
712     // Driver uniforms:
713     VkShaderStageFlags driverUniformsStages =
714         glExecutable.isCompute() ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS;
715     vk::DescriptorSetLayoutDesc driverUniformsSetDesc =
716         contextVk->getDriverUniformsDescriptorSetDesc(driverUniformsStages);
717     ANGLE_TRY(renderer->getDescriptorSetLayout(
718         contextVk, driverUniformsSetDesc,
719         &mDescriptorSetLayouts[kDriverUniformsDescriptorSetIndex]));
720 
721     // Create pipeline layout with these 4 descriptor sets.
722     vk::PipelineLayoutDesc pipelineLayoutDesc;
723     pipelineLayoutDesc.updateDescriptorSetLayout(kUniformsAndXfbDescriptorSetIndex,
724                                                  uniformsAndXfbSetDesc);
725     pipelineLayoutDesc.updateDescriptorSetLayout(kShaderResourceDescriptorSetIndex,
726                                                  resourcesSetDesc);
727     pipelineLayoutDesc.updateDescriptorSetLayout(kTextureDescriptorSetIndex, texturesSetDesc);
728     pipelineLayoutDesc.updateDescriptorSetLayout(kDriverUniformsDescriptorSetIndex,
729                                                  driverUniformsSetDesc);
730 
731     ANGLE_TRY(renderer->getPipelineLayout(contextVk, pipelineLayoutDesc, mDescriptorSetLayouts,
732                                           &mPipelineLayout));
733 
734     // Initialize descriptor pools.
735     std::array<VkDescriptorPoolSize, 2> uniformAndXfbSetSize = {
736         {{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
737           static_cast<uint32_t>(mNumDefaultUniformDescriptors)},
738          {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS}}};
739 
740     uint32_t uniformBlockCount        = 0;
741     uint32_t storageBlockCount        = 0;
742     uint32_t atomicCounterBufferCount = 0;
743     uint32_t imageCount               = 0;
744     uint32_t textureCount             = 0;
745     for (const gl::ShaderType shaderType : linkedShaderStages)
746     {
747         const gl::ProgramState *programState = programStates[shaderType];
748         ASSERT(programState);
749         // TODO(timvp): http://anglebug.com/3570: These counts will be too high for monolithic
750         // programs, since it's the same ProgramState for each shader type.
751         uniformBlockCount += static_cast<uint32_t>(programState->getUniformBlocks().size());
752         storageBlockCount += static_cast<uint32_t>(programState->getShaderStorageBlocks().size());
753         atomicCounterBufferCount +=
754             static_cast<uint32_t>(programState->getAtomicCounterBuffers().size());
755         imageCount += static_cast<uint32_t>(programState->getImageBindings().size());
756         textureCount += static_cast<uint32_t>(programState->getSamplerBindings().size());
757     }
758 
759     if (renderer->getFeatures().bindEmptyForUnusedDescriptorSets.enabled)
760     {
761         // For this workaround, we have to create an empty descriptor set for each descriptor set
762         // index, so make sure their pools are initialized.
763         uniformBlockCount = std::max(uniformBlockCount, 1u);
764         textureCount      = std::max(textureCount, 1u);
765     }
766 
767     constexpr size_t kResourceTypesInResourcesSet = 3;
768     angle::FixedVector<VkDescriptorPoolSize, kResourceTypesInResourcesSet> resourceSetSize;
769     if (uniformBlockCount > 0)
770     {
771         resourceSetSize.emplace_back(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uniformBlockCount);
772     }
773     if (storageBlockCount > 0 || atomicCounterBufferCount > 0)
774     {
775         // Note that we always use an array of IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS storage
776         // buffers for emulating atomic counters, so if there are any atomic counter buffers, we
777         // need to allocate IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS descriptors.
778         const uint32_t atomicCounterStorageBufferCount =
779             atomicCounterBufferCount > 0 ? gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS : 0;
780         const uint32_t storageBufferDescCount = storageBlockCount + atomicCounterStorageBufferCount;
781         resourceSetSize.emplace_back(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, storageBufferDescCount);
782     }
783     if (imageCount > 0)
784     {
785         resourceSetSize.emplace_back(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, imageCount);
786     }
787 
788     VkDescriptorPoolSize textureSetSize = {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, textureCount};
789 
790     ANGLE_TRY(mDynamicDescriptorPools[kUniformsAndXfbDescriptorSetIndex].init(
791         contextVk, uniformAndXfbSetSize.data(), uniformAndXfbSetSize.size()));
792     if (resourceSetSize.size() > 0)
793     {
794         ANGLE_TRY(mDynamicDescriptorPools[kShaderResourceDescriptorSetIndex].init(
795             contextVk, resourceSetSize.data(), static_cast<uint32_t>(resourceSetSize.size())));
796     }
797     if (textureCount > 0)
798     {
799         ANGLE_TRY(mDynamicDescriptorPools[kTextureDescriptorSetIndex].init(contextVk,
800                                                                            &textureSetSize, 1));
801     }
802 
803     mDynamicBufferOffsets.resize(glExecutable.getLinkedShaderStageCount());
804 
805     // Initialize an "empty" buffer for use with default uniform blocks where there are no uniforms,
806     // or atomic counter buffer array indices that are unused.
807     constexpr VkBufferUsageFlags kEmptyBufferUsage =
808         VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
809 
810     VkBufferCreateInfo emptyBufferInfo    = {};
811     emptyBufferInfo.sType                 = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
812     emptyBufferInfo.flags                 = 0;
813     emptyBufferInfo.size                  = 4;
814     emptyBufferInfo.usage                 = kEmptyBufferUsage;
815     emptyBufferInfo.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
816     emptyBufferInfo.queueFamilyIndexCount = 0;
817     emptyBufferInfo.pQueueFamilyIndices   = nullptr;
818 
819     constexpr VkMemoryPropertyFlags kMemoryType = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
820     angle::Result status = mEmptyBuffer.init(contextVk, emptyBufferInfo, kMemoryType);
821 
822     mPipelineLayoutCreated = true;
823 
824     return status;
825 }
826 
updateDefaultUniformsDescriptorSet(const gl::ShaderType shaderType,gl::ShaderMap<DefaultUniformBlock> & defaultUniformBlocks,ContextVk * contextVk)827 void ProgramExecutableVk::updateDefaultUniformsDescriptorSet(
828     const gl::ShaderType shaderType,
829     gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
830     ContextVk *contextVk)
831 {
832     const std::string uniformBlockName = kDefaultUniformNames[shaderType];
833     ShaderInterfaceVariableInfo &info  = mVariableInfoMap[shaderType][uniformBlockName];
834     if (!info.activeStages[shaderType])
835     {
836         return;
837     }
838 
839     DefaultUniformBlock &uniformBlock = defaultUniformBlocks[shaderType];
840     VkDescriptorBufferInfo bufferInfo;
841     VkWriteDescriptorSet writeInfo;
842 
843     if (!uniformBlock.uniformData.empty())
844     {
845         vk::BufferHelper *bufferHelper = uniformBlock.storage.getCurrentBuffer();
846         bufferInfo.buffer              = bufferHelper->getBuffer().getHandle();
847         mDescriptorBuffersCache.emplace_back(bufferHelper);
848     }
849     else
850     {
851         mEmptyBuffer.retain(&contextVk->getResourceUseList());
852         bufferInfo.buffer = mEmptyBuffer.getBuffer().getHandle();
853         mDescriptorBuffersCache.emplace_back(&mEmptyBuffer);
854     }
855 
856     bufferInfo.offset = 0;
857     bufferInfo.range  = VK_WHOLE_SIZE;
858 
859     writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
860     writeInfo.pNext            = nullptr;
861     writeInfo.dstSet           = mDescriptorSets[kUniformsAndXfbDescriptorSetIndex];
862     writeInfo.dstBinding       = info.binding;
863     writeInfo.dstArrayElement  = 0;
864     writeInfo.descriptorCount  = 1;
865     writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
866     writeInfo.pImageInfo       = nullptr;
867     writeInfo.pBufferInfo      = &bufferInfo;
868     writeInfo.pTexelBufferView = nullptr;
869 
870     VkDevice device = contextVk->getDevice();
871 
872     vkUpdateDescriptorSets(device, 1, &writeInfo, 0, nullptr);
873 }
874 
updateBuffersDescriptorSet(ContextVk * contextVk,const gl::ShaderType shaderType,vk::ResourceUseList * resourceUseList,CommandBufferHelper * commandBufferHelper,const std::vector<gl::InterfaceBlock> & blocks,VkDescriptorType descriptorType)875 void ProgramExecutableVk::updateBuffersDescriptorSet(ContextVk *contextVk,
876                                                      const gl::ShaderType shaderType,
877                                                      vk::ResourceUseList *resourceUseList,
878                                                      CommandBufferHelper *commandBufferHelper,
879                                                      const std::vector<gl::InterfaceBlock> &blocks,
880                                                      VkDescriptorType descriptorType)
881 {
882     if (blocks.empty())
883     {
884         return;
885     }
886 
887     VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
888 
889     ASSERT(descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ||
890            descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
891     const bool isStorageBuffer = descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
892 
893     static_assert(
894         gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS >=
895             gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS,
896         "The descriptor arrays here would have inadequate size for uniform buffer objects");
897 
898     gl::StorageBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
899     gl::StorageBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo;
900     uint32_t writeCount = 0;
901 
902     // Write uniform or storage buffers.
903     const gl::State &glState = contextVk->getState();
904     for (uint32_t bufferIndex = 0; bufferIndex < blocks.size(); ++bufferIndex)
905     {
906         const gl::InterfaceBlock &block = blocks[bufferIndex];
907         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
908             isStorageBuffer ? glState.getIndexedShaderStorageBuffer(block.binding)
909                             : glState.getIndexedUniformBuffer(block.binding);
910 
911         if (!block.isActive(shaderType))
912         {
913             continue;
914         }
915 
916         if (bufferBinding.get() == nullptr)
917         {
918             continue;
919         }
920 
921         ShaderInterfaceVariableInfo info = mVariableInfoMap[shaderType][block.mappedName];
922         uint32_t binding                 = info.binding;
923         uint32_t arrayElement            = block.isArray ? block.arrayElement : 0;
924         VkDeviceSize maxBlockSize        = isStorageBuffer ? 0 : block.dataSize;
925 
926         VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[writeCount];
927         VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[writeCount];
928 
929         WriteBufferDescriptorSetBinding(bufferBinding, maxBlockSize, descriptorSet, descriptorType,
930                                         binding, arrayElement, 0, &bufferInfo, &writeInfo);
931 
932         BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
933         vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
934 
935         if (isStorageBuffer)
936         {
937             // We set the SHADER_READ_BIT to be conservative.
938             VkAccessFlags accessFlags = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
939             commandBufferHelper->bufferWrite(resourceUseList, accessFlags, &bufferHelper);
940         }
941         else
942         {
943             commandBufferHelper->bufferRead(resourceUseList, VK_ACCESS_UNIFORM_READ_BIT,
944                                             &bufferHelper);
945         }
946 
947         ++writeCount;
948     }
949 
950     VkDevice device = contextVk->getDevice();
951 
952     vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
953 }
954 
updateAtomicCounterBuffersDescriptorSet(const gl::ProgramState & programState,const gl::ShaderType shaderType,ContextVk * contextVk,vk::ResourceUseList * resourceUseList,CommandBufferHelper * commandBufferHelper)955 void ProgramExecutableVk::updateAtomicCounterBuffersDescriptorSet(
956     const gl::ProgramState &programState,
957     const gl::ShaderType shaderType,
958     ContextVk *contextVk,
959     vk::ResourceUseList *resourceUseList,
960     CommandBufferHelper *commandBufferHelper)
961 {
962     const gl::State &glState = contextVk->getState();
963     const std::vector<gl::AtomicCounterBuffer> &atomicCounterBuffers =
964         programState.getAtomicCounterBuffers();
965 
966     if (atomicCounterBuffers.empty())
967     {
968         return;
969     }
970 
971     VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
972 
973     std::string blockName(sh::vk::kAtomicCountersBlockName);
974     const ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][blockName];
975 
976     if (!info.activeStages[shaderType])
977     {
978         return;
979     }
980 
981     gl::AtomicCounterBuffersArray<VkDescriptorBufferInfo> descriptorBufferInfo;
982     gl::AtomicCounterBuffersArray<VkWriteDescriptorSet> writeDescriptorInfo;
983     gl::AtomicCounterBufferMask writtenBindings;
984 
985     RendererVk *rendererVk = contextVk->getRenderer();
986     const VkDeviceSize requiredOffsetAlignment =
987         rendererVk->getPhysicalDeviceProperties().limits.minStorageBufferOffsetAlignment;
988 
989     // Write atomic counter buffers.
990     for (uint32_t bufferIndex = 0; bufferIndex < atomicCounterBuffers.size(); ++bufferIndex)
991     {
992         const gl::AtomicCounterBuffer &atomicCounterBuffer = atomicCounterBuffers[bufferIndex];
993         uint32_t binding                                   = atomicCounterBuffer.binding;
994         const gl::OffsetBindingPointer<gl::Buffer> &bufferBinding =
995             glState.getIndexedAtomicCounterBuffer(binding);
996 
997         if (bufferBinding.get() == nullptr)
998         {
999             continue;
1000         }
1001 
1002         VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[binding];
1003         VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[binding];
1004 
1005         WriteBufferDescriptorSetBinding(bufferBinding, 0, descriptorSet,
1006                                         VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, info.binding, binding,
1007                                         requiredOffsetAlignment, &bufferInfo, &writeInfo);
1008 
1009         BufferVk *bufferVk             = vk::GetImpl(bufferBinding.get());
1010         vk::BufferHelper &bufferHelper = bufferVk->getBuffer();
1011 
1012         // We set SHADER_READ_BIT to be conservative.
1013         commandBufferHelper->bufferWrite(
1014             resourceUseList, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, &bufferHelper);
1015 
1016         writtenBindings.set(binding);
1017     }
1018 
1019     // Bind the empty buffer to every array slot that's unused.
1020     mEmptyBuffer.retain(&contextVk->getResourceUseList());
1021     for (size_t binding : ~writtenBindings)
1022     {
1023         VkDescriptorBufferInfo &bufferInfo = descriptorBufferInfo[binding];
1024         VkWriteDescriptorSet &writeInfo    = writeDescriptorInfo[binding];
1025 
1026         bufferInfo.buffer = mEmptyBuffer.getBuffer().getHandle();
1027         bufferInfo.offset = 0;
1028         bufferInfo.range  = VK_WHOLE_SIZE;
1029 
1030         writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1031         writeInfo.pNext            = nullptr;
1032         writeInfo.dstSet           = descriptorSet;
1033         writeInfo.dstBinding       = info.binding;
1034         writeInfo.dstArrayElement  = static_cast<uint32_t>(binding);
1035         writeInfo.descriptorCount  = 1;
1036         writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1037         writeInfo.pImageInfo       = nullptr;
1038         writeInfo.pBufferInfo      = &bufferInfo;
1039         writeInfo.pTexelBufferView = nullptr;
1040     }
1041 
1042     VkDevice device = contextVk->getDevice();
1043 
1044     vkUpdateDescriptorSets(device, gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS,
1045                            writeDescriptorInfo.data(), 0, nullptr);
1046 }
1047 
updateImagesDescriptorSet(const gl::ProgramState & programState,const gl::ShaderType shaderType,ContextVk * contextVk)1048 angle::Result ProgramExecutableVk::updateImagesDescriptorSet(const gl::ProgramState &programState,
1049                                                              const gl::ShaderType shaderType,
1050                                                              ContextVk *contextVk)
1051 {
1052     const gl::State &glState                           = contextVk->getState();
1053     const std::vector<gl::ImageBinding> &imageBindings = programState.getImageBindings();
1054     const std::vector<gl::LinkedUniform> &uniforms     = programState.getUniforms();
1055 
1056     if (imageBindings.empty())
1057     {
1058         return angle::Result::Continue;
1059     }
1060 
1061     VkDescriptorSet descriptorSet = mDescriptorSets[kShaderResourceDescriptorSetIndex];
1062 
1063     const gl::ActiveTextureArray<TextureVk *> &activeImages = contextVk->getActiveImages();
1064 
1065     gl::ImagesArray<VkDescriptorImageInfo> descriptorImageInfo;
1066     gl::ImagesArray<VkWriteDescriptorSet> writeDescriptorInfo;
1067     uint32_t writeCount = 0;
1068 
1069     // Write images.
1070     for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
1071     {
1072         const gl::ImageBinding &imageBinding = imageBindings[imageIndex];
1073         uint32_t uniformIndex = programState.getUniformIndexFromImageIndex(imageIndex);
1074         const gl::LinkedUniform &imageUniform = uniforms[uniformIndex];
1075 
1076         if (!imageUniform.isActive(shaderType))
1077         {
1078             continue;
1079         }
1080 
1081         std::string name = imageUniform.mappedName;
1082         GetImageNameWithoutIndices(&name);
1083         ShaderInterfaceVariableInfo &info = mVariableInfoMap[shaderType][name];
1084 
1085         ASSERT(!imageBinding.unreferenced);
1086 
1087         for (uint32_t arrayElement = 0; arrayElement < imageBinding.boundImageUnits.size();
1088              ++arrayElement)
1089         {
1090             GLuint imageUnit             = imageBinding.boundImageUnits[arrayElement];
1091             const gl::ImageUnit &binding = glState.getImageUnit(imageUnit);
1092             TextureVk *textureVk         = activeImages[imageUnit];
1093 
1094             vk::ImageHelper *image         = &textureVk->getImage();
1095             const vk::ImageView *imageView = nullptr;
1096 
1097             ANGLE_TRY(textureVk->getStorageImageView(contextVk, (binding.layered == GL_TRUE),
1098                                                      binding.level, binding.layer, &imageView));
1099 
1100             // Note: binding.access is unused because it is implied by the shader.
1101 
1102             // TODO(syoussefi): Support image data reinterpretation by using binding.format.
1103             // http://anglebug.com/3563
1104 
1105             VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
1106             VkWriteDescriptorSet &writeInfo  = writeDescriptorInfo[writeCount];
1107 
1108             imageInfo.sampler     = VK_NULL_HANDLE;
1109             imageInfo.imageView   = imageView->getHandle();
1110             imageInfo.imageLayout = image->getCurrentLayout();
1111 
1112             writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1113             writeInfo.pNext            = nullptr;
1114             writeInfo.dstSet           = descriptorSet;
1115             writeInfo.dstBinding       = info.binding;
1116             writeInfo.dstArrayElement  = arrayElement;
1117             writeInfo.descriptorCount  = 1;
1118             writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1119             writeInfo.pImageInfo       = &imageInfo;
1120             writeInfo.pBufferInfo      = nullptr;
1121             writeInfo.pTexelBufferView = nullptr;
1122 
1123             ++writeCount;
1124         }
1125     }
1126 
1127     VkDevice device = contextVk->getDevice();
1128 
1129     vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
1130 
1131     return angle::Result::Continue;
1132 }
1133 
updateShaderResourcesDescriptorSet(ContextVk * contextVk,vk::ResourceUseList * resourceUseList,CommandBufferHelper * commandBufferHelper)1134 angle::Result ProgramExecutableVk::updateShaderResourcesDescriptorSet(
1135     ContextVk *contextVk,
1136     vk::ResourceUseList *resourceUseList,
1137     CommandBufferHelper *commandBufferHelper)
1138 {
1139     const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
1140     ASSERT(executable);
1141     gl::ShaderMap<const gl::ProgramState *> programStates;
1142     fillProgramStateMap(contextVk, &programStates);
1143 
1144     ANGLE_TRY(allocateDescriptorSet(contextVk, kShaderResourceDescriptorSetIndex));
1145 
1146     for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
1147     {
1148         const gl::ProgramState *programState = programStates[shaderType];
1149         ASSERT(programState);
1150 
1151         updateBuffersDescriptorSet(contextVk, shaderType, resourceUseList, commandBufferHelper,
1152                                    programState->getUniformBlocks(),
1153                                    VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
1154         updateBuffersDescriptorSet(contextVk, shaderType, resourceUseList, commandBufferHelper,
1155                                    programState->getShaderStorageBlocks(),
1156                                    VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1157         updateAtomicCounterBuffersDescriptorSet(*programState, shaderType, contextVk,
1158                                                 resourceUseList, commandBufferHelper);
1159         angle::Result status = updateImagesDescriptorSet(*programState, shaderType, contextVk);
1160         if (status != angle::Result::Continue)
1161         {
1162             return status;
1163         }
1164     }
1165 
1166     return angle::Result::Continue;
1167 }
1168 
updateTransformFeedbackDescriptorSet(const gl::ProgramState & programState,gl::ShaderMap<DefaultUniformBlock> & defaultUniformBlocks,ContextVk * contextVk)1169 angle::Result ProgramExecutableVk::updateTransformFeedbackDescriptorSet(
1170     const gl::ProgramState &programState,
1171     gl::ShaderMap<DefaultUniformBlock> &defaultUniformBlocks,
1172     ContextVk *contextVk)
1173 {
1174     const gl::ProgramExecutable &executable = programState.getProgramExecutable();
1175     ASSERT(executable.hasTransformFeedbackOutput());
1176 
1177     ANGLE_TRY(allocateDescriptorSet(contextVk, kUniformsAndXfbDescriptorSetIndex));
1178 
1179     mDescriptorBuffersCache.clear();
1180     for (const gl::ShaderType shaderType : executable.getLinkedShaderStages())
1181     {
1182         updateDefaultUniformsDescriptorSet(shaderType, defaultUniformBlocks, contextVk);
1183     }
1184 
1185     updateTransformFeedbackDescriptorSetImpl(programState, contextVk);
1186 
1187     return angle::Result::Continue;
1188 }
1189 
updateTransformFeedbackDescriptorSetImpl(const gl::ProgramState & programState,ContextVk * contextVk)1190 void ProgramExecutableVk::updateTransformFeedbackDescriptorSetImpl(
1191     const gl::ProgramState &programState,
1192     ContextVk *contextVk)
1193 {
1194     const gl::State &glState                 = contextVk->getState();
1195     gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
1196     const gl::ProgramExecutable &executable  = programState.getProgramExecutable();
1197 
1198     if (!executable.hasTransformFeedbackOutput())
1199     {
1200         // If xfb has no output there is no need to update descriptor set.
1201         return;
1202     }
1203     if (!glState.isTransformFeedbackActive())
1204     {
1205         // We set empty Buffer to xfb descriptor set because xfb descriptor set
1206         // requires valid buffer bindings, even if they are empty buffer,
1207         // otherwise Vulkan validation layer generates errors.
1208         if (transformFeedback)
1209         {
1210             TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(transformFeedback);
1211             transformFeedbackVk->initDescriptorSet(
1212                 contextVk, programState.getTransformFeedbackBufferCount(), &mEmptyBuffer,
1213                 mDescriptorSets[kUniformsAndXfbDescriptorSetIndex]);
1214         }
1215         return;
1216     }
1217 
1218     TransformFeedbackVk *transformFeedbackVk = vk::GetImpl(glState.getCurrentTransformFeedback());
1219     transformFeedbackVk->updateDescriptorSet(contextVk, programState,
1220                                              mDescriptorSets[kUniformsAndXfbDescriptorSetIndex]);
1221 }
1222 
updateTexturesDescriptorSet(ContextVk * contextVk)1223 angle::Result ProgramExecutableVk::updateTexturesDescriptorSet(ContextVk *contextVk)
1224 {
1225     const gl::ProgramExecutable *executable = contextVk->getState().getProgramExecutable();
1226     ASSERT(executable);
1227 
1228     if (!executable->hasTextures())
1229     {
1230         return angle::Result::Continue;
1231     }
1232 
1233     const vk::TextureDescriptorDesc &texturesDesc = contextVk->getActiveTexturesDesc();
1234 
1235     auto iter = mTextureDescriptorsCache.find(texturesDesc);
1236     if (iter != mTextureDescriptorsCache.end())
1237     {
1238         mDescriptorSets[kTextureDescriptorSetIndex] = iter->second;
1239         return angle::Result::Continue;
1240     }
1241 
1242     bool newPoolAllocated;
1243     ANGLE_TRY(
1244         allocateDescriptorSetAndGetInfo(contextVk, kTextureDescriptorSetIndex, &newPoolAllocated));
1245 
1246     // Clear descriptor set cache. It may no longer be valid.
1247     if (newPoolAllocated)
1248     {
1249         mTextureDescriptorsCache.clear();
1250     }
1251 
1252     VkDescriptorSet descriptorSet = mDescriptorSets[kTextureDescriptorSetIndex];
1253 
1254     gl::ActiveTextureArray<VkDescriptorImageInfo> descriptorImageInfo;
1255     gl::ActiveTextureArray<VkWriteDescriptorSet> writeDescriptorInfo;
1256     uint32_t writeCount = 0;
1257 
1258     const gl::ActiveTextureArray<vk::TextureUnit> &activeTextures = contextVk->getActiveTextures();
1259 
1260     bool emulateSeamfulCubeMapSampling = contextVk->emulateSeamfulCubeMapSampling();
1261     bool useOldRewriteStructSamplers   = contextVk->useOldRewriteStructSamplers();
1262 
1263     gl::ShaderMap<const gl::ProgramState *> programStates;
1264     fillProgramStateMap(contextVk, &programStates);
1265 
1266     for (const gl::ShaderType shaderType : executable->getLinkedShaderStages())
1267     {
1268         std::unordered_map<std::string, uint32_t> mappedSamplerNameToArrayOffset;
1269         const gl::ProgramState *programState = programStates[shaderType];
1270         ASSERT(programState);
1271         for (uint32_t textureIndex = 0; textureIndex < programState->getSamplerBindings().size();
1272              ++textureIndex)
1273         {
1274             const gl::SamplerBinding &samplerBinding =
1275                 programState->getSamplerBindings()[textureIndex];
1276 
1277             ASSERT(!samplerBinding.unreferenced);
1278 
1279             uint32_t uniformIndex = programState->getUniformIndexFromSamplerIndex(textureIndex);
1280             const gl::LinkedUniform &samplerUniform = programState->getUniforms()[uniformIndex];
1281             std::string mappedSamplerName = GlslangGetMappedSamplerName(samplerUniform.name);
1282 
1283             if (!samplerUniform.isActive(shaderType))
1284             {
1285                 continue;
1286             }
1287 
1288             uint32_t arrayOffset = 0;
1289             uint32_t arraySize   = static_cast<uint32_t>(samplerBinding.boundTextureUnits.size());
1290 
1291             if (!useOldRewriteStructSamplers)
1292             {
1293                 arrayOffset = mappedSamplerNameToArrayOffset[mappedSamplerName];
1294                 // Front-end generates array elements in order, so we can just increment
1295                 // the offset each time we process a nested array.
1296                 mappedSamplerNameToArrayOffset[mappedSamplerName] += arraySize;
1297             }
1298 
1299             for (uint32_t arrayElement = 0; arrayElement < arraySize; ++arrayElement)
1300             {
1301                 GLuint textureUnit   = samplerBinding.boundTextureUnits[arrayElement];
1302                 TextureVk *textureVk = activeTextures[textureUnit].texture;
1303                 SamplerVk *samplerVk = activeTextures[textureUnit].sampler;
1304 
1305                 vk::ImageHelper &image = textureVk->getImage();
1306 
1307                 VkDescriptorImageInfo &imageInfo = descriptorImageInfo[writeCount];
1308 
1309                 // Use bound sampler object if one present, otherwise use texture's sampler
1310                 const vk::Sampler &sampler =
1311                     (samplerVk != nullptr) ? samplerVk->getSampler() : textureVk->getSampler();
1312 
1313                 imageInfo.sampler     = sampler.getHandle();
1314                 imageInfo.imageLayout = image.getCurrentLayout();
1315 
1316                 if (emulateSeamfulCubeMapSampling)
1317                 {
1318                     // If emulating seamful cubemapping, use the fetch image view.  This is
1319                     // basically the same image view as read, except it's a 2DArray view for
1320                     // cube maps.
1321                     imageInfo.imageView =
1322                         textureVk->getFetchImageViewAndRecordUse(contextVk).getHandle();
1323                 }
1324                 else
1325                 {
1326                     imageInfo.imageView =
1327                         textureVk->getReadImageViewAndRecordUse(contextVk).getHandle();
1328                 }
1329 
1330                 ShaderInterfaceVariableInfoMap &variableInfoMap = mVariableInfoMap[shaderType];
1331                 const std::string samplerName =
1332                     contextVk->getRenderer()->getFeatures().forceOldRewriteStructSamplers.enabled
1333                         ? GetMappedSamplerNameOld(samplerUniform.name)
1334                         : GlslangGetMappedSamplerName(samplerUniform.name);
1335                 ShaderInterfaceVariableInfo &info = variableInfoMap[samplerName];
1336 
1337                 VkWriteDescriptorSet &writeInfo = writeDescriptorInfo[writeCount];
1338 
1339                 writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1340                 writeInfo.pNext            = nullptr;
1341                 writeInfo.dstSet           = descriptorSet;
1342                 writeInfo.dstBinding       = info.binding;
1343                 writeInfo.dstArrayElement  = arrayOffset + arrayElement;
1344                 writeInfo.descriptorCount  = 1;
1345                 writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1346                 writeInfo.pImageInfo       = &imageInfo;
1347                 writeInfo.pBufferInfo      = nullptr;
1348                 writeInfo.pTexelBufferView = nullptr;
1349 
1350                 ++writeCount;
1351             }
1352         }
1353     }
1354 
1355     VkDevice device = contextVk->getDevice();
1356 
1357     ASSERT(writeCount > 0);
1358 
1359     vkUpdateDescriptorSets(device, writeCount, writeDescriptorInfo.data(), 0, nullptr);
1360 
1361     mTextureDescriptorsCache.emplace(texturesDesc, descriptorSet);
1362 
1363     return angle::Result::Continue;
1364 }
1365 
updateDescriptorSets(ContextVk * contextVk,vk::CommandBuffer * commandBuffer)1366 angle::Result ProgramExecutableVk::updateDescriptorSets(ContextVk *contextVk,
1367                                                         vk::CommandBuffer *commandBuffer)
1368 {
1369     // Can probably use better dirty bits here.
1370 
1371     if (mDescriptorSets.empty())
1372         return angle::Result::Continue;
1373 
1374     // Find the maximum non-null descriptor set.  This is used in conjunction with a driver
1375     // workaround to bind empty descriptor sets only for gaps in between 0 and max and avoid
1376     // binding unnecessary empty descriptor sets for the sets beyond max.
1377     const size_t descriptorSetStart = kUniformsAndXfbDescriptorSetIndex;
1378     size_t descriptorSetRange       = 0;
1379     for (size_t descriptorSetIndex = descriptorSetStart;
1380          descriptorSetIndex < mDescriptorSets.size(); ++descriptorSetIndex)
1381     {
1382         if (mDescriptorSets[descriptorSetIndex] != VK_NULL_HANDLE)
1383         {
1384             descriptorSetRange = descriptorSetIndex + 1;
1385         }
1386     }
1387 
1388     const gl::State &glState                    = contextVk->getState();
1389     const VkPipelineBindPoint pipelineBindPoint = glState.getProgramExecutable()->isCompute()
1390                                                       ? VK_PIPELINE_BIND_POINT_COMPUTE
1391                                                       : VK_PIPELINE_BIND_POINT_GRAPHICS;
1392 
1393     for (uint32_t descriptorSetIndex = descriptorSetStart; descriptorSetIndex < descriptorSetRange;
1394          ++descriptorSetIndex)
1395     {
1396         VkDescriptorSet descSet = mDescriptorSets[descriptorSetIndex];
1397         if (descSet == VK_NULL_HANDLE)
1398         {
1399             if (!contextVk->getRenderer()->getFeatures().bindEmptyForUnusedDescriptorSets.enabled)
1400             {
1401                 continue;
1402             }
1403 
1404             // Workaround a driver bug where missing (though unused) descriptor sets indices cause
1405             // later sets to misbehave.
1406             if (mEmptyDescriptorSets[descriptorSetIndex] == VK_NULL_HANDLE)
1407             {
1408                 const vk::DescriptorSetLayout &descriptorSetLayout =
1409                     mDescriptorSetLayouts[descriptorSetIndex].get();
1410 
1411                 ANGLE_TRY(mDynamicDescriptorPools[descriptorSetIndex].allocateSets(
1412                     contextVk, descriptorSetLayout.ptr(), 1,
1413                     &mDescriptorPoolBindings[descriptorSetIndex],
1414                     &mEmptyDescriptorSets[descriptorSetIndex]));
1415             }
1416             descSet = mEmptyDescriptorSets[descriptorSetIndex];
1417         }
1418 
1419         // Default uniforms are encompassed in a block per shader stage, and they are assigned
1420         // through dynamic uniform buffers (requiring dynamic offsets).  No other descriptor
1421         // requires a dynamic offset.
1422         const uint32_t uniformBlockOffsetCount =
1423             descriptorSetIndex == kUniformsAndXfbDescriptorSetIndex
1424                 ? static_cast<uint32_t>(mNumDefaultUniformDescriptors)
1425                 : 0;
1426 
1427         commandBuffer->bindDescriptorSets(getPipelineLayout(), pipelineBindPoint,
1428                                           descriptorSetIndex, 1, &descSet, uniformBlockOffsetCount,
1429                                           mDynamicBufferOffsets.data());
1430     }
1431 
1432     for (vk::BufferHelper *buffer : mDescriptorBuffersCache)
1433     {
1434         buffer->retain(&contextVk->getResourceUseList());
1435     }
1436 
1437     return angle::Result::Continue;
1438 }
1439 
1440 }  // namespace rx
1441