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