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