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