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