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