• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2018 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 // UtilsVk.cpp:
7 //    Implements the UtilsVk class.
8 //
9 
10 #include "libANGLE/renderer/vulkan/UtilsVk.h"
11 
12 #include "libANGLE/renderer/vulkan/ContextVk.h"
13 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
14 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
15 #include "libANGLE/renderer/vulkan/RendererVk.h"
16 
17 namespace rx
18 {
19 
20 namespace BufferUtils_comp                  = vk::InternalShader::BufferUtils_comp;
21 namespace ConvertVertex_comp                = vk::InternalShader::ConvertVertex_comp;
22 namespace ImageClear_frag                   = vk::InternalShader::ImageClear_frag;
23 namespace ImageCopy_frag                    = vk::InternalShader::ImageCopy_frag;
24 namespace BlitResolve_frag                  = vk::InternalShader::BlitResolve_frag;
25 namespace BlitResolveStencilNoExport_comp   = vk::InternalShader::BlitResolveStencilNoExport_comp;
26 namespace OverlayCull_comp                  = vk::InternalShader::OverlayCull_comp;
27 namespace OverlayDraw_comp                  = vk::InternalShader::OverlayDraw_comp;
28 namespace ConvertIndexIndirectLineLoop_comp = vk::InternalShader::ConvertIndexIndirectLineLoop_comp;
29 
30 namespace
31 {
32 // All internal shaders assume there is only one descriptor set, indexed at 0
33 constexpr uint32_t kSetIndex = 0;
34 
35 constexpr uint32_t kBufferClearOutputBinding                 = 0;
36 constexpr uint32_t kConvertIndexDestinationBinding           = 0;
37 constexpr uint32_t kConvertVertexDestinationBinding          = 0;
38 constexpr uint32_t kConvertVertexSourceBinding               = 1;
39 constexpr uint32_t kImageCopySourceBinding                   = 0;
40 constexpr uint32_t kBlitResolveColorOrDepthBinding           = 0;
41 constexpr uint32_t kBlitResolveStencilBinding                = 1;
42 constexpr uint32_t kBlitResolveSamplerBinding                = 2;
43 constexpr uint32_t kBlitResolveStencilNoExportDestBinding    = 0;
44 constexpr uint32_t kBlitResolveStencilNoExportSrcBinding     = 1;
45 constexpr uint32_t kBlitResolveStencilNoExportSamplerBinding = 2;
46 constexpr uint32_t kOverlayCullCulledWidgetsBinding          = 0;
47 constexpr uint32_t kOverlayCullWidgetCoordsBinding           = 1;
48 constexpr uint32_t kOverlayDrawOutputBinding                 = 0;
49 constexpr uint32_t kOverlayDrawTextWidgetsBinding            = 1;
50 constexpr uint32_t kOverlayDrawGraphWidgetsBinding           = 2;
51 constexpr uint32_t kOverlayDrawCulledWidgetsBinding          = 3;
52 constexpr uint32_t kOverlayDrawFontBinding                   = 4;
53 
GetBufferUtilsFlags(size_t dispatchSize,const vk::Format & format)54 uint32_t GetBufferUtilsFlags(size_t dispatchSize, const vk::Format &format)
55 {
56     uint32_t flags                    = dispatchSize % 64 == 0 ? BufferUtils_comp::kIsAligned : 0;
57     const angle::Format &bufferFormat = format.actualBufferFormat();
58 
59     if (bufferFormat.isSint())
60     {
61         flags |= BufferUtils_comp::kIsSint;
62     }
63     else if (bufferFormat.isUint())
64     {
65         flags |= BufferUtils_comp::kIsUint;
66     }
67     else
68     {
69         flags |= BufferUtils_comp::kIsFloat;
70     }
71 
72     return flags;
73 }
74 
GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters & params)75 uint32_t GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters &params)
76 {
77     bool srcIsSint  = params.srcFormat->isSint();
78     bool srcIsUint  = params.srcFormat->isUint();
79     bool srcIsSnorm = params.srcFormat->isSnorm();
80     bool srcIsUnorm = params.srcFormat->isUnorm();
81     bool srcIsFixed = params.srcFormat->isFixed;
82     bool srcIsFloat = params.srcFormat->isFloat();
83     bool srcIsA2BGR10 =
84         params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt2101010 ||
85         params.srcFormat->vertexAttribType == gl::VertexAttribType::Int2101010;
86     bool srcIsRGB10A2 =
87         params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt1010102 ||
88         params.srcFormat->vertexAttribType == gl::VertexAttribType::Int1010102;
89     bool srcIsHalfFloat = params.srcFormat->isVertexTypeHalfFloat();
90 
91     bool destIsSint      = params.destFormat->isSint();
92     bool destIsUint      = params.destFormat->isUint();
93     bool destIsFloat     = params.destFormat->isFloat();
94     bool destIsHalfFloat = params.destFormat->isVertexTypeHalfFloat();
95 
96     // Assert on the types to make sure the shader supports its.  These are based on
97     // ConvertVertex_comp::Conversion values.
98     ASSERT(!destIsSint || srcIsSint);           // If destination is sint, src must be sint too
99     ASSERT(!destIsUint || srcIsUint);           // If destination is uint, src must be uint too
100     ASSERT(!srcIsFixed || destIsFloat);         // If source is fixed, dest must be float
101     ASSERT(srcIsHalfFloat == destIsHalfFloat);  // Both src and dest are half float or neither
102 
103     // One of each bool set must be true
104     ASSERT(srcIsSint || srcIsUint || srcIsSnorm || srcIsUnorm || srcIsFixed || srcIsFloat);
105     ASSERT(destIsSint || destIsUint || destIsFloat);
106 
107     // We currently don't have any big-endian devices in the list of supported platforms.  The
108     // shader is capable of supporting big-endian architectures, but the relevant flag (IsBigEndian)
109     // is not added to the build configuration file (to reduce binary size).  If necessary, add
110     // IsBigEndian to ConvertVertex.comp.json and select the appropriate flag based on the
111     // endian-ness test here.
112     ASSERT(IsLittleEndian());
113 
114     uint32_t flags = 0;
115 
116     if (srcIsA2BGR10)
117     {
118         if (srcIsSint && destIsSint)
119         {
120             flags |= ConvertVertex_comp::kA2BGR10SintToSint;
121         }
122         else if (srcIsUint && destIsUint)
123         {
124             flags |= ConvertVertex_comp::kA2BGR10UintToUint;
125         }
126         else if (srcIsSint)
127         {
128             flags |= ConvertVertex_comp::kA2BGR10SintToFloat;
129         }
130         else if (srcIsUint)
131         {
132             flags |= ConvertVertex_comp::kA2BGR10UintToFloat;
133         }
134         else if (srcIsSnorm)
135         {
136             flags |= ConvertVertex_comp::kA2BGR10SnormToFloat;
137         }
138         else
139         {
140             UNREACHABLE();
141         }
142     }
143     else if (srcIsRGB10A2)
144     {
145         if (srcIsSint)
146         {
147             flags |= ConvertVertex_comp::kRGB10A2SintToFloat;
148         }
149         else if (srcIsUint)
150         {
151             flags |= ConvertVertex_comp::kRGB10A2UintToFloat;
152         }
153         else if (srcIsSnorm)
154         {
155             flags |= ConvertVertex_comp::kRGB10A2SnormToFloat;
156         }
157         else if (srcIsUnorm)
158         {
159             flags |= ConvertVertex_comp::kRGB10A2UnormToFloat;
160         }
161         else
162         {
163             UNREACHABLE();
164         }
165     }
166     else if (srcIsHalfFloat && destIsHalfFloat)
167     {
168         // Note that HalfFloat conversion uses the same shader as Uint.
169         flags |= ConvertVertex_comp::kUintToUint;
170     }
171     else if (srcIsSint && destIsSint)
172     {
173         flags |= ConvertVertex_comp::kSintToSint;
174     }
175     else if (srcIsUint && destIsUint)
176     {
177         flags |= ConvertVertex_comp::kUintToUint;
178     }
179     else if (srcIsSint)
180     {
181         flags |= ConvertVertex_comp::kSintToFloat;
182     }
183     else if (srcIsUint)
184     {
185         flags |= ConvertVertex_comp::kUintToFloat;
186     }
187     else if (srcIsSnorm)
188     {
189         flags |= ConvertVertex_comp::kSnormToFloat;
190     }
191     else if (srcIsUnorm)
192     {
193         flags |= ConvertVertex_comp::kUnormToFloat;
194     }
195     else if (srcIsFixed)
196     {
197         flags |= ConvertVertex_comp::kFixedToFloat;
198     }
199     else if (srcIsFloat)
200     {
201         flags |= ConvertVertex_comp::kFloatToFloat;
202     }
203     else
204     {
205         UNREACHABLE();
206     }
207 
208     return flags;
209 }
210 
GetImageClearFlags(const angle::Format & format,uint32_t attachmentIndex)211 uint32_t GetImageClearFlags(const angle::Format &format, uint32_t attachmentIndex)
212 {
213     constexpr uint32_t kAttachmentFlagStep =
214         ImageClear_frag::kAttachment1 - ImageClear_frag::kAttachment0;
215 
216     static_assert(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS == 8,
217                   "ImageClear shader assumes maximum 8 draw buffers");
218     static_assert(
219         ImageClear_frag::kAttachment0 + 7 * kAttachmentFlagStep == ImageClear_frag::kAttachment7,
220         "ImageClear AttachmentN flag calculation needs correction");
221 
222     uint32_t flags = ImageClear_frag::kAttachment0 + attachmentIndex * kAttachmentFlagStep;
223 
224     if (format.isSint())
225     {
226         flags |= ImageClear_frag::kIsSint;
227     }
228     else if (format.isUint())
229     {
230         flags |= ImageClear_frag::kIsUint;
231     }
232     else
233     {
234         flags |= ImageClear_frag::kIsFloat;
235     }
236 
237     return flags;
238 }
239 
GetFormatFlags(const angle::Format & format,uint32_t intFlag,uint32_t uintFlag,uint32_t floatFlag)240 uint32_t GetFormatFlags(const angle::Format &format,
241                         uint32_t intFlag,
242                         uint32_t uintFlag,
243                         uint32_t floatFlag)
244 {
245     if (format.isSint())
246     {
247         return intFlag;
248     }
249     if (format.isUint())
250     {
251         return uintFlag;
252     }
253     return floatFlag;
254 }
255 
GetImageCopyFlags(const vk::Format & srcFormat,const vk::Format & dstFormat)256 uint32_t GetImageCopyFlags(const vk::Format &srcFormat, const vk::Format &dstFormat)
257 {
258     const angle::Format &srcIntendedFormat = srcFormat.intendedFormat();
259     const angle::Format &dstIntendedFormat = dstFormat.intendedFormat();
260 
261     uint32_t flags = 0;
262 
263     flags |= GetFormatFlags(srcIntendedFormat, ImageCopy_frag::kSrcIsSint,
264                             ImageCopy_frag::kSrcIsUint, ImageCopy_frag::kSrcIsFloat);
265     flags |= GetFormatFlags(dstIntendedFormat, ImageCopy_frag::kDestIsSint,
266                             ImageCopy_frag::kDestIsUint, ImageCopy_frag::kDestIsFloat);
267 
268     return flags;
269 }
270 
GetBlitResolveFlags(bool blitColor,bool blitDepth,bool blitStencil,const vk::Format & format)271 uint32_t GetBlitResolveFlags(bool blitColor,
272                              bool blitDepth,
273                              bool blitStencil,
274                              const vk::Format &format)
275 {
276     if (blitColor)
277     {
278         const angle::Format &intendedFormat = format.intendedFormat();
279 
280         return GetFormatFlags(intendedFormat, BlitResolve_frag::kBlitColorInt,
281                               BlitResolve_frag::kBlitColorUint, BlitResolve_frag::kBlitColorFloat);
282     }
283 
284     if (blitDepth)
285     {
286         if (blitStencil)
287         {
288             return BlitResolve_frag::kBlitDepthStencil;
289         }
290         else
291         {
292             return BlitResolve_frag::kBlitDepth;
293         }
294     }
295     else
296     {
297         return BlitResolve_frag::kBlitStencil;
298     }
299 }
300 
GetConvertIndexIndirectLineLoopFlag(uint32_t indicesBitsWidth)301 uint32_t GetConvertIndexIndirectLineLoopFlag(uint32_t indicesBitsWidth)
302 {
303     switch (indicesBitsWidth)
304     {
305         case 8:
306             return ConvertIndexIndirectLineLoop_comp::kIs8Bits;
307         case 16:
308             return ConvertIndexIndirectLineLoop_comp::kIs16Bits;
309         case 32:
310             return ConvertIndexIndirectLineLoop_comp::kIs32Bits;
311         default:
312             UNREACHABLE();
313             return 0;
314     }
315 }
316 
GetFormatDefaultChannelMask(const vk::Format & format)317 uint32_t GetFormatDefaultChannelMask(const vk::Format &format)
318 {
319     uint32_t mask = 0;
320 
321     const angle::Format &intendedFormat = format.intendedFormat();
322     const angle::Format &imageFormat    = format.actualImageFormat();
323 
324     // Red can never be introduced due to format emulation (except for luma which is handled
325     // especially)
326     ASSERT(((intendedFormat.redBits > 0) == (imageFormat.redBits > 0)) || intendedFormat.isLUMA());
327     mask |= intendedFormat.greenBits == 0 && imageFormat.greenBits > 0 ? 2 : 0;
328     mask |= intendedFormat.blueBits == 0 && imageFormat.blueBits > 0 ? 4 : 0;
329     mask |= intendedFormat.alphaBits == 0 && imageFormat.alphaBits > 0 ? 8 : 0;
330 
331     return mask;
332 }
333 
334 // Calculate the transformation offset for blit/resolve.  See BlitResolve.frag for details on how
335 // these values are derived.
CalculateBlitOffset(const UtilsVk::BlitResolveParameters & params,float offset[2])336 void CalculateBlitOffset(const UtilsVk::BlitResolveParameters &params, float offset[2])
337 {
338     int srcOffsetFactorX = params.flipX ? -1 : 1;
339     int srcOffsetFactorY = params.flipY ? -1 : 1;
340 
341     offset[0] = params.destOffset[0] * params.stretch[0] - params.srcOffset[0] * srcOffsetFactorX;
342     offset[1] = params.destOffset[1] * params.stretch[1] - params.srcOffset[1] * srcOffsetFactorY;
343 }
344 
CalculateResolveOffset(const UtilsVk::BlitResolveParameters & params,int32_t offset[2])345 void CalculateResolveOffset(const UtilsVk::BlitResolveParameters &params, int32_t offset[2])
346 {
347     int srcOffsetFactorX = params.flipX ? -1 : 1;
348     int srcOffsetFactorY = params.flipY ? -1 : 1;
349 
350     // There's no stretching in resolve.
351     offset[0] = params.destOffset[0] - params.srcOffset[0] * srcOffsetFactorX;
352     offset[1] = params.destOffset[1] - params.srcOffset[1] * srcOffsetFactorY;
353 }
354 }  // namespace
355 
356 UtilsVk::ConvertVertexShaderParams::ConvertVertexShaderParams() = default;
357 
358 UtilsVk::ImageCopyShaderParams::ImageCopyShaderParams() = default;
359 
360 UtilsVk::UtilsVk() = default;
361 
362 UtilsVk::~UtilsVk() = default;
363 
destroy(VkDevice device)364 void UtilsVk::destroy(VkDevice device)
365 {
366     for (Function f : angle::AllEnums<Function>())
367     {
368         for (auto &descriptorSetLayout : mDescriptorSetLayouts[f])
369         {
370             descriptorSetLayout.reset();
371         }
372         mPipelineLayouts[f].reset();
373         mDescriptorPools[f].destroy(device);
374     }
375 
376     for (vk::ShaderProgramHelper &program : mBufferUtilsPrograms)
377     {
378         program.destroy(device);
379     }
380     for (vk::ShaderProgramHelper &program : mConvertIndexPrograms)
381     {
382         program.destroy(device);
383     }
384     for (vk::ShaderProgramHelper &program : mConvertIndirectLineLoopPrograms)
385     {
386         program.destroy(device);
387     }
388     for (vk::ShaderProgramHelper &program : mConvertIndexIndirectLineLoopPrograms)
389     {
390         program.destroy(device);
391     }
392     for (vk::ShaderProgramHelper &program : mConvertVertexPrograms)
393     {
394         program.destroy(device);
395     }
396     mImageClearProgramVSOnly.destroy(device);
397     for (vk::ShaderProgramHelper &program : mImageClearProgram)
398     {
399         program.destroy(device);
400     }
401     for (vk::ShaderProgramHelper &program : mImageCopyPrograms)
402     {
403         program.destroy(device);
404     }
405     for (vk::ShaderProgramHelper &program : mBlitResolvePrograms)
406     {
407         program.destroy(device);
408     }
409     for (vk::ShaderProgramHelper &program : mBlitResolveStencilNoExportPrograms)
410     {
411         program.destroy(device);
412     }
413     for (vk::ShaderProgramHelper &program : mOverlayCullPrograms)
414     {
415         program.destroy(device);
416     }
417     for (vk::ShaderProgramHelper &program : mOverlayDrawPrograms)
418     {
419         program.destroy(device);
420     }
421 
422     mPointSampler.destroy(device);
423     mLinearSampler.destroy(device);
424 }
425 
ensureResourcesInitialized(ContextVk * contextVk,Function function,VkDescriptorPoolSize * setSizes,size_t setSizesCount,size_t pushConstantsSize)426 angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
427                                                   Function function,
428                                                   VkDescriptorPoolSize *setSizes,
429                                                   size_t setSizesCount,
430                                                   size_t pushConstantsSize)
431 {
432     RendererVk *renderer = contextVk->getRenderer();
433 
434     vk::DescriptorSetLayoutDesc descriptorSetDesc;
435     bool isCompute = function >= Function::ComputeStartIndex;
436     const VkShaderStageFlags descStages =
437         isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
438 
439     uint32_t currentBinding = 0;
440     for (size_t i = 0; i < setSizesCount; ++i)
441     {
442         descriptorSetDesc.update(currentBinding, setSizes[i].type, setSizes[i].descriptorCount,
443                                  descStages);
444         currentBinding += setSizes[i].descriptorCount;
445     }
446 
447     ANGLE_TRY(renderer->getDescriptorSetLayout(contextVk, descriptorSetDesc,
448                                                &mDescriptorSetLayouts[function][kSetIndex]));
449 
450     gl::ShaderType pushConstantsShaderStage =
451         isCompute ? gl::ShaderType::Compute : gl::ShaderType::Fragment;
452 
453     // Corresponding pipeline layouts:
454     vk::PipelineLayoutDesc pipelineLayoutDesc;
455 
456     pipelineLayoutDesc.updateDescriptorSetLayout(kSetIndex, descriptorSetDesc);
457     if (pushConstantsSize)
458     {
459         pipelineLayoutDesc.updatePushConstantRange(pushConstantsShaderStage, 0,
460                                                    static_cast<uint32_t>(pushConstantsSize));
461     }
462 
463     ANGLE_TRY(renderer->getPipelineLayout(contextVk, pipelineLayoutDesc,
464                                           mDescriptorSetLayouts[function],
465                                           &mPipelineLayouts[function]));
466 
467     if (setSizesCount > 0)
468     {
469         ANGLE_TRY(mDescriptorPools[function].init(contextVk, setSizes,
470                                                   static_cast<uint32_t>(setSizesCount)));
471     }
472 
473     return angle::Result::Continue;
474 }
475 
ensureBufferClearResourcesInitialized(ContextVk * contextVk)476 angle::Result UtilsVk::ensureBufferClearResourcesInitialized(ContextVk *contextVk)
477 {
478     if (mPipelineLayouts[Function::BufferClear].valid())
479     {
480         return angle::Result::Continue;
481     }
482 
483     VkDescriptorPoolSize setSizes[1] = {
484         {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1},
485     };
486 
487     return ensureResourcesInitialized(contextVk, Function::BufferClear, setSizes,
488                                       ArraySize(setSizes), sizeof(BufferUtilsShaderParams));
489 }
490 
ensureConvertIndexResourcesInitialized(ContextVk * contextVk)491 angle::Result UtilsVk::ensureConvertIndexResourcesInitialized(ContextVk *contextVk)
492 {
493     if (mPipelineLayouts[Function::ConvertIndexBuffer].valid())
494     {
495         return angle::Result::Continue;
496     }
497 
498     VkDescriptorPoolSize setSizes[2] = {
499         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
500         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
501     };
502 
503     return ensureResourcesInitialized(contextVk, Function::ConvertIndexBuffer, setSizes,
504                                       ArraySize(setSizes), sizeof(ConvertIndexShaderParams));
505 }
506 
ensureConvertIndexIndirectResourcesInitialized(ContextVk * contextVk)507 angle::Result UtilsVk::ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk)
508 {
509     if (mPipelineLayouts[Function::ConvertIndexIndirectBuffer].valid())
510     {
511         return angle::Result::Continue;
512     }
513 
514     VkDescriptorPoolSize setSizes[4] = {
515         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest index buffer
516         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // source index buffer
517         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // src indirect buffer
518         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest indirect buffer
519     };
520 
521     return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectBuffer, setSizes,
522                                       ArraySize(setSizes),
523                                       sizeof(ConvertIndexIndirectShaderParams));
524 }
525 
ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk * contextVk)526 angle::Result UtilsVk::ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
527 {
528     if (mPipelineLayouts[Function::ConvertIndexIndirectLineLoopBuffer].valid())
529     {
530         return angle::Result::Continue;
531     }
532 
533     VkDescriptorPoolSize setSizes[4] = {
534         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // cmd buffer
535         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest cmd buffer
536         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // source index buffer
537         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest index buffer
538     };
539 
540     return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
541                                       setSizes, ArraySize(setSizes),
542                                       sizeof(ConvertIndexIndirectLineLoopShaderParams));
543 }
544 
ensureConvertIndirectLineLoopResourcesInitialized(ContextVk * contextVk)545 angle::Result UtilsVk::ensureConvertIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
546 {
547     if (mPipelineLayouts[Function::ConvertIndirectLineLoopBuffer].valid())
548     {
549         return angle::Result::Continue;
550     }
551 
552     VkDescriptorPoolSize setSizes[3] = {
553         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // cmd buffer
554         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest cmd buffer
555         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest index buffer
556     };
557 
558     return ensureResourcesInitialized(contextVk, Function::ConvertIndirectLineLoopBuffer, setSizes,
559                                       ArraySize(setSizes),
560                                       sizeof(ConvertIndirectLineLoopShaderParams));
561 }
562 
ensureConvertVertexResourcesInitialized(ContextVk * contextVk)563 angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk)
564 {
565     if (mPipelineLayouts[Function::ConvertVertexBuffer].valid())
566     {
567         return angle::Result::Continue;
568     }
569 
570     VkDescriptorPoolSize setSizes[2] = {
571         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
572         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
573     };
574 
575     return ensureResourcesInitialized(contextVk, Function::ConvertVertexBuffer, setSizes,
576                                       ArraySize(setSizes), sizeof(ConvertVertexShaderParams));
577 }
578 
ensureImageClearResourcesInitialized(ContextVk * contextVk)579 angle::Result UtilsVk::ensureImageClearResourcesInitialized(ContextVk *contextVk)
580 {
581     if (mPipelineLayouts[Function::ImageClear].valid())
582     {
583         return angle::Result::Continue;
584     }
585 
586     // The shader does not use any descriptor sets.
587     return ensureResourcesInitialized(contextVk, Function::ImageClear, nullptr, 0,
588                                       sizeof(ImageClearShaderParams));
589 }
590 
ensureImageCopyResourcesInitialized(ContextVk * contextVk)591 angle::Result UtilsVk::ensureImageCopyResourcesInitialized(ContextVk *contextVk)
592 {
593     if (mPipelineLayouts[Function::ImageCopy].valid())
594     {
595         return angle::Result::Continue;
596     }
597 
598     VkDescriptorPoolSize setSizes[1] = {
599         {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
600     };
601 
602     return ensureResourcesInitialized(contextVk, Function::ImageCopy, setSizes, ArraySize(setSizes),
603                                       sizeof(ImageCopyShaderParams));
604 }
605 
ensureBlitResolveResourcesInitialized(ContextVk * contextVk)606 angle::Result UtilsVk::ensureBlitResolveResourcesInitialized(ContextVk *contextVk)
607 {
608     if (!mPipelineLayouts[Function::BlitResolve].valid())
609     {
610         VkDescriptorPoolSize setSizes[3] = {
611             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
612             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
613             {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
614         };
615 
616         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolve, setSizes,
617                                              ArraySize(setSizes), sizeof(BlitResolveShaderParams)));
618     }
619 
620     return ensureSamplersInitialized(contextVk);
621 }
622 
ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk * contextVk)623 angle::Result UtilsVk::ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk *contextVk)
624 {
625     if (!mPipelineLayouts[Function::BlitResolveStencilNoExport].valid())
626     {
627         VkDescriptorPoolSize setSizes[3] = {
628             {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
629             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
630             {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
631         };
632 
633         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolveStencilNoExport,
634                                              setSizes, ArraySize(setSizes),
635                                              sizeof(BlitResolveStencilNoExportShaderParams)));
636     }
637 
638     return ensureSamplersInitialized(contextVk);
639 }
640 
ensureOverlayCullResourcesInitialized(ContextVk * contextVk)641 angle::Result UtilsVk::ensureOverlayCullResourcesInitialized(ContextVk *contextVk)
642 {
643     if (mPipelineLayouts[Function::OverlayCull].valid())
644     {
645         return angle::Result::Continue;
646     }
647 
648     VkDescriptorPoolSize setSizes[2] = {
649         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
650         {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
651     };
652 
653     return ensureResourcesInitialized(contextVk, Function::OverlayCull, setSizes,
654                                       ArraySize(setSizes), 0);
655 }
656 
ensureOverlayDrawResourcesInitialized(ContextVk * contextVk)657 angle::Result UtilsVk::ensureOverlayDrawResourcesInitialized(ContextVk *contextVk)
658 {
659     if (!mPipelineLayouts[Function::OverlayDraw].valid())
660     {
661         VkDescriptorPoolSize setSizes[5] = {
662             {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},  {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
663             {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1}, {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
664             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
665         };
666 
667         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::OverlayDraw, setSizes,
668                                              ArraySize(setSizes), sizeof(OverlayDrawShaderParams)));
669     }
670 
671     return ensureSamplersInitialized(contextVk);
672 }
673 
ensureSamplersInitialized(ContextVk * contextVk)674 angle::Result UtilsVk::ensureSamplersInitialized(ContextVk *contextVk)
675 {
676     VkSamplerCreateInfo samplerInfo     = {};
677     samplerInfo.sType                   = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
678     samplerInfo.flags                   = 0;
679     samplerInfo.magFilter               = VK_FILTER_NEAREST;
680     samplerInfo.minFilter               = VK_FILTER_NEAREST;
681     samplerInfo.mipmapMode              = VK_SAMPLER_MIPMAP_MODE_NEAREST;
682     samplerInfo.addressModeU            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
683     samplerInfo.addressModeV            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
684     samplerInfo.addressModeW            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
685     samplerInfo.mipLodBias              = 0.0f;
686     samplerInfo.anisotropyEnable        = VK_FALSE;
687     samplerInfo.maxAnisotropy           = 1;
688     samplerInfo.compareEnable           = VK_FALSE;
689     samplerInfo.compareOp               = VK_COMPARE_OP_ALWAYS;
690     samplerInfo.minLod                  = 0;
691     samplerInfo.maxLod                  = 0;
692     samplerInfo.borderColor             = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
693     samplerInfo.unnormalizedCoordinates = VK_FALSE;
694 
695     if (!mPointSampler.valid())
696     {
697         ANGLE_VK_TRY(contextVk, mPointSampler.init(contextVk->getDevice(), samplerInfo));
698     }
699 
700     samplerInfo.magFilter = VK_FILTER_LINEAR;
701     samplerInfo.minFilter = VK_FILTER_LINEAR;
702 
703     if (!mLinearSampler.valid())
704     {
705         ANGLE_VK_TRY(contextVk, mLinearSampler.init(contextVk->getDevice(), samplerInfo));
706     }
707 
708     return angle::Result::Continue;
709 }
710 
setupProgram(ContextVk * contextVk,Function function,vk::RefCounted<vk::ShaderAndSerial> * fsCsShader,vk::RefCounted<vk::ShaderAndSerial> * vsShader,vk::ShaderProgramHelper * program,const vk::GraphicsPipelineDesc * pipelineDesc,const VkDescriptorSet descriptorSet,const void * pushConstants,size_t pushConstantsSize,vk::CommandBuffer * commandBuffer)711 angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
712                                     Function function,
713                                     vk::RefCounted<vk::ShaderAndSerial> *fsCsShader,
714                                     vk::RefCounted<vk::ShaderAndSerial> *vsShader,
715                                     vk::ShaderProgramHelper *program,
716                                     const vk::GraphicsPipelineDesc *pipelineDesc,
717                                     const VkDescriptorSet descriptorSet,
718                                     const void *pushConstants,
719                                     size_t pushConstantsSize,
720                                     vk::CommandBuffer *commandBuffer)
721 {
722     RendererVk *renderer = contextVk->getRenderer();
723 
724     const bool isCompute = function >= Function::ComputeStartIndex;
725     const VkShaderStageFlags pushConstantsShaderStage =
726         isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
727     const VkPipelineBindPoint pipelineBindPoint =
728         isCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
729 
730     // If compute, vsShader and pipelineDesc should be nullptr, and if not compute they shouldn't
731     // be.
732     ASSERT(isCompute != (vsShader && pipelineDesc));
733 
734     const vk::BindingPointer<vk::PipelineLayout> &pipelineLayout = mPipelineLayouts[function];
735 
736     Serial serial = contextVk->getCurrentQueueSerial();
737 
738     if (isCompute)
739     {
740         vk::PipelineAndSerial *pipelineAndSerial;
741         program->setShader(gl::ShaderType::Compute, fsCsShader);
742         ANGLE_TRY(program->getComputePipeline(contextVk, pipelineLayout.get(), &pipelineAndSerial));
743         pipelineAndSerial->updateSerial(serial);
744         commandBuffer->bindComputePipeline(pipelineAndSerial->get());
745     }
746     else
747     {
748         program->setShader(gl::ShaderType::Vertex, vsShader);
749         if (fsCsShader)
750         {
751             program->setShader(gl::ShaderType::Fragment, fsCsShader);
752         }
753 
754         // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
755         const vk::GraphicsPipelineDesc *descPtr;
756         vk::PipelineHelper *helper;
757         vk::PipelineCache *pipelineCache = nullptr;
758         ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
759         ANGLE_TRY(program->getGraphicsPipeline(contextVk, &contextVk->getRenderPassCache(),
760                                                *pipelineCache, serial, pipelineLayout.get(),
761                                                *pipelineDesc, gl::AttributesMask(),
762                                                gl::ComponentTypeMask(), &descPtr, &helper));
763         helper->updateSerial(serial);
764         commandBuffer->bindGraphicsPipeline(helper->getPipeline());
765     }
766 
767     if (descriptorSet != VK_NULL_HANDLE)
768     {
769         commandBuffer->bindDescriptorSets(pipelineLayout.get(), pipelineBindPoint, 0, 1,
770                                           &descriptorSet, 0, nullptr);
771         if (isCompute)
772         {
773             contextVk->invalidateComputeDescriptorSet(0);
774         }
775         else
776         {
777             contextVk->invalidateGraphicsDescriptorSet(0);
778         }
779     }
780 
781     if (pushConstants)
782     {
783         commandBuffer->pushConstants(pipelineLayout.get(), pushConstantsShaderStage, 0,
784                                      static_cast<uint32_t>(pushConstantsSize), pushConstants);
785     }
786 
787     return angle::Result::Continue;
788 }
789 
clearBuffer(ContextVk * contextVk,vk::BufferHelper * dest,const ClearParameters & params)790 angle::Result UtilsVk::clearBuffer(ContextVk *contextVk,
791                                    vk::BufferHelper *dest,
792                                    const ClearParameters &params)
793 {
794     ANGLE_TRY(ensureBufferClearResourcesInitialized(contextVk));
795 
796     vk::CommandBuffer *commandBuffer;
797     // Tell the context dest that we are writing to dest.
798     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dest));
799     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
800 
801     const vk::Format &destFormat = dest->getViewFormat();
802 
803     uint32_t flags = BufferUtils_comp::kIsClear | GetBufferUtilsFlags(params.size, destFormat);
804 
805     BufferUtilsShaderParams shaderParams;
806     shaderParams.destOffset = static_cast<uint32_t>(params.offset);
807     shaderParams.size       = static_cast<uint32_t>(params.size);
808     shaderParams.clearValue = params.clearValue;
809 
810     VkDescriptorSet descriptorSet;
811     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
812     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BufferClear, &descriptorPoolBinding,
813                                     &descriptorSet));
814 
815     VkWriteDescriptorSet writeInfo = {};
816 
817     writeInfo.sType            = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
818     writeInfo.dstSet           = descriptorSet;
819     writeInfo.dstBinding       = kBufferClearOutputBinding;
820     writeInfo.descriptorCount  = 1;
821     writeInfo.descriptorType   = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
822     writeInfo.pTexelBufferView = dest->getBufferView().ptr();
823 
824     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
825 
826     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
827     ANGLE_TRY(contextVk->getShaderLibrary().getBufferUtils_comp(contextVk, flags, &shader));
828 
829     ANGLE_TRY(setupProgram(contextVk, Function::BufferClear, shader, nullptr,
830                            &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
831                            sizeof(shaderParams), commandBuffer));
832 
833     commandBuffer->dispatch(UnsignedCeilDivide(static_cast<uint32_t>(params.size), 64), 1, 1);
834 
835     descriptorPoolBinding.reset();
836 
837     return angle::Result::Continue;
838 }
839 
convertIndexBuffer(ContextVk * contextVk,vk::BufferHelper * dest,vk::BufferHelper * src,const ConvertIndexParameters & params)840 angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
841                                           vk::BufferHelper *dest,
842                                           vk::BufferHelper *src,
843                                           const ConvertIndexParameters &params)
844 {
845     ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk));
846 
847     vk::CommandBuffer *commandBuffer;
848     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, src));
849     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dest));
850     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
851 
852     VkDescriptorSet descriptorSet;
853     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
854     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexBuffer, &descriptorPoolBinding,
855                                     &descriptorSet));
856 
857     std::array<VkDescriptorBufferInfo, 2> buffers = {{
858         {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
859         {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
860     }};
861 
862     VkWriteDescriptorSet writeInfo = {};
863     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
864     writeInfo.dstSet               = descriptorSet;
865     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
866     writeInfo.descriptorCount      = 2;
867     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
868     writeInfo.pBufferInfo          = buffers.data();
869 
870     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
871 
872     ConvertIndexShaderParams shaderParams = {params.srcOffset, params.dstOffset >> 2,
873                                              params.maxIndex, 0};
874 
875     uint32_t flags = 0;
876     if (contextVk->getState().isPrimitiveRestartEnabled())
877     {
878         flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
879     }
880 
881     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
882     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
883 
884     ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexBuffer, shader, nullptr,
885                            &mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
886                            sizeof(ConvertIndexShaderParams), commandBuffer));
887 
888     constexpr uint32_t kInvocationsPerGroup = 64;
889     constexpr uint32_t kInvocationsPerIndex = 2;
890     const uint32_t kIndexCount              = params.maxIndex - params.srcOffset;
891     const uint32_t kGroupCount =
892         UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
893     commandBuffer->dispatch(kGroupCount, 1, 1);
894 
895     descriptorPoolBinding.reset();
896 
897     return angle::Result::Continue;
898 }
899 
convertIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuf,vk::BufferHelper * srcIndexBuf,vk::BufferHelper * dstIndirectBuf,vk::BufferHelper * dstIndexBuf,const ConvertIndexIndirectParameters & params)900 angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
901                                                   vk::BufferHelper *srcIndirectBuf,
902                                                   vk::BufferHelper *srcIndexBuf,
903                                                   vk::BufferHelper *dstIndirectBuf,
904                                                   vk::BufferHelper *dstIndexBuf,
905                                                   const ConvertIndexIndirectParameters &params)
906 {
907     ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk));
908 
909     vk::CommandBuffer *commandBuffer;
910     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndirectBuf));
911     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndexBuf));
912     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndirectBuf));
913     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndexBuf));
914     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
915 
916     VkDescriptorSet descriptorSet;
917     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
918     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexIndirectBuffer,
919                                     &descriptorPoolBinding, &descriptorSet));
920 
921     std::array<VkDescriptorBufferInfo, 4> buffers = {{
922         {dstIndexBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
923         {srcIndexBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
924         {srcIndirectBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
925         {dstIndirectBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
926     }};
927 
928     VkWriteDescriptorSet writeInfo = {};
929     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
930     writeInfo.dstSet               = descriptorSet;
931     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
932     writeInfo.descriptorCount      = 4;
933     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
934     writeInfo.pBufferInfo          = buffers.data();
935 
936     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
937 
938     ConvertIndexIndirectShaderParams shaderParams = {params.srcIndirectBufOffset >> 2,
939                                                      params.dstIndexBufOffset >> 2, params.maxIndex,
940                                                      params.dstIndirectBufOffset >> 2};
941 
942     uint32_t flags = vk::InternalShader::ConvertIndex_comp::kIsIndirect;
943     if (contextVk->getState().isPrimitiveRestartEnabled())
944     {
945         flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
946     }
947 
948     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
949     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
950 
951     ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader, nullptr,
952                            &mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
953                            sizeof(ConvertIndexIndirectShaderParams), commandBuffer));
954 
955     constexpr uint32_t kInvocationsPerGroup = 64;
956     constexpr uint32_t kInvocationsPerIndex = 2;
957     const uint32_t kIndexCount              = params.maxIndex;
958     const uint32_t kGroupCount =
959         UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
960     commandBuffer->dispatch(kGroupCount, 1, 1);
961 
962     descriptorPoolBinding.reset();
963 
964     return angle::Result::Continue;
965 }
966 
convertLineLoopIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * dstIndirectBuffer,vk::BufferHelper * dstIndexBuffer,vk::BufferHelper * srcIndexBuffer,const ConvertLineLoopIndexIndirectParameters & params)967 angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
968     ContextVk *contextVk,
969     vk::BufferHelper *srcIndirectBuffer,
970     vk::BufferHelper *dstIndirectBuffer,
971     vk::BufferHelper *dstIndexBuffer,
972     vk::BufferHelper *srcIndexBuffer,
973     const ConvertLineLoopIndexIndirectParameters &params)
974 {
975     ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk));
976 
977     vk::CommandBuffer *commandBuffer;
978     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer));
979     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndexBuffer));
980     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndirectBuffer));
981     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndexBuffer));
982     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
983 
984     VkDescriptorSet descriptorSet;
985     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
986     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
987                                     &descriptorPoolBinding, &descriptorSet));
988 
989     std::array<VkDescriptorBufferInfo, 4> buffers = {{
990         {dstIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
991         {srcIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
992         {srcIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
993         {dstIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
994     }};
995 
996     VkWriteDescriptorSet writeInfo = {};
997     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
998     writeInfo.dstSet               = descriptorSet;
999     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
1000     writeInfo.descriptorCount      = 4;
1001     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1002     writeInfo.pBufferInfo          = buffers.data();
1003 
1004     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1005 
1006     ConvertIndexIndirectLineLoopShaderParams shaderParams = {
1007         params.indirectBufferOffset >> 2, params.dstIndirectBufferOffset >> 2,
1008         params.dstIndexBufferOffset >> 2, contextVk->getState().isPrimitiveRestartEnabled()};
1009 
1010     uint32_t flags = GetConvertIndexIndirectLineLoopFlag(params.indicesBitsWidth);
1011 
1012     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1013     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndexIndirectLineLoop_comp(contextVk, flags,
1014                                                                                  &shader));
1015 
1016     ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader, nullptr,
1017                            &mConvertIndexIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
1018                            &shaderParams, sizeof(ConvertIndexIndirectLineLoopShaderParams),
1019                            commandBuffer));
1020 
1021     commandBuffer->dispatch(1, 1, 1);
1022 
1023     descriptorPoolBinding.reset();
1024 
1025     return angle::Result::Continue;
1026 }
1027 
convertLineLoopArrayIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * destIndirectBuffer,vk::BufferHelper * destIndexBuffer,const ConvertLineLoopArrayIndirectParameters & params)1028 angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer(
1029     ContextVk *contextVk,
1030     vk::BufferHelper *srcIndirectBuffer,
1031     vk::BufferHelper *destIndirectBuffer,
1032     vk::BufferHelper *destIndexBuffer,
1033     const ConvertLineLoopArrayIndirectParameters &params)
1034 {
1035     ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk));
1036 
1037     vk::CommandBuffer *commandBuffer;
1038     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer));
1039     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, destIndirectBuffer));
1040     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, destIndexBuffer));
1041     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1042 
1043     VkDescriptorSet descriptorSet;
1044     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1045     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndirectLineLoopBuffer,
1046                                     &descriptorPoolBinding, &descriptorSet));
1047 
1048     std::array<VkDescriptorBufferInfo, 3> buffers = {{
1049         {srcIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1050         {destIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1051         {destIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1052     }};
1053 
1054     VkWriteDescriptorSet writeInfo = {};
1055     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1056     writeInfo.dstSet               = descriptorSet;
1057     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
1058     writeInfo.descriptorCount      = 3;
1059     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1060     writeInfo.pBufferInfo          = buffers.data();
1061 
1062     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1063 
1064     ConvertIndirectLineLoopShaderParams shaderParams = {params.indirectBufferOffset >> 2,
1065                                                         params.dstIndirectBufferOffset >> 2,
1066                                                         params.dstIndexBufferOffset >> 2};
1067 
1068     uint32_t flags = 0;
1069 
1070     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1071     ANGLE_TRY(
1072         contextVk->getShaderLibrary().getConvertIndirectLineLoop_comp(contextVk, flags, &shader));
1073 
1074     ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndirectLineLoopBuffer, shader, nullptr,
1075                            &mConvertIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
1076                            &shaderParams, sizeof(ConvertIndirectLineLoopShaderParams),
1077                            commandBuffer));
1078 
1079     commandBuffer->dispatch(1, 1, 1);
1080 
1081     descriptorPoolBinding.reset();
1082 
1083     return angle::Result::Continue;
1084 }
1085 
convertVertexBuffer(ContextVk * contextVk,vk::BufferHelper * dest,vk::BufferHelper * src,const ConvertVertexParameters & params)1086 angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk,
1087                                            vk::BufferHelper *dest,
1088                                            vk::BufferHelper *src,
1089                                            const ConvertVertexParameters &params)
1090 {
1091     ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk));
1092 
1093     vk::CommandBuffer *commandBuffer;
1094     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, src));
1095     ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dest));
1096     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1097 
1098     ConvertVertexShaderParams shaderParams;
1099     shaderParams.Ns = params.srcFormat->channelCount;
1100     shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount;
1101     shaderParams.Ss = static_cast<uint32_t>(params.srcStride);
1102     shaderParams.Nd = params.destFormat->channelCount;
1103     shaderParams.Bd = params.destFormat->pixelBytes / params.destFormat->channelCount;
1104     shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
1105     // The component size is expected to either be 1, 2 or 4 bytes.
1106     ASSERT(4 % shaderParams.Bs == 0);
1107     ASSERT(4 % shaderParams.Bd == 0);
1108     shaderParams.Es = 4 / shaderParams.Bs;
1109     shaderParams.Ed = 4 / shaderParams.Bd;
1110     // Total number of output components is simply the number of vertices by number of components in
1111     // each.
1112     shaderParams.componentCount = static_cast<uint32_t>(params.vertexCount * shaderParams.Nd);
1113     // Total number of 4-byte outputs is the number of components divided by how many components can
1114     // fit in a 4-byte value.  Note that this value is also the invocation size of the shader.
1115     shaderParams.outputCount = shaderParams.componentCount / shaderParams.Ed;
1116     shaderParams.srcOffset   = static_cast<uint32_t>(params.srcOffset);
1117     shaderParams.destOffset  = static_cast<uint32_t>(params.destOffset);
1118 
1119     uint32_t flags = GetConvertVertexFlags(params);
1120 
1121     VkDescriptorSet descriptorSet;
1122     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1123     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertVertexBuffer,
1124                                     &descriptorPoolBinding, &descriptorSet));
1125 
1126     VkWriteDescriptorSet writeInfo    = {};
1127     VkDescriptorBufferInfo buffers[2] = {
1128         {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1129         {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1130     };
1131     static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
1132                   "Update write info");
1133 
1134     writeInfo.sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1135     writeInfo.dstSet          = descriptorSet;
1136     writeInfo.dstBinding      = kConvertVertexDestinationBinding;
1137     writeInfo.descriptorCount = 2;
1138     writeInfo.descriptorType  = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1139     writeInfo.pBufferInfo     = buffers;
1140 
1141     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1142 
1143     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1144     ANGLE_TRY(contextVk->getShaderLibrary().getConvertVertex_comp(contextVk, flags, &shader));
1145 
1146     ANGLE_TRY(setupProgram(contextVk, Function::ConvertVertexBuffer, shader, nullptr,
1147                            &mConvertVertexPrograms[flags], nullptr, descriptorSet, &shaderParams,
1148                            sizeof(shaderParams), commandBuffer));
1149 
1150     commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
1151 
1152     descriptorPoolBinding.reset();
1153 
1154     return angle::Result::Continue;
1155 }
1156 
startRenderPass(ContextVk * contextVk,vk::ImageHelper * image,const vk::ImageView * imageView,const vk::RenderPassDesc & renderPassDesc,const gl::Rectangle & renderArea,vk::CommandBuffer ** commandBufferOut)1157 angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
1158                                        vk::ImageHelper *image,
1159                                        const vk::ImageView *imageView,
1160                                        const vk::RenderPassDesc &renderPassDesc,
1161                                        const gl::Rectangle &renderArea,
1162                                        vk::CommandBuffer **commandBufferOut)
1163 {
1164     vk::RenderPass *compatibleRenderPass = nullptr;
1165     ANGLE_TRY(contextVk->getCompatibleRenderPass(renderPassDesc, &compatibleRenderPass));
1166 
1167     VkFramebufferCreateInfo framebufferInfo = {};
1168 
1169     // Minimize the framebuffer coverage to only cover up to the render area.
1170     framebufferInfo.sType           = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
1171     framebufferInfo.flags           = 0;
1172     framebufferInfo.renderPass      = compatibleRenderPass->getHandle();
1173     framebufferInfo.attachmentCount = 1;
1174     framebufferInfo.pAttachments    = imageView->ptr();
1175     framebufferInfo.width           = renderArea.x + renderArea.width;
1176     framebufferInfo.height          = renderArea.y + renderArea.height;
1177     framebufferInfo.layers          = 1;
1178     if (contextVk->isRotatedAspectRatioForDrawFBO())
1179     {
1180         // The surface is rotated 90/270 degrees.  This changes the aspect ratio of
1181         // the surface.  Swap the width and height of the framebuffer.
1182         std::swap(framebufferInfo.width, framebufferInfo.height);
1183     }
1184 
1185     vk::Framebuffer framebuffer;
1186     ANGLE_VK_TRY(contextVk, framebuffer.init(contextVk->getDevice(), framebufferInfo));
1187 
1188     vk::AttachmentOpsArray renderPassAttachmentOps;
1189     std::vector<VkClearValue> clearValues = {{}};
1190     ASSERT(clearValues.size() == 1);
1191 
1192     renderPassAttachmentOps.initWithStore(0, VK_ATTACHMENT_LOAD_OP_LOAD,
1193                                           vk::ImageLayout::ColorAttachment,
1194                                           vk::ImageLayout::ColorAttachment);
1195 
1196     ANGLE_TRY(contextVk->flushAndBeginRenderPass(framebuffer, renderArea, renderPassDesc,
1197                                                  renderPassAttachmentOps, clearValues,
1198                                                  commandBufferOut));
1199 
1200     contextVk->addGarbage(&framebuffer);
1201 
1202     return angle::Result::Continue;
1203 }
1204 
clearFramebuffer(ContextVk * contextVk,FramebufferVk * framebuffer,const ClearFramebufferParameters & params)1205 angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
1206                                         FramebufferVk *framebuffer,
1207                                         const ClearFramebufferParameters &params)
1208 {
1209     ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
1210 
1211     const gl::Rectangle &scissoredRenderArea = params.clearArea;
1212 
1213     vk::CommandBuffer *commandBuffer;
1214     ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, scissoredRenderArea, &commandBuffer));
1215 
1216     ImageClearShaderParams shaderParams;
1217     shaderParams.clearValue = params.colorClearValue;
1218 
1219     vk::GraphicsPipelineDesc pipelineDesc;
1220     pipelineDesc.initDefaults();
1221     pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
1222     pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask());
1223     pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags);
1224     pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
1225     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
1226     // Note: depth test is disabled by default so this should be unnecessary, but works around an
1227     // Intel bug on windows.  http://anglebug.com/3348
1228     pipelineDesc.setDepthWriteEnabled(false);
1229 
1230     // Clear stencil by enabling stencil write with the right mask.
1231     if (params.clearStencil)
1232     {
1233         const uint8_t compareMask       = 0xFF;
1234         const uint8_t clearStencilValue = params.stencilClearValue;
1235 
1236         pipelineDesc.setStencilTestEnabled(true);
1237         pipelineDesc.setStencilFrontFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
1238         pipelineDesc.setStencilBackFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
1239         pipelineDesc.setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1240                                         VK_STENCIL_OP_REPLACE);
1241         pipelineDesc.setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1242                                        VK_STENCIL_OP_REPLACE);
1243         pipelineDesc.setStencilFrontWriteMask(params.stencilMask);
1244         pipelineDesc.setStencilBackWriteMask(params.stencilMask);
1245     }
1246 
1247     VkViewport viewport;
1248     gl::Rectangle completeRenderArea = framebuffer->getCompleteRenderArea();
1249     bool invertViewport              = contextVk->isViewportFlipEnabledForDrawFBO();
1250     gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, completeRenderArea.height,
1251                        &viewport);
1252     pipelineDesc.setViewport(viewport);
1253 
1254     pipelineDesc.setScissor(gl_vk::GetRect(params.clearArea));
1255 
1256     vk::ShaderLibrary &shaderLibrary                    = contextVk->getShaderLibrary();
1257     vk::RefCounted<vk::ShaderAndSerial> *vertexShader   = nullptr;
1258     vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
1259     vk::ShaderProgramHelper *imageClearProgram          = &mImageClearProgramVSOnly;
1260 
1261     ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
1262     if (params.clearColor)
1263     {
1264         uint32_t flags = GetImageClearFlags(*params.colorFormat, params.colorAttachmentIndexGL);
1265         ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
1266         imageClearProgram = &mImageClearProgram[flags];
1267     }
1268 
1269     ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
1270                            imageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
1271                            sizeof(shaderParams), commandBuffer));
1272     commandBuffer->draw(6, 0);
1273     return angle::Result::Continue;
1274 }
1275 
colorBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcView,const BlitResolveParameters & params)1276 angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk,
1277                                         FramebufferVk *framebuffer,
1278                                         vk::ImageHelper *src,
1279                                         const vk::ImageView *srcView,
1280                                         const BlitResolveParameters &params)
1281 {
1282     return blitResolveImpl(contextVk, framebuffer, src, srcView, nullptr, nullptr, params);
1283 }
1284 
depthStencilBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)1285 angle::Result UtilsVk::depthStencilBlitResolve(ContextVk *contextVk,
1286                                                FramebufferVk *framebuffer,
1287                                                vk::ImageHelper *src,
1288                                                const vk::ImageView *srcDepthView,
1289                                                const vk::ImageView *srcStencilView,
1290                                                const BlitResolveParameters &params)
1291 {
1292     return blitResolveImpl(contextVk, framebuffer, src, nullptr, srcDepthView, srcStencilView,
1293                            params);
1294 }
1295 
blitResolveImpl(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcColorView,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)1296 angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
1297                                        FramebufferVk *framebuffer,
1298                                        vk::ImageHelper *src,
1299                                        const vk::ImageView *srcColorView,
1300                                        const vk::ImageView *srcDepthView,
1301                                        const vk::ImageView *srcStencilView,
1302                                        const BlitResolveParameters &params)
1303 {
1304     // Possible ways to resolve color are:
1305     //
1306     // - vkCmdResolveImage: This is by far the easiest method, but lacks the ability to flip
1307     //   images during resolve.
1308     // - Manual resolve: A shader can read all samples from input, average them and output.
1309     // - Using subpass resolve attachment: A shader can transform the sample colors from source to
1310     //   destination coordinates and the subpass resolve would finish the job.
1311     //
1312     // The first method is unable to handle flipping, so it's not generally applicable.  The last
1313     // method would have been great were we able to modify the last render pass that rendered into
1314     // source, but still wouldn't be able to handle flipping.  The second method is implemented in
1315     // this function for complete control.
1316 
1317     // Possible ways to resolve depth/stencil are:
1318     //
1319     // - Manual resolve: A shader can read a samples from input and choose that for output.
1320     // - Using subpass resolve attachment through VkSubpassDescriptionDepthStencilResolveKHR: This
1321     //   requires an extension that's not very well supported.
1322     //
1323     // The first method is implemented in this function.
1324 
1325     // Possible ways to blit color, depth or stencil are:
1326     //
1327     // - vkCmdBlitImage: This function works if the source and destination formats have the blit
1328     //   feature.
1329     // - Manual blit: A shader can sample from the source image and write it to the destination.
1330     //
1331     // The first method has a serious shortcoming.  GLES allows blit parameters to exceed the
1332     // source or destination boundaries.  The actual blit is clipped to these limits, but the
1333     // scaling applied is determined solely by the input areas.  Vulkan requires the blit parameters
1334     // to be within the source and destination bounds.  This makes it hard to keep the scaling
1335     // constant.
1336     //
1337     // The second method is implemented in this function, which shares code with the resolve method.
1338 
1339     ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
1340 
1341     bool isResolve = src->getSamples() > 1;
1342 
1343     BlitResolveShaderParams shaderParams;
1344     if (isResolve)
1345     {
1346         CalculateResolveOffset(params, shaderParams.offset.resolve);
1347     }
1348     else
1349     {
1350         CalculateBlitOffset(params, shaderParams.offset.blit);
1351     }
1352     shaderParams.stretch[0]      = params.stretch[0];
1353     shaderParams.stretch[1]      = params.stretch[1];
1354     shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
1355     shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
1356     shaderParams.srcLayer        = params.srcLayer;
1357     shaderParams.samples         = src->getSamples();
1358     shaderParams.invSamples      = 1.0f / shaderParams.samples;
1359     shaderParams.outputMask =
1360         static_cast<uint32_t>(framebuffer->getState().getEnabledDrawBuffers().to_ulong());
1361     shaderParams.flipX = params.flipX;
1362     shaderParams.flipY = params.flipY;
1363 
1364     bool blitColor   = srcColorView != nullptr;
1365     bool blitDepth   = srcDepthView != nullptr;
1366     bool blitStencil = srcStencilView != nullptr;
1367 
1368     // Either color is blitted/resolved or depth/stencil, but not both.
1369     ASSERT(blitColor != (blitDepth || blitStencil));
1370 
1371     // Linear sampling is only valid with color blitting.
1372     ASSERT((blitColor && !isResolve) || !params.linear);
1373 
1374     uint32_t flags = GetBlitResolveFlags(blitColor, blitDepth, blitStencil, src->getFormat());
1375     flags |= src->getLayerCount() > 1 ? BlitResolve_frag::kSrcIsArray : 0;
1376     flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
1377 
1378     VkDescriptorSet descriptorSet;
1379     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1380     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BlitResolve, &descriptorPoolBinding,
1381                                     &descriptorSet));
1382 
1383     constexpr VkColorComponentFlags kAllColorComponents =
1384         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
1385         VK_COLOR_COMPONENT_A_BIT;
1386 
1387     vk::GraphicsPipelineDesc pipelineDesc;
1388     pipelineDesc.initDefaults();
1389     if (blitColor)
1390     {
1391         pipelineDesc.setColorWriteMask(kAllColorComponents,
1392                                        framebuffer->getEmulatedAlphaAttachmentMask());
1393     }
1394     else
1395     {
1396         pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask());
1397     }
1398     pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
1399     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
1400     pipelineDesc.setDepthTestEnabled(blitDepth);
1401     pipelineDesc.setDepthWriteEnabled(blitDepth);
1402     pipelineDesc.setDepthFunc(VK_COMPARE_OP_ALWAYS);
1403 
1404     if (blitStencil)
1405     {
1406         ASSERT(contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled);
1407 
1408         const uint8_t completeMask    = 0xFF;
1409         const uint8_t unusedReference = 0x00;
1410 
1411         pipelineDesc.setStencilTestEnabled(true);
1412         pipelineDesc.setStencilFrontFuncs(unusedReference, VK_COMPARE_OP_ALWAYS, completeMask);
1413         pipelineDesc.setStencilBackFuncs(unusedReference, VK_COMPARE_OP_ALWAYS, completeMask);
1414         pipelineDesc.setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1415                                         VK_STENCIL_OP_REPLACE);
1416         pipelineDesc.setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1417                                        VK_STENCIL_OP_REPLACE);
1418         pipelineDesc.setStencilFrontWriteMask(completeMask);
1419         pipelineDesc.setStencilBackWriteMask(completeMask);
1420     }
1421 
1422     VkViewport viewport;
1423     gl::Rectangle completeRenderArea = framebuffer->getCompleteRenderArea();
1424     gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, completeRenderArea.height, &viewport);
1425     pipelineDesc.setViewport(viewport);
1426 
1427     pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
1428 
1429     // Change source layout outside render pass
1430     ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
1431                                      src));
1432 
1433     vk::CommandBuffer *commandBuffer;
1434     ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer));
1435 
1436     VkDescriptorImageInfo imageInfos[2] = {};
1437 
1438     if (blitColor)
1439     {
1440         imageInfos[0].imageView   = srcColorView->getHandle();
1441         imageInfos[0].imageLayout = src->getCurrentLayout();
1442     }
1443     if (blitDepth)
1444     {
1445         imageInfos[0].imageView   = srcDepthView->getHandle();
1446         imageInfos[0].imageLayout = src->getCurrentLayout();
1447     }
1448     if (blitStencil)
1449     {
1450         imageInfos[1].imageView   = srcStencilView->getHandle();
1451         imageInfos[1].imageLayout = src->getCurrentLayout();
1452     }
1453 
1454     VkDescriptorImageInfo samplerInfo = {};
1455     samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
1456 
1457     VkWriteDescriptorSet writeInfos[3] = {};
1458     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1459     writeInfos[0].dstSet               = descriptorSet;
1460     writeInfos[0].dstBinding           = kBlitResolveColorOrDepthBinding;
1461     writeInfos[0].descriptorCount      = 1;
1462     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1463     writeInfos[0].pImageInfo           = &imageInfos[0];
1464 
1465     writeInfos[1]            = writeInfos[0];
1466     writeInfos[1].dstBinding = kBlitResolveStencilBinding;
1467     writeInfos[1].pImageInfo = &imageInfos[1];
1468 
1469     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1470     writeInfos[2].dstSet          = descriptorSet;
1471     writeInfos[2].dstBinding      = kBlitResolveSamplerBinding;
1472     writeInfos[2].descriptorCount = 1;
1473     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
1474     writeInfos[2].pImageInfo      = &samplerInfo;
1475 
1476     // If resolving color, there's one write info; index 0
1477     // If resolving depth, write info index 0 must be written
1478     // If resolving stencil, write info index 1 must also be written
1479     //
1480     // Note again that resolving color and depth/stencil are mutually exclusive here.
1481     uint32_t writeInfoOffset = blitDepth || blitColor ? 0 : 1;
1482     uint32_t writeInfoCount  = blitColor + blitDepth + blitStencil;
1483 
1484     vkUpdateDescriptorSets(contextVk->getDevice(), writeInfoCount, writeInfos + writeInfoOffset, 0,
1485                            nullptr);
1486     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfos[2], 0, nullptr);
1487 
1488     vk::ShaderLibrary &shaderLibrary                    = contextVk->getShaderLibrary();
1489     vk::RefCounted<vk::ShaderAndSerial> *vertexShader   = nullptr;
1490     vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
1491     ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
1492     ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
1493 
1494     ANGLE_TRY(setupProgram(contextVk, Function::BlitResolve, fragmentShader, vertexShader,
1495                            &mBlitResolvePrograms[flags], &pipelineDesc, descriptorSet,
1496                            &shaderParams, sizeof(shaderParams), commandBuffer));
1497     commandBuffer->draw(6, 0);
1498     descriptorPoolBinding.reset();
1499 
1500     return angle::Result::Continue;
1501 }
1502 
stencilBlitResolveNoShaderExport(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)1503 angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
1504                                                         FramebufferVk *framebuffer,
1505                                                         vk::ImageHelper *src,
1506                                                         const vk::ImageView *srcStencilView,
1507                                                         const BlitResolveParameters &params)
1508 {
1509     // When VK_EXT_shader_stencil_export is not available, stencil is blitted/resolved into a
1510     // temporary buffer which is then copied into the stencil aspect of the image.
1511 
1512     ANGLE_TRY(ensureBlitResolveStencilNoExportResourcesInitialized(contextVk));
1513 
1514     bool isResolve = src->getSamples() > 1;
1515 
1516     VkDescriptorSet descriptorSet;
1517     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1518     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BlitResolveStencilNoExport,
1519                                     &descriptorPoolBinding, &descriptorSet));
1520 
1521     // Create a temporary buffer to blit/resolve stencil into.
1522     vk::RendererScoped<vk::BufferHelper> blitBuffer(contextVk->getRenderer());
1523 
1524     uint32_t bufferRowLengthInUints = UnsignedCeilDivide(params.blitArea.width, sizeof(uint32_t));
1525     VkDeviceSize bufferSize = bufferRowLengthInUints * sizeof(uint32_t) * params.blitArea.height;
1526 
1527     VkBufferCreateInfo blitBufferInfo = {};
1528     blitBufferInfo.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1529     blitBufferInfo.flags              = 0;
1530     blitBufferInfo.size               = bufferSize;
1531     blitBufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1532     blitBufferInfo.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
1533     blitBufferInfo.queueFamilyIndexCount = 0;
1534     blitBufferInfo.pQueueFamilyIndices   = nullptr;
1535 
1536     ANGLE_TRY(
1537         blitBuffer.get().init(contextVk, blitBufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
1538     blitBuffer.get().retain(&contextVk->getResourceUseList());
1539 
1540     BlitResolveStencilNoExportShaderParams shaderParams;
1541     if (isResolve)
1542     {
1543         CalculateResolveOffset(params, shaderParams.offset.resolve);
1544     }
1545     else
1546     {
1547         CalculateBlitOffset(params, shaderParams.offset.blit);
1548     }
1549     shaderParams.stretch[0]      = params.stretch[0];
1550     shaderParams.stretch[1]      = params.stretch[1];
1551     shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
1552     shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
1553     shaderParams.srcLayer        = params.srcLayer;
1554     shaderParams.srcWidth        = params.srcExtents[0];
1555     shaderParams.destPitch       = bufferRowLengthInUints;
1556     shaderParams.blitArea[0]     = params.blitArea.x;
1557     shaderParams.blitArea[1]     = params.blitArea.y;
1558     shaderParams.blitArea[2]     = params.blitArea.width;
1559     shaderParams.blitArea[3]     = params.blitArea.height;
1560     shaderParams.flipX           = params.flipX;
1561     shaderParams.flipY           = params.flipY;
1562 
1563     // Linear sampling is only valid with color blitting.
1564     ASSERT(!params.linear);
1565 
1566     uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0;
1567     flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
1568 
1569     RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
1570     ASSERT(depthStencilRenderTarget != nullptr);
1571     vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImage();
1572 
1573     vk::CommandBuffer *commandBuffer;
1574     // Change source layout prior to computation.
1575     ANGLE_TRY(
1576         contextVk->onImageRead(src->getAspectFlags(), vk::ImageLayout::ComputeShaderReadOnly, src));
1577     ANGLE_TRY(contextVk->onImageWrite(depthStencilImage->getAspectFlags(),
1578                                       vk::ImageLayout::TransferDst, depthStencilImage));
1579     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1580 
1581     // Blit/resolve stencil into the buffer.
1582     VkDescriptorImageInfo imageInfo = {};
1583     imageInfo.imageView             = srcStencilView->getHandle();
1584     imageInfo.imageLayout           = src->getCurrentLayout();
1585 
1586     VkDescriptorBufferInfo bufferInfo = {};
1587     bufferInfo.buffer                 = blitBuffer.get().getBuffer().getHandle();
1588     bufferInfo.offset                 = 0;
1589     bufferInfo.range                  = VK_WHOLE_SIZE;
1590 
1591     VkDescriptorImageInfo samplerInfo = {};
1592     samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
1593 
1594     VkWriteDescriptorSet writeInfos[3] = {};
1595     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1596     writeInfos[0].dstSet               = descriptorSet;
1597     writeInfos[0].dstBinding           = kBlitResolveStencilNoExportDestBinding;
1598     writeInfos[0].descriptorCount      = 1;
1599     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1600     writeInfos[0].pBufferInfo          = &bufferInfo;
1601 
1602     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1603     writeInfos[1].dstSet          = descriptorSet;
1604     writeInfos[1].dstBinding      = kBlitResolveStencilNoExportSrcBinding;
1605     writeInfos[1].descriptorCount = 1;
1606     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1607     writeInfos[1].pImageInfo      = &imageInfo;
1608 
1609     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1610     writeInfos[2].dstSet          = descriptorSet;
1611     writeInfos[2].dstBinding      = kBlitResolveStencilNoExportSamplerBinding;
1612     writeInfos[2].descriptorCount = 1;
1613     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
1614     writeInfos[2].pImageInfo      = &samplerInfo;
1615 
1616     vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
1617 
1618     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1619     ANGLE_TRY(contextVk->getShaderLibrary().getBlitResolveStencilNoExport_comp(contextVk, flags,
1620                                                                                &shader));
1621 
1622     ANGLE_TRY(setupProgram(contextVk, Function::BlitResolveStencilNoExport, shader, nullptr,
1623                            &mBlitResolveStencilNoExportPrograms[flags], nullptr, descriptorSet,
1624                            &shaderParams, sizeof(shaderParams), commandBuffer));
1625     commandBuffer->dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
1626                             UnsignedCeilDivide(params.blitArea.height, 8), 1);
1627     descriptorPoolBinding.reset();
1628 
1629     // Add a barrier prior to copy.
1630     VkMemoryBarrier memoryBarrier = {};
1631     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
1632     memoryBarrier.srcAccessMask   = VK_ACCESS_SHADER_WRITE_BIT;
1633     memoryBarrier.dstAccessMask   = VK_ACCESS_TRANSFER_READ_BIT;
1634 
1635     // Use the all pipe stage to keep the state management simple.
1636     commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1637                                    VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memoryBarrier, 0, nullptr,
1638                                    0, nullptr);
1639 
1640     // Copy the resulting buffer into dest.
1641     VkBufferImageCopy region               = {};
1642     region.bufferOffset                    = 0;
1643     region.bufferRowLength                 = bufferRowLengthInUints * sizeof(uint32_t);
1644     region.bufferImageHeight               = params.blitArea.height;
1645     region.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_STENCIL_BIT;
1646     region.imageSubresource.mipLevel       = depthStencilRenderTarget->getLevelIndex();
1647     region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex();
1648     region.imageSubresource.layerCount     = 1;
1649     region.imageOffset.x                   = params.blitArea.x;
1650     region.imageOffset.y                   = params.blitArea.y;
1651     region.imageOffset.z                   = 0;
1652     region.imageExtent.width               = params.blitArea.width;
1653     region.imageExtent.height              = params.blitArea.height;
1654     region.imageExtent.depth               = 1;
1655 
1656     commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(),
1657                                      depthStencilImage->getImage(),
1658                                      depthStencilImage->getCurrentLayout(), 1, &region);
1659 
1660     return angle::Result::Continue;
1661 }
1662 
copyImage(ContextVk * contextVk,vk::ImageHelper * dest,const vk::ImageView * destView,vk::ImageHelper * src,const vk::ImageView * srcView,const CopyImageParameters & params)1663 angle::Result UtilsVk::copyImage(ContextVk *contextVk,
1664                                  vk::ImageHelper *dest,
1665                                  const vk::ImageView *destView,
1666                                  vk::ImageHelper *src,
1667                                  const vk::ImageView *srcView,
1668                                  const CopyImageParameters &params)
1669 {
1670     ANGLE_TRY(ensureImageCopyResourcesInitialized(contextVk));
1671 
1672     const vk::Format &srcFormat            = src->getFormat();
1673     const vk::Format &dstFormat            = dest->getFormat();
1674     const angle::Format &dstIntendedFormat = dstFormat.intendedFormat();
1675 
1676     ImageCopyShaderParams shaderParams;
1677     shaderParams.flipY            = params.srcFlipY || params.destFlipY;
1678     shaderParams.premultiplyAlpha = params.srcPremultiplyAlpha;
1679     shaderParams.unmultiplyAlpha  = params.srcUnmultiplyAlpha;
1680     shaderParams.destHasLuminance = dstIntendedFormat.luminanceBits > 0;
1681     shaderParams.destIsAlpha      = dstIntendedFormat.isLUMA() && dstIntendedFormat.alphaBits > 0;
1682     shaderParams.destDefaultChannelsMask = GetFormatDefaultChannelMask(dstFormat);
1683     shaderParams.srcMip                  = params.srcMip;
1684     shaderParams.srcLayer                = params.srcLayer;
1685     shaderParams.srcOffset[0]            = params.srcOffset[0];
1686     shaderParams.srcOffset[1]            = params.srcOffset[1];
1687     shaderParams.destOffset[0]           = params.destOffset[0];
1688     shaderParams.destOffset[1]           = params.destOffset[1];
1689 
1690     ASSERT(!(params.srcFlipY && params.destFlipY));
1691     if (params.srcFlipY)
1692     {
1693         // If viewport is flipped, the shader expects srcOffset[1] to have the
1694         // last row's index instead of the first's.
1695         shaderParams.srcOffset[1] = params.srcHeight - params.srcOffset[1] - 1;
1696     }
1697     else if (params.destFlipY)
1698     {
1699         // If image is flipped during copy, the shader uses the same code path as above,
1700         // with srcOffset being set to the last row's index instead of the first's.
1701         shaderParams.srcOffset[1] = params.srcOffset[1] + params.srcExtents[1] - 1;
1702     }
1703 
1704     uint32_t flags = GetImageCopyFlags(srcFormat, dstFormat);
1705     flags |= src->getLayerCount() > 1 ? ImageCopy_frag::kSrcIsArray : 0;
1706 
1707     VkDescriptorSet descriptorSet;
1708     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1709     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ImageCopy, &descriptorPoolBinding,
1710                                     &descriptorSet));
1711 
1712     vk::RenderPassDesc renderPassDesc;
1713     renderPassDesc.setSamples(dest->getSamples());
1714     renderPassDesc.packColorAttachment(0, dstFormat.intendedFormatID);
1715 
1716     // Multisampled copy is not yet supported.
1717     ASSERT(src->getSamples() == 1 && dest->getSamples() == 1);
1718 
1719     vk::GraphicsPipelineDesc pipelineDesc;
1720     pipelineDesc.initDefaults();
1721     pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
1722     pipelineDesc.setRenderPassDesc(renderPassDesc);
1723 
1724     gl::Rectangle renderArea;
1725     renderArea.x      = params.destOffset[0];
1726     renderArea.y      = params.destOffset[1];
1727     renderArea.width  = params.srcExtents[0];
1728     renderArea.height = params.srcExtents[1];
1729 
1730     VkViewport viewport;
1731     gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, dest->getExtents().height, &viewport);
1732     pipelineDesc.setViewport(viewport);
1733 
1734     VkRect2D scissor = gl_vk::GetRect(renderArea);
1735     pipelineDesc.setScissor(scissor);
1736 
1737     // Change source layout outside render pass
1738     ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
1739                                      vk::ImageLayout::FragmentShaderReadOnly, src));
1740     ANGLE_TRY(
1741         contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment, dest));
1742 
1743     vk::CommandBuffer *commandBuffer;
1744     ANGLE_TRY(
1745         startRenderPass(contextVk, dest, destView, renderPassDesc, renderArea, &commandBuffer));
1746 
1747     VkDescriptorImageInfo imageInfo = {};
1748     imageInfo.imageView             = srcView->getHandle();
1749     imageInfo.imageLayout           = src->getCurrentLayout();
1750 
1751     VkWriteDescriptorSet writeInfo = {};
1752     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1753     writeInfo.dstSet               = descriptorSet;
1754     writeInfo.dstBinding           = kImageCopySourceBinding;
1755     writeInfo.descriptorCount      = 1;
1756     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1757     writeInfo.pImageInfo           = &imageInfo;
1758 
1759     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1760 
1761     vk::ShaderLibrary &shaderLibrary                    = contextVk->getShaderLibrary();
1762     vk::RefCounted<vk::ShaderAndSerial> *vertexShader   = nullptr;
1763     vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
1764     ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
1765     ANGLE_TRY(shaderLibrary.getImageCopy_frag(contextVk, flags, &fragmentShader));
1766 
1767     ANGLE_TRY(setupProgram(contextVk, Function::ImageCopy, fragmentShader, vertexShader,
1768                            &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
1769                            sizeof(shaderParams), commandBuffer));
1770     commandBuffer->draw(6, 0);
1771     descriptorPoolBinding.reset();
1772 
1773     return angle::Result::Continue;
1774 }
1775 
cullOverlayWidgets(ContextVk * contextVk,vk::BufferHelper * enabledWidgetsBuffer,vk::ImageHelper * dest,const vk::ImageView * destView,const OverlayCullParameters & params)1776 angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk,
1777                                           vk::BufferHelper *enabledWidgetsBuffer,
1778                                           vk::ImageHelper *dest,
1779                                           const vk::ImageView *destView,
1780                                           const OverlayCullParameters &params)
1781 {
1782     ANGLE_TRY(ensureOverlayCullResourcesInitialized(contextVk));
1783 
1784     ASSERT(params.subgroupSize[0] == 8 &&
1785            (params.subgroupSize[1] == 8 || params.subgroupSize[1] == 4));
1786     uint32_t flags =
1787         params.subgroupSize[1] == 8 ? OverlayCull_comp::kIs8x8 : OverlayCull_comp::kIs8x4;
1788     if (params.supportsSubgroupBallot)
1789     {
1790         flags |= OverlayCull_comp::kSupportsBallot;
1791     }
1792     else if (params.supportsSubgroupBallot)
1793     {
1794         flags |= OverlayCull_comp::kSupportsArithmetic;
1795     }
1796     else
1797     {
1798         flags |= OverlayCull_comp::kSupportsNone;
1799     }
1800 
1801     VkDescriptorSet descriptorSet;
1802     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1803     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::OverlayCull, &descriptorPoolBinding,
1804                                     &descriptorSet));
1805 
1806     vk::CommandBuffer *commandBuffer;
1807     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, enabledWidgetsBuffer));
1808     ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
1809                                       vk::ImageLayout::ComputeShaderWrite, dest));
1810     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1811 
1812     VkDescriptorImageInfo imageInfo = {};
1813     imageInfo.imageView             = destView->getHandle();
1814     imageInfo.imageLayout           = dest->getCurrentLayout();
1815 
1816     VkDescriptorBufferInfo bufferInfo = {};
1817     bufferInfo.buffer                 = enabledWidgetsBuffer->getBuffer().getHandle();
1818     bufferInfo.offset                 = 0;
1819     bufferInfo.range                  = VK_WHOLE_SIZE;
1820 
1821     VkWriteDescriptorSet writeInfos[2] = {};
1822     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1823     writeInfos[0].dstSet               = descriptorSet;
1824     writeInfos[0].dstBinding           = kOverlayCullCulledWidgetsBinding;
1825     writeInfos[0].descriptorCount      = 1;
1826     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1827     writeInfos[0].pImageInfo           = &imageInfo;
1828 
1829     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1830     writeInfos[1].dstSet          = descriptorSet;
1831     writeInfos[1].dstBinding      = kOverlayCullWidgetCoordsBinding;
1832     writeInfos[1].descriptorCount = 1;
1833     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1834     writeInfos[1].pBufferInfo     = &bufferInfo;
1835 
1836     vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
1837 
1838     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1839     ANGLE_TRY(contextVk->getShaderLibrary().getOverlayCull_comp(contextVk, flags, &shader));
1840 
1841     ANGLE_TRY(setupProgram(contextVk, Function::OverlayCull, shader, nullptr,
1842                            &mOverlayCullPrograms[flags], nullptr, descriptorSet, nullptr, 0,
1843                            commandBuffer));
1844     commandBuffer->dispatch(dest->getExtents().width, dest->getExtents().height, 1);
1845     descriptorPoolBinding.reset();
1846 
1847     return angle::Result::Continue;
1848 }
1849 
drawOverlay(ContextVk * contextVk,vk::BufferHelper * textWidgetsBuffer,vk::BufferHelper * graphWidgetsBuffer,vk::ImageHelper * font,const vk::ImageView * fontView,vk::ImageHelper * culledWidgets,const vk::ImageView * culledWidgetsView,vk::ImageHelper * dest,const vk::ImageView * destView,const OverlayDrawParameters & params)1850 angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
1851                                    vk::BufferHelper *textWidgetsBuffer,
1852                                    vk::BufferHelper *graphWidgetsBuffer,
1853                                    vk::ImageHelper *font,
1854                                    const vk::ImageView *fontView,
1855                                    vk::ImageHelper *culledWidgets,
1856                                    const vk::ImageView *culledWidgetsView,
1857                                    vk::ImageHelper *dest,
1858                                    const vk::ImageView *destView,
1859                                    const OverlayDrawParameters &params)
1860 {
1861     ANGLE_TRY(ensureOverlayDrawResourcesInitialized(contextVk));
1862 
1863     OverlayDrawShaderParams shaderParams;
1864     shaderParams.outputSize[0] = dest->getExtents().width;
1865     shaderParams.outputSize[1] = dest->getExtents().height;
1866 
1867     ASSERT(params.subgroupSize[0] == 8 &&
1868            (params.subgroupSize[1] == 8 || params.subgroupSize[1] == 4));
1869     uint32_t flags =
1870         params.subgroupSize[1] == 8 ? OverlayDraw_comp::kIs8x8 : OverlayDraw_comp::kIs8x4;
1871 
1872     VkDescriptorSet descriptorSet;
1873     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1874     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::OverlayDraw, &descriptorPoolBinding,
1875                                     &descriptorSet));
1876 
1877     vk::CommandBuffer *commandBuffer;
1878     ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
1879                                       vk::ImageLayout::ComputeShaderWrite, dest));
1880     ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
1881                                      vk::ImageLayout::ComputeShaderReadOnly, culledWidgets));
1882     ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
1883                                      vk::ImageLayout::ComputeShaderReadOnly, font));
1884     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, textWidgetsBuffer));
1885     ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, graphWidgetsBuffer));
1886 
1887     ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1888 
1889     VkDescriptorImageInfo imageInfos[3] = {};
1890     imageInfos[0].imageView             = destView->getHandle();
1891     imageInfos[0].imageLayout           = dest->getCurrentLayout();
1892 
1893     imageInfos[1].imageView   = culledWidgetsView->getHandle();
1894     imageInfos[1].imageLayout = culledWidgets->getCurrentLayout();
1895 
1896     imageInfos[2].imageView   = fontView->getHandle();
1897     imageInfos[2].imageLayout = font->getCurrentLayout();
1898 
1899     VkDescriptorBufferInfo bufferInfos[2] = {};
1900     bufferInfos[0].buffer                 = textWidgetsBuffer->getBuffer().getHandle();
1901     bufferInfos[0].offset                 = 0;
1902     bufferInfos[0].range                  = VK_WHOLE_SIZE;
1903 
1904     bufferInfos[1].buffer = graphWidgetsBuffer->getBuffer().getHandle();
1905     bufferInfos[1].offset = 0;
1906     bufferInfos[1].range  = VK_WHOLE_SIZE;
1907 
1908     VkWriteDescriptorSet writeInfos[5] = {};
1909     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1910     writeInfos[0].dstSet               = descriptorSet;
1911     writeInfos[0].dstBinding           = kOverlayDrawOutputBinding;
1912     writeInfos[0].descriptorCount      = 1;
1913     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1914     writeInfos[0].pImageInfo           = &imageInfos[0];
1915 
1916     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1917     writeInfos[1].dstSet          = descriptorSet;
1918     writeInfos[1].dstBinding      = kOverlayDrawCulledWidgetsBinding;
1919     writeInfos[1].descriptorCount = 1;
1920     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1921     writeInfos[1].pImageInfo      = &imageInfos[1];
1922 
1923     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1924     writeInfos[2].dstSet          = descriptorSet;
1925     writeInfos[2].dstBinding      = kOverlayDrawFontBinding;
1926     writeInfos[2].descriptorCount = 1;
1927     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1928     writeInfos[2].pImageInfo      = &imageInfos[2];
1929 
1930     writeInfos[3].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1931     writeInfos[3].dstSet          = descriptorSet;
1932     writeInfos[3].dstBinding      = kOverlayDrawTextWidgetsBinding;
1933     writeInfos[3].descriptorCount = 1;
1934     writeInfos[3].descriptorType  = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1935     writeInfos[3].pBufferInfo     = &bufferInfos[0];
1936 
1937     writeInfos[4]             = writeInfos[3];
1938     writeInfos[4].dstBinding  = kOverlayDrawGraphWidgetsBinding;
1939     writeInfos[4].pBufferInfo = &bufferInfos[1];
1940 
1941     vkUpdateDescriptorSets(contextVk->getDevice(), 5, writeInfos, 0, nullptr);
1942 
1943     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1944     ANGLE_TRY(contextVk->getShaderLibrary().getOverlayDraw_comp(contextVk, flags, &shader));
1945 
1946     ANGLE_TRY(setupProgram(contextVk, Function::OverlayDraw, shader, nullptr,
1947                            &mOverlayDrawPrograms[flags], nullptr, descriptorSet, &shaderParams,
1948                            sizeof(shaderParams), commandBuffer));
1949 
1950     // Every pixel of culledWidgets corresponds to one workgroup, so we can use that as dispatch
1951     // size.
1952     commandBuffer->dispatch(culledWidgets->getExtents().width, culledWidgets->getExtents().height,
1953                             1);
1954     descriptorPoolBinding.reset();
1955 
1956     return angle::Result::Continue;
1957 }
1958 
allocateDescriptorSet(ContextVk * contextVk,Function function,vk::RefCountedDescriptorPoolBinding * bindingOut,VkDescriptorSet * descriptorSetOut)1959 angle::Result UtilsVk::allocateDescriptorSet(ContextVk *contextVk,
1960                                              Function function,
1961                                              vk::RefCountedDescriptorPoolBinding *bindingOut,
1962                                              VkDescriptorSet *descriptorSetOut)
1963 {
1964     ANGLE_TRY(mDescriptorPools[function].allocateSets(
1965         contextVk, mDescriptorSetLayouts[function][kSetIndex].get().ptr(), 1, bindingOut,
1966         descriptorSetOut));
1967     bindingOut->get().updateSerial(contextVk->getCurrentQueueSerial());
1968     return angle::Result::Continue;
1969 }
1970 
ClearFramebufferParameters()1971 UtilsVk::ClearFramebufferParameters::ClearFramebufferParameters()
1972     : clearColor(false),
1973       clearStencil(false),
1974       stencilMask(0),
1975       colorMaskFlags(0),
1976       colorAttachmentIndexGL(0),
1977       colorFormat(nullptr),
1978       colorClearValue{},
1979       stencilClearValue(0)
1980 {}
1981 
1982 }  // namespace rx
1983