• 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 "common/spirv/spirv_instruction_builder_autogen.h"
13 
14 #include "libANGLE/renderer/vulkan/ContextVk.h"
15 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
16 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
17 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
18 #include "libANGLE/renderer/vulkan/vk_renderer.h"
19 #include "libANGLE/renderer/vulkan/vk_utils.h"
20 
21 namespace rx
22 {
23 
24 namespace ConvertVertex_comp                = vk::InternalShader::ConvertVertex_comp;
25 namespace ImageClear_frag                   = vk::InternalShader::ImageClear_frag;
26 namespace ImageCopy_frag                    = vk::InternalShader::ImageCopy_frag;
27 namespace ImageCopyFloat_frag               = vk::InternalShader::ImageCopyFloat_frag;
28 namespace CopyImageToBuffer_comp            = vk::InternalShader::CopyImageToBuffer_comp;
29 namespace BlitResolve_frag                  = vk::InternalShader::BlitResolve_frag;
30 namespace Blit3DSrc_frag                    = vk::InternalShader::Blit3DSrc_frag;
31 namespace BlitResolveStencilNoExport_comp   = vk::InternalShader::BlitResolveStencilNoExport_comp;
32 namespace ExportStencil_frag                = vk::InternalShader::ExportStencil_frag;
33 namespace ConvertIndexIndirectLineLoop_comp = vk::InternalShader::ConvertIndexIndirectLineLoop_comp;
34 namespace GenerateMipmap_comp               = vk::InternalShader::GenerateMipmap_comp;
35 namespace EtcToBc_comp                      = vk::InternalShader::EtcToBc_comp;
36 
37 namespace spirv = angle::spirv;
38 
39 namespace
40 {
41 constexpr uint32_t kConvertIndexDestinationBinding = 0;
42 
43 constexpr uint32_t kConvertVertexDestinationBinding = 0;
44 constexpr uint32_t kConvertVertexSourceBinding      = 1;
45 
46 constexpr uint32_t kImageCopySourceBinding = 0;
47 
48 constexpr uint32_t kCopyImageToBufferSourceBinding      = 0;
49 constexpr uint32_t kCopyImageToBufferDestinationBinding = 1;
50 
51 constexpr uint32_t kBlitResolveColorOrDepthBinding = 0;
52 constexpr uint32_t kBlitResolveStencilBinding      = 1;
53 constexpr uint32_t kBlitResolveSamplerBinding      = 2;
54 
55 constexpr uint32_t kBlitResolveStencilNoExportDestBinding    = 0;
56 constexpr uint32_t kBlitResolveStencilNoExportSrcBinding     = 1;
57 constexpr uint32_t kBlitResolveStencilNoExportSamplerBinding = 2;
58 
59 constexpr uint32_t kExportStencilInputIndex = 0;
60 constexpr uint32_t kExportStencilBinding    = 0;
61 
62 constexpr uint32_t kOverlayDrawTextWidgetsBinding  = 0;
63 constexpr uint32_t kOverlayDrawGraphWidgetsBinding = 1;
64 constexpr uint32_t kOverlayDrawFontBinding         = 2;
65 
66 constexpr uint32_t kGenerateMipmapDestinationBinding = 0;
67 constexpr uint32_t kGenerateMipmapSourceBinding      = 1;
68 
69 constexpr uint32_t kGenerateFragmentShadingRateAttachmentBinding = 0;
70 
ValidateFloatOneAsUint()71 bool ValidateFloatOneAsUint()
72 {
73     union
74     {
75         uint32_t asUint;
76         float asFloat;
77     } one;
78     one.asUint = gl::Float32One;
79     return one.asFloat == 1.0f;
80 }
81 
GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters & params)82 uint32_t GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters &params)
83 {
84     bool srcIsSint      = params.srcFormat->isSint();
85     bool srcIsUint      = params.srcFormat->isUint();
86     bool srcIsSnorm     = params.srcFormat->isSnorm();
87     bool srcIsUnorm     = params.srcFormat->isUnorm();
88     bool srcIsFixed     = params.srcFormat->isFixed;
89     bool srcIsFloat     = params.srcFormat->isFloat();
90     bool srcIsHalfFloat = params.srcFormat->isVertexTypeHalfFloat();
91 
92     bool dstIsSint      = params.dstFormat->isSint();
93     bool dstIsUint      = params.dstFormat->isUint();
94     bool dstIsSnorm     = params.dstFormat->isSnorm();
95     bool dstIsUnorm     = params.dstFormat->isUnorm();
96     bool dstIsFloat     = params.dstFormat->isFloat();
97     bool dstIsHalfFloat = params.dstFormat->isVertexTypeHalfFloat();
98 
99     // Assert on the types to make sure the shader supports its.  These are based on
100     // ConvertVertex_comp::Conversion values.
101     ASSERT(!dstIsSint || srcIsSint);    // If destination is sint, src must be sint too
102     ASSERT(!dstIsUint || srcIsUint);    // If destination is uint, src must be uint too
103     ASSERT(!srcIsFixed || dstIsFloat);  // If source is fixed, dst must be float
104 
105     // One of each bool set must be true
106     ASSERT(srcIsSint || srcIsUint || srcIsSnorm || srcIsUnorm || srcIsFixed || srcIsFloat);
107     ASSERT(dstIsSint || dstIsUint || dstIsSnorm || dstIsUnorm || dstIsFloat || dstIsHalfFloat);
108 
109     // We currently don't have any big-endian devices in the list of supported platforms.  The
110     // shader is capable of supporting big-endian architectures, but the relevant flag (IsBigEndian)
111     // is not added to the build configuration file (to reduce binary size).  If necessary, add
112     // IsBigEndian to ConvertVertex.comp.json and select the appropriate flag based on the
113     // endian-ness test here.
114     ASSERT(IsLittleEndian());
115 
116     uint32_t flags = 0;
117 
118     if (srcIsHalfFloat && dstIsHalfFloat)
119     {
120         // Note that HalfFloat conversion uses the same shader as Uint.
121         flags = ConvertVertex_comp::kUintToUint;
122     }
123     else if ((srcIsSnorm && dstIsSnorm) || (srcIsUnorm && dstIsUnorm))
124     {
125         // Do snorm->snorm and unorm->unorm copies using the uint->uint shader.  Currently only
126         // supported for same-width formats, so it's only used when adding channels.
127         ASSERT(params.srcFormat->redBits == params.dstFormat->redBits);
128         flags = ConvertVertex_comp::kUintToUint;
129     }
130     else if (srcIsSint && dstIsSint)
131     {
132         flags = ConvertVertex_comp::kSintToSint;
133     }
134     else if (srcIsUint && dstIsUint)
135     {
136         flags = ConvertVertex_comp::kUintToUint;
137     }
138     else if (srcIsSint)
139     {
140         flags = ConvertVertex_comp::kSintToFloat;
141     }
142     else if (srcIsUint)
143     {
144         flags = ConvertVertex_comp::kUintToFloat;
145     }
146     else if (srcIsSnorm)
147     {
148         flags = ConvertVertex_comp::kSnormToFloat;
149     }
150     else if (srcIsUnorm)
151     {
152         flags = ConvertVertex_comp::kUnormToFloat;
153     }
154     else if (srcIsFixed)
155     {
156         flags = ConvertVertex_comp::kFixedToFloat;
157     }
158     else if (srcIsFloat)
159     {
160         flags = ConvertVertex_comp::kFloatToFloat;
161     }
162     else
163     {
164         UNREACHABLE();
165     }
166 
167     return flags;
168 }
169 
GetImageClearFlags(const angle::Format & format,uint32_t attachmentIndex,bool clearDepth)170 uint32_t GetImageClearFlags(const angle::Format &format, uint32_t attachmentIndex, bool clearDepth)
171 {
172     constexpr uint32_t kAttachmentFlagStep =
173         ImageClear_frag::kAttachment1 - ImageClear_frag::kAttachment0;
174 
175     static_assert(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS == 8,
176                   "ImageClear shader assumes maximum 8 draw buffers");
177     static_assert(
178         ImageClear_frag::kAttachment0 + 7 * kAttachmentFlagStep == ImageClear_frag::kAttachment7,
179         "ImageClear AttachmentN flag calculation needs correction");
180 
181     uint32_t flags = ImageClear_frag::kAttachment0 + attachmentIndex * kAttachmentFlagStep;
182 
183     if (format.isSint())
184     {
185         flags |= ImageClear_frag::kIsSint;
186     }
187     else if (format.isUint())
188     {
189         flags |= ImageClear_frag::kIsUint;
190     }
191     else
192     {
193         flags |= ImageClear_frag::kIsFloat;
194     }
195 
196     if (clearDepth)
197     {
198         flags |= ImageClear_frag::kClearDepth;
199     }
200 
201     return flags;
202 }
203 
GetFormatFlags(const angle::Format & format,uint32_t intFlag,uint32_t uintFlag,uint32_t floatFlag)204 uint32_t GetFormatFlags(const angle::Format &format,
205                         uint32_t intFlag,
206                         uint32_t uintFlag,
207                         uint32_t floatFlag)
208 {
209     if (format.isSint())
210     {
211         return intFlag;
212     }
213     if (format.isUint())
214     {
215         return uintFlag;
216     }
217     return floatFlag;
218 }
219 
GetImageCopyFlags(const angle::Format & srcIntendedFormat,const angle::Format & dstIntendedFormat)220 uint32_t GetImageCopyFlags(const angle::Format &srcIntendedFormat,
221                            const angle::Format &dstIntendedFormat)
222 {
223     uint32_t flags = 0;
224 
225     flags |= GetFormatFlags(srcIntendedFormat, ImageCopy_frag::kSrcIsSint,
226                             ImageCopy_frag::kSrcIsUint, ImageCopy_frag::kSrcIsFloat);
227     flags |= GetFormatFlags(dstIntendedFormat, ImageCopy_frag::kDstIsSint,
228                             ImageCopy_frag::kDstIsUint, ImageCopy_frag::kDstIsFloat);
229 
230     return flags;
231 }
232 
GetCopyImageToBufferFlags(const angle::Format & srcFormat)233 uint32_t GetCopyImageToBufferFlags(const angle::Format &srcFormat)
234 {
235     ASSERT(!srcFormat.isSint() && !srcFormat.isUint());
236     return CopyImageToBuffer_comp::kSrcIsFloat;
237 }
238 
GetBlitResolveFlags(bool blitColor,bool blitDepth,bool blitStencil,const angle::Format & intendedFormat)239 uint32_t GetBlitResolveFlags(bool blitColor,
240                              bool blitDepth,
241                              bool blitStencil,
242                              const angle::Format &intendedFormat)
243 {
244     if (blitColor)
245     {
246         return GetFormatFlags(intendedFormat, BlitResolve_frag::kBlitColorInt,
247                               BlitResolve_frag::kBlitColorUint, BlitResolve_frag::kBlitColorFloat);
248     }
249 
250     if (blitDepth)
251     {
252         if (blitStencil)
253         {
254             return BlitResolve_frag::kBlitDepthStencil;
255         }
256         else
257         {
258             return BlitResolve_frag::kBlitDepth;
259         }
260     }
261     else
262     {
263         return BlitResolve_frag::kBlitStencil;
264     }
265 }
266 
GetConvertIndexIndirectLineLoopFlag(uint32_t indicesBitsWidth)267 uint32_t GetConvertIndexIndirectLineLoopFlag(uint32_t indicesBitsWidth)
268 {
269     switch (indicesBitsWidth)
270     {
271         case 8:
272             return ConvertIndexIndirectLineLoop_comp::kIs8Bits;
273         case 16:
274             return ConvertIndexIndirectLineLoop_comp::kIs16Bits;
275         case 32:
276             return ConvertIndexIndirectLineLoop_comp::kIs32Bits;
277         default:
278             UNREACHABLE();
279             return 0;
280     }
281 }
282 
GetGenerateMipmapFlags(ContextVk * contextVk,const angle::Format & actualFormat)283 uint32_t GetGenerateMipmapFlags(ContextVk *contextVk, const angle::Format &actualFormat)
284 {
285     uint32_t flags = 0;
286 
287     // Note: If bits-per-component is 8 or 16 and float16 is supported in the shader, use that for
288     // faster math.
289     const bool hasShaderFloat16 = contextVk->getFeatures().supportsShaderFloat16.enabled;
290 
291     if (actualFormat.redBits <= 8)
292     {
293         flags = hasShaderFloat16 ? GenerateMipmap_comp::kIsRGBA8_UseHalf
294                                  : GenerateMipmap_comp::kIsRGBA8;
295     }
296     else if (actualFormat.redBits <= 16)
297     {
298         flags = hasShaderFloat16 ? GenerateMipmap_comp::kIsRGBA16_UseHalf
299                                  : GenerateMipmap_comp::kIsRGBA16;
300     }
301     else
302     {
303         flags = GenerateMipmap_comp::kIsRGBA32F;
304     }
305 
306     flags |= UtilsVk::GetGenerateMipmapMaxLevels(contextVk) == UtilsVk::kGenerateMipmapMaxLevels
307                  ? GenerateMipmap_comp::kDestSize6
308                  : GenerateMipmap_comp::kDestSize4;
309 
310     return flags;
311 }
312 
313 enum UnresolveColorAttachmentType
314 {
315     kUnresolveTypeUnused = 0,
316     kUnresolveTypeFloat  = 1,
317     kUnresolveTypeSint   = 2,
318     kUnresolveTypeUint   = 3,
319 };
320 
GetUnresolveFlags(uint32_t colorAttachmentCount,const gl::DrawBuffersArray<vk::ImageHelper * > & colorSrc,bool unresolveDepth,bool unresolveStencil,gl::DrawBuffersArray<UnresolveColorAttachmentType> * attachmentTypesOut)321 uint32_t GetUnresolveFlags(uint32_t colorAttachmentCount,
322                            const gl::DrawBuffersArray<vk::ImageHelper *> &colorSrc,
323                            bool unresolveDepth,
324                            bool unresolveStencil,
325                            gl::DrawBuffersArray<UnresolveColorAttachmentType> *attachmentTypesOut)
326 {
327     uint32_t flags = 0;
328 
329     for (uint32_t attachmentIndex = 0; attachmentIndex < colorAttachmentCount; ++attachmentIndex)
330     {
331         const angle::Format &format = colorSrc[attachmentIndex]->getIntendedFormat();
332 
333         UnresolveColorAttachmentType type = kUnresolveTypeFloat;
334         if (format.isSint())
335         {
336             type = kUnresolveTypeSint;
337         }
338         else if (format.isUint())
339         {
340             type = kUnresolveTypeUint;
341         }
342 
343         (*attachmentTypesOut)[attachmentIndex] = type;
344 
345         // |flags| is comprised of |colorAttachmentCount| values from
346         // |UnresolveColorAttachmentType|, each taking up 2 bits.
347         flags |= type << (2 * attachmentIndex);
348     }
349 
350     // Additionally, two bits are used for depth and stencil unresolve.
351     constexpr uint32_t kDepthUnresolveFlagBit   = 2 * gl::IMPLEMENTATION_MAX_DRAW_BUFFERS;
352     constexpr uint32_t kStencilUnresolveFlagBit = kDepthUnresolveFlagBit + 1;
353     if (unresolveDepth)
354     {
355         flags |= 1 << kDepthUnresolveFlagBit;
356     }
357 
358     if (unresolveStencil)
359     {
360         flags |= 1 << kStencilUnresolveFlagBit;
361     }
362 
363     return flags;
364 }
365 
GetFormatDefaultChannelMask(const angle::Format & intendedImageFormat,const angle::Format & actualImageFormat)366 uint32_t GetFormatDefaultChannelMask(const angle::Format &intendedImageFormat,
367                                      const angle::Format &actualImageFormat)
368 {
369     uint32_t mask = 0;
370 
371     // Red can never be introduced due to format emulation (except for luma which is handled
372     // especially)
373     ASSERT(((intendedImageFormat.redBits > 0) == (actualImageFormat.redBits > 0)) ||
374            intendedImageFormat.isLUMA());
375     mask |= intendedImageFormat.greenBits == 0 && actualImageFormat.greenBits > 0 ? 2 : 0;
376     mask |= intendedImageFormat.blueBits == 0 && actualImageFormat.blueBits > 0 ? 4 : 0;
377     mask |= intendedImageFormat.alphaBits == 0 && actualImageFormat.alphaBits > 0 ? 8 : 0;
378 
379     return mask;
380 }
381 
382 // Calculate the transformation offset for blit/resolve.  See BlitResolve.frag for details on how
383 // these values are derived.
CalculateBlitOffset(const UtilsVk::BlitResolveParameters & params,float offset[2])384 void CalculateBlitOffset(const UtilsVk::BlitResolveParameters &params, float offset[2])
385 {
386     int srcOffsetFactorX = params.flipX ? -1 : 1;
387     int srcOffsetFactorY = params.flipY ? -1 : 1;
388 
389     offset[0] = params.dstOffset[0] * params.stretch[0] - params.srcOffset[0] * srcOffsetFactorX;
390     offset[1] = params.dstOffset[1] * params.stretch[1] - params.srcOffset[1] * srcOffsetFactorY;
391 }
392 
CalculateResolveOffset(const UtilsVk::BlitResolveParameters & params,int32_t offset[2])393 void CalculateResolveOffset(const UtilsVk::BlitResolveParameters &params, int32_t offset[2])
394 {
395     int srcOffsetFactorX = params.flipX ? -1 : 1;
396     int srcOffsetFactorY = params.flipY ? -1 : 1;
397 
398     // There's no stretching in resolve.
399     offset[0] = params.dstOffset[0] - params.srcOffset[0] * srcOffsetFactorX;
400     offset[1] = params.dstOffset[1] - params.srcOffset[1] * srcOffsetFactorY;
401 }
402 
SetDepthStateForWrite(vk::Renderer * renderer,vk::GraphicsPipelineDesc * desc)403 void SetDepthStateForWrite(vk::Renderer *renderer, vk::GraphicsPipelineDesc *desc)
404 {
405     if (!renderer->getFeatures().useDepthTestEnableDynamicState.enabled)
406     {
407         desc->setDepthTestEnabled(VK_TRUE);
408     }
409     if (!renderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
410     {
411         desc->setDepthWriteEnabled(VK_TRUE);
412     }
413     if (!renderer->getFeatures().useDepthCompareOpDynamicState.enabled)
414     {
415         desc->setDepthFunc(VK_COMPARE_OP_ALWAYS);
416     }
417 }
418 
SetDepthStateForUnused(vk::Renderer * renderer,vk::GraphicsPipelineDesc * desc)419 void SetDepthStateForUnused(vk::Renderer *renderer, vk::GraphicsPipelineDesc *desc)
420 {
421     if (!renderer->getFeatures().useDepthTestEnableDynamicState.enabled)
422     {
423         desc->setDepthTestEnabled(VK_FALSE);
424     }
425     if (!renderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
426     {
427         desc->setDepthWriteEnabled(VK_FALSE);
428     }
429 }
430 
SetDepthDynamicStateForWrite(vk::Renderer * renderer,vk::RenderPassCommandBuffer * commandBuffer)431 void SetDepthDynamicStateForWrite(vk::Renderer *renderer,
432                                   vk::RenderPassCommandBuffer *commandBuffer)
433 {
434     if (renderer->getFeatures().useDepthTestEnableDynamicState.enabled)
435     {
436         commandBuffer->setDepthTestEnable(VK_TRUE);
437     }
438     if (renderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
439     {
440         commandBuffer->setDepthWriteEnable(VK_TRUE);
441     }
442     if (renderer->getFeatures().useDepthCompareOpDynamicState.enabled)
443     {
444         commandBuffer->setDepthCompareOp(VK_COMPARE_OP_ALWAYS);
445     }
446 }
447 
SetDepthDynamicStateForUnused(vk::Renderer * renderer,vk::RenderPassCommandBuffer * commandBuffer)448 void SetDepthDynamicStateForUnused(vk::Renderer *renderer,
449                                    vk::RenderPassCommandBuffer *commandBuffer)
450 {
451     if (renderer->getFeatures().useDepthTestEnableDynamicState.enabled)
452     {
453         commandBuffer->setDepthTestEnable(VK_FALSE);
454     }
455     if (renderer->getFeatures().useDepthWriteEnableDynamicState.enabled)
456     {
457         commandBuffer->setDepthWriteEnable(VK_FALSE);
458     }
459     if (renderer->getFeatures().useDepthCompareOpDynamicState.enabled)
460     {
461         commandBuffer->setDepthCompareOp(VK_COMPARE_OP_ALWAYS);
462     }
463 }
464 
465 // Sets the appropriate settings in the pipeline for either the shader to output stencil, regardless
466 // of whether its done through the reference value or the shader stencil export extension.
SetStencilStateForWrite(vk::Renderer * renderer,vk::GraphicsPipelineDesc * desc)467 void SetStencilStateForWrite(vk::Renderer *renderer, vk::GraphicsPipelineDesc *desc)
468 {
469     if (!renderer->getFeatures().useStencilTestEnableDynamicState.enabled)
470     {
471         desc->setStencilTestEnabled(true);
472     }
473     if (!renderer->getFeatures().useStencilOpDynamicState.enabled)
474     {
475         desc->setStencilFrontFuncs(VK_COMPARE_OP_ALWAYS);
476         desc->setStencilBackFuncs(VK_COMPARE_OP_ALWAYS);
477         desc->setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
478                                  VK_STENCIL_OP_REPLACE);
479         desc->setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
480                                 VK_STENCIL_OP_REPLACE);
481     }
482 }
483 
SetStencilDynamicStateForWrite(vk::Renderer * renderer,vk::RenderPassCommandBuffer * commandBuffer)484 void SetStencilDynamicStateForWrite(vk::Renderer *renderer,
485                                     vk::RenderPassCommandBuffer *commandBuffer)
486 {
487     if (renderer->getFeatures().useStencilTestEnableDynamicState.enabled)
488     {
489         commandBuffer->setStencilTestEnable(true);
490     }
491     if (renderer->getFeatures().useStencilOpDynamicState.enabled)
492     {
493         commandBuffer->setStencilOp(VK_STENCIL_FACE_FRONT_BIT, VK_STENCIL_OP_REPLACE,
494                                     VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
495                                     VK_COMPARE_OP_ALWAYS);
496         commandBuffer->setStencilOp(VK_STENCIL_FACE_BACK_BIT, VK_STENCIL_OP_REPLACE,
497                                     VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
498                                     VK_COMPARE_OP_ALWAYS);
499     }
500 }
501 
SetStencilDynamicStateForUnused(vk::Renderer * renderer,vk::RenderPassCommandBuffer * commandBuffer)502 void SetStencilDynamicStateForUnused(vk::Renderer *renderer,
503                                      vk::RenderPassCommandBuffer *commandBuffer)
504 {
505     if (renderer->getFeatures().useStencilTestEnableDynamicState.enabled)
506     {
507         commandBuffer->setStencilTestEnable(false);
508     }
509     if (renderer->getFeatures().useStencilOpDynamicState.enabled)
510     {
511         commandBuffer->setStencilOp(VK_STENCIL_FACE_FRONT_BIT, VK_STENCIL_OP_REPLACE,
512                                     VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
513                                     VK_COMPARE_OP_ALWAYS);
514         commandBuffer->setStencilOp(VK_STENCIL_FACE_BACK_BIT, VK_STENCIL_OP_REPLACE,
515                                     VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
516                                     VK_COMPARE_OP_ALWAYS);
517     }
518     commandBuffer->setStencilCompareMask(0x00, 0x00);
519     commandBuffer->setStencilWriteMask(0x00, 0x00);
520     commandBuffer->setStencilReference(0x00, 0x00);
521 }
522 
HandlePrimitiveRestart(ContextVk * contextVk,gl::DrawElementsType glIndexType,GLsizei indexCount,const uint8_t * srcPtr,uint8_t * outPtr)523 void HandlePrimitiveRestart(ContextVk *contextVk,
524                             gl::DrawElementsType glIndexType,
525                             GLsizei indexCount,
526                             const uint8_t *srcPtr,
527                             uint8_t *outPtr)
528 {
529     switch (glIndexType)
530     {
531         case gl::DrawElementsType::UnsignedByte:
532             if (contextVk->getFeatures().supportsIndexTypeUint8.enabled)
533             {
534                 CopyLineLoopIndicesWithRestart<uint8_t, uint8_t>(indexCount, srcPtr, outPtr);
535             }
536             else
537             {
538                 CopyLineLoopIndicesWithRestart<uint8_t, uint16_t>(indexCount, srcPtr, outPtr);
539             }
540             break;
541         case gl::DrawElementsType::UnsignedShort:
542             CopyLineLoopIndicesWithRestart<uint16_t, uint16_t>(indexCount, srcPtr, outPtr);
543             break;
544         case gl::DrawElementsType::UnsignedInt:
545             CopyLineLoopIndicesWithRestart<uint32_t, uint32_t>(indexCount, srcPtr, outPtr);
546             break;
547         default:
548             UNREACHABLE();
549     }
550 }
551 
552 namespace unresolve
553 {
554 // The unresolve shader looks like the following, based on the number and types of unresolve
555 // attachments.  Note that stencil is placed first, to align with the ExportStencil shader, and
556 // simplifying descriptor set creation.
557 //
558 //     #version 450 core
559 //     #extension GL_ARB_shader_stencil_export : require
560 //
561 //     layout(location = 0) out vec4 colorOut0;
562 //     layout(location = 1) out ivec4 colorOut1;
563 //     layout(location = 2) out uvec4 colorOut2;
564 //     layout(input_attachment_index = 0, set = 0, binding = 0) uniform usubpassInput stencilIn;
565 //     layout(input_attachment_index = 0, set = 0, binding = 1) uniform subpassInput depthIn;
566 //     layout(input_attachment_index = 1, set = 0, binding = 2) uniform subpassInput colorIn0;
567 //     layout(input_attachment_index = 2, set = 0, binding = 3) uniform isubpassInput colorIn1;
568 //     layout(input_attachment_index = 3, set = 0, binding = 4) uniform usubpassInput colorIn2;
569 //
570 //     void main()
571 //     {
572 //         colorOut0 = subpassLoad(colorIn0);
573 //         colorOut1 = subpassLoad(colorIn1);
574 //         colorOut2 = subpassLoad(colorIn2);
575 //         gl_FragDepth = subpassLoad(depthIn).x;
576 //         gl_FragStencilRefARB = int(subpassLoad(stencilIn).x);
577 //     }
578 //
579 // This shader compiles to the following SPIR-V:
580 //
581 //           OpCapability Shader                              \
582 //           OpCapability InputAttachment                      \
583 //           OpCapability StencilExportEXT                      \   Preamble.  Mostly fixed, except
584 //           OpExtension "SPV_EXT_shader_stencil_export"         \  OpEntryPoint should enumerate
585 //      %1 = OpExtInstImport "GLSL.std.450"                       \ out variables, stencil export
586 //           OpMemoryModel Logical GLSL450                        / is conditional to stencil
587 //           OpEntryPoint Fragment %4 "main" %26 %27 %28 %29 %30 /  unresolve, and depth replacing
588 //           OpExecutionMode %4 OriginUpperLeft                 /   conditional to depth unresolve.
589 //           OpExecutionMode %4 DepthReplacing                 /
590 //           OpSource GLSL 450                                /
591 //
592 //           OpName %4 "main"              \
593 //           OpName %26 "colorOut0"         \
594 //           OpName %27 "colorOut1"          \
595 //           OpName %28 "colorOut2"           \
596 //           OpName %29 "gl_FragDepth"         \ Debug information.  Not generated here.
597 //           OpName %30 "gl_FragStencilRefARB" /
598 //           OpName %31 "colorIn0"            /
599 //           OpName %32 "colorIn1"           /
600 //           OpName %33 "colorIn2"          /
601 //           OpName %34 "depthIn"          /
602 //           OpName %35 "stencilIn"       /
603 //
604 //           OpDecorate %26 Location 0      \
605 //           OpDecorate %27 Location 1       \ Location decoration of out variables.
606 //           OpDecorate %28 Location 2       /
607 //
608 //           OpDecorate %29 BuiltIn FragDepth          \ Builtin outputs, conditional to depth
609 //           OpDecorate %30 BuiltIn FragStencilRefEXT  / and stencil unresolve.
610 //
611 //           OpDecorate %31 DescriptorSet 0        \
612 //           OpDecorate %31 Binding 2               \
613 //           OpDecorate %31 InputAttachmentIndex 1   \
614 //           OpDecorate %32 DescriptorSet 0           \
615 //           OpDecorate %32 Binding 3                  \
616 //           OpDecorate %32 InputAttachmentIndex 2      \
617 //           OpDecorate %33 DescriptorSet 0              \  set, binding and input_attachment
618 //           OpDecorate %33 Binding 4                     \ decorations of the subpassInput
619 //           OpDecorate %33 InputAttachmentIndex 3        / variables.
620 //           OpDecorate %34 DescriptorSet 0              /
621 //           OpDecorate %34 Binding 1                   /
622 //           OpDecorate %34 InputAttachmentIndex 0     /
623 //           OpDecorate %35 DescriptorSet 0           /
624 //           OpDecorate %35 Binding 0                /
625 //           OpDecorate %35 InputAttachmentIndex 0  /
626 //
627 //      %2 = OpTypeVoid         \ Type of main().  Fixed.
628 //      %3 = OpTypeFunction %2  /
629 //
630 //      %6 = OpTypeFloat 32                             \
631 //      %7 = OpTypeVector %6 4                           \
632 //      %8 = OpTypePointer Output %7                      \ Type declaration for "out vec4"
633 //      %9 = OpTypeImage %6 SubpassData 0 0 0 2 Unknown   / and "subpassInput".  Fixed.
634 //     %10 = OpTypePointer UniformConstant %9            /
635 //
636 //     %11 = OpTypeInt 32 1                              \
637 //     %12 = OpTypeVector %11 4                           \
638 //     %13 = OpTypePointer Output %12                      \ Type declaration for "out ivec4"
639 //     %14 = OpTypeImage %11 SubpassData 0 0 0 2 Unknown   / and "isubpassInput".  Fixed.
640 //     %15 = OpTypePointer UniformConstant %14            /
641 //
642 //     %16 = OpTypeInt 32 0                              \
643 //     %17 = OpTypeVector %16 4                           \
644 //     %18 = OpTypePointer Output %17                      \ Type declaration for "out uvec4"
645 //     %19 = OpTypeImage %16 SubpassData 0 0 0 2 Unknown   / and "usubpassInput".  Fixed.
646 //     %20 = OpTypePointer UniformConstant %19            /
647 //
648 //     %21 = OpTypePointer Output %6         \ Type declaraions for depth and stencil. Fixed.
649 //     %22 = OpTypePointer Output %11        /
650 //
651 //     %23 = OpConstant %11 0                \
652 //     %24 = OpTypeVector %11 2               \ ivec2(0) for OpImageRead.  subpassLoad
653 //     %25 = OpConstantComposite %22 %21 %21  / doesn't require coordinates.  Fixed.
654 //
655 //     %26 = OpVariable %8 Output            \
656 //     %27 = OpVariable %13 Output            \
657 //     %28 = OpVariable %18 Output             \
658 //     %29 = OpVariable %21 Output              \
659 //     %30 = OpVariable %22 Output               \ Actual "out" and "*subpassInput"
660 //     %31 = OpVariable %10 UniformConstant      / variable declarations.
661 //     %32 = OpVariable %15 UniformConstant     /
662 //     %33 = OpVariable %20 UniformConstant    /
663 //     %34 = OpVariable %10 UniformConstant   /
664 //     %35 = OpVariable %20 UniformConstant  /
665 //
666 //      %4 = OpFunction %2 None %3   \ Top of main().  Fixed.
667 //      %5 = OpLabel                 /
668 //
669 //     %36 = OpLoad %9 %31           \
670 //     %37 = OpImageRead %7 %36 %23   \ colorOut0 = subpassLoad(colorIn0);
671 //           OpStore %26 %37          /
672 //
673 //     %38 = OpLoad %14 %32          \
674 //     %39 = OpImageRead %12 %38 %23  \ colorOut1 = subpassLoad(colorIn1);
675 //           OpStore %27 %39          /
676 //
677 //     %40 = OpLoad %19 %33          \
678 //     %41 = OpImageRead %17 %40 %23  \ colorOut2 = subpassLoad(colorIn2);
679 //           OpStore %28 %41          /
680 //
681 //     %42 = OpLoad %9 %34              \
682 //     %43 = OpImageRead %7 %42 %23      \ gl_FragDepth = subpassLoad(depthIn).x;
683 //     %44 = OpCompositeExtract %6 %43 0 /
684 //           OpStore %29 %44            /
685 //
686 //     %45 = OpLoad %19 %35              \
687 //     %46 = OpImageRead %17 %45 %23      \
688 //     %47 = OpCompositeExtract %16 %46 0  \ gl_FragStencilRefARB = int(subpassLoad(stencilIn).x);
689 //     %48 = OpBitcast %11 %47             /
690 //           OpStore %30 %48              /
691 //
692 //           OpReturn           \ Bottom of main().  Fixed.
693 //           OpFunctionEnd      /
694 //
695 // What makes the generation of this shader manageable is that the majority of it is constant
696 // between the different variations of the shader.  The rest are repeating patterns with different
697 // ids or indices.
698 
699 enum
700 {
701     // main() ids
702     kIdExtInstImport = 1,
703     kIdVoid,
704     kIdMainType,
705     kIdMain,
706     kIdMainLabel,
707 
708     // Types for "out vec4" and "subpassInput"
709     kIdFloatType,
710     kIdFloat4Type,
711     kIdFloat4OutType,
712     kIdFloatSubpassImageType,
713     kIdFloatSubpassInputType,
714 
715     // Types for "out ivec4" and "isubpassInput"
716     kIdSIntType,
717     kIdSInt4Type,
718     kIdSInt4OutType,
719     kIdSIntSubpassImageType,
720     kIdSIntSubpassInputType,
721 
722     // Types for "out uvec4" and "usubpassInput"
723     kIdUIntType,
724     kIdUInt4Type,
725     kIdUInt4OutType,
726     kIdUIntSubpassImageType,
727     kIdUIntSubpassInputType,
728 
729     // Types for gl_FragDepth && gl_FragStencilRefARB
730     kIdFloatOutType,
731     kIdSIntOutType,
732 
733     // ivec2(0) constant
734     kIdSIntZero,
735     kIdSInt2Type,
736     kIdSInt2Zero,
737 
738     // Output variable ids
739     kIdColor0Out,
740     kIdDepthOut = kIdColor0Out + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
741     kIdStencilOut,
742 
743     // Input variable ids
744     kIdColor0In,
745     kIdDepthIn = kIdColor0In + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
746     kIdStencilIn,
747 
748     // Ids for temp variables
749     kIdColor0Load,
750     // 2 temp ids per color unresolve
751     kIdDepthLoad = kIdColor0Load + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS * 2,
752     // 3 temp ids for depth unresolve
753     kIdStencilLoad = kIdDepthLoad + 3,
754     // Total number of ids used
755     // 4 temp ids for stencil unresolve
756     kIdCount = kIdStencilLoad + 4,
757 };
758 
InsertPreamble(uint32_t colorAttachmentCount,bool unresolveDepth,bool unresolveStencil,angle::spirv::Blob * blobOut)759 void InsertPreamble(uint32_t colorAttachmentCount,
760                     bool unresolveDepth,
761                     bool unresolveStencil,
762                     angle::spirv::Blob *blobOut)
763 {
764     spirv::WriteCapability(blobOut, spv::CapabilityShader);
765     spirv::WriteCapability(blobOut, spv::CapabilityInputAttachment);
766     if (unresolveStencil)
767     {
768         spirv::WriteCapability(blobOut, spv::CapabilityStencilExportEXT);
769         spirv::WriteExtension(blobOut, "SPV_EXT_shader_stencil_export");
770     }
771     // OpExtInstImport is actually not needed by this shader.  We don't use any instructions from
772     // GLSL.std.450.
773     spirv::WriteMemoryModel(blobOut, spv::AddressingModelLogical, spv::MemoryModelGLSL450);
774 
775     // Create the list of entry point ids, including only the out variables.
776     spirv::IdRefList entryPointIds;
777     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; ++colorIndex)
778     {
779         entryPointIds.push_back(spirv::IdRef(kIdColor0Out + colorIndex));
780     }
781     if (unresolveDepth)
782     {
783         entryPointIds.push_back(spirv::IdRef(kIdDepthOut));
784     }
785     if (unresolveStencil)
786     {
787         entryPointIds.push_back(spirv::IdRef(kIdStencilOut));
788     }
789     spirv::WriteEntryPoint(blobOut, spv::ExecutionModelFragment, spirv::IdRef(kIdMain), "main",
790                            entryPointIds);
791 
792     spirv::WriteExecutionMode(blobOut, spirv::IdRef(kIdMain), spv::ExecutionModeOriginUpperLeft,
793                               {});
794     if (unresolveDepth)
795     {
796         spirv::WriteExecutionMode(blobOut, spirv::IdRef(kIdMain), spv::ExecutionModeDepthReplacing,
797                                   {});
798     }
799     spirv::WriteSource(blobOut, spv::SourceLanguageGLSL, spirv::LiteralInteger(450), nullptr,
800                        nullptr);
801 }
802 
InsertInputDecorations(spirv::IdRef id,uint32_t attachmentIndex,uint32_t binding,angle::spirv::Blob * blobOut)803 void InsertInputDecorations(spirv::IdRef id,
804                             uint32_t attachmentIndex,
805                             uint32_t binding,
806                             angle::spirv::Blob *blobOut)
807 {
808     spirv::WriteDecorate(blobOut, id, spv::DecorationDescriptorSet,
809                          {spirv::LiteralInteger(ToUnderlying(DescriptorSetIndex::Internal))});
810     spirv::WriteDecorate(blobOut, id, spv::DecorationBinding, {spirv::LiteralInteger(binding)});
811     spirv::WriteDecorate(blobOut, id, spv::DecorationInputAttachmentIndex,
812                          {spirv::LiteralInteger(attachmentIndex)});
813 }
814 
InsertColorDecorations(uint32_t colorIndex,uint32_t colorInputIndexStart,uint32_t colorBindingIndexStart,angle::spirv::Blob * blobOut)815 void InsertColorDecorations(uint32_t colorIndex,
816                             uint32_t colorInputIndexStart,
817                             uint32_t colorBindingIndexStart,
818                             angle::spirv::Blob *blobOut)
819 {
820     // Decorate the output color attachment with Location
821     spirv::WriteDecorate(blobOut, spirv::IdRef(kIdColor0Out + colorIndex), spv::DecorationLocation,
822                          {spirv::LiteralInteger(colorIndex)});
823     // Decorate the subpasss input color attachment with Set/Binding/InputAttachmentIndex.
824     InsertInputDecorations(spirv::IdRef(kIdColor0In + colorIndex),
825                            colorIndex + colorInputIndexStart, colorIndex + colorBindingIndexStart,
826                            blobOut);
827 }
828 
InsertDepthStencilDecorations(bool unresolveDepth,bool unresolveStencil,bool supportsShaderStencilExport,uint32_t * nextInputIndex,uint32_t * nextBindingIndex,angle::spirv::Blob * blobOut)829 void InsertDepthStencilDecorations(bool unresolveDepth,
830                                    bool unresolveStencil,
831                                    bool supportsShaderStencilExport,
832                                    uint32_t *nextInputIndex,
833                                    uint32_t *nextBindingIndex,
834                                    angle::spirv::Blob *blobOut)
835 {
836     if (unresolveStencil && supportsShaderStencilExport)
837     {
838         // Make sure unresolve desc set is compatible with the ExportStencil shader.
839         ASSERT(*nextInputIndex == kExportStencilInputIndex);
840         ASSERT(*nextBindingIndex == kExportStencilBinding);
841 
842         // Decorate the output stencil attachment with Location
843         spirv::WriteDecorate(blobOut, spirv::IdRef(kIdStencilOut), spv::DecorationBuiltIn,
844                              {spirv::LiteralInteger(spv::BuiltInFragStencilRefEXT)});
845         // Decorate the subpasss input stencil attachment with Set/Binding/InputAttachmentIndex.
846         InsertInputDecorations(spirv::IdRef(kIdStencilIn), *nextInputIndex, *nextBindingIndex,
847                                blobOut);
848 
849         // Advance the binding.  Note that the depth/stencil attachment has the same input
850         // attachment index (it's the same attachment in the subpass), but different bindings (one
851         // aspect per image view).
852         ++*nextBindingIndex;
853     }
854     if (unresolveDepth)
855     {
856         // Decorate the output depth attachment with Location
857         spirv::WriteDecorate(blobOut, spirv::IdRef(kIdDepthOut), spv::DecorationBuiltIn,
858                              {spirv::LiteralInteger(spv::BuiltInFragDepth)});
859         // Decorate the subpasss input depth attachment with Set/Binding/InputAttachmentIndex.
860         InsertInputDecorations(spirv::IdRef(kIdDepthIn), *nextInputIndex, *nextBindingIndex,
861                                blobOut);
862 
863         ++*nextBindingIndex;
864     }
865 
866     if (unresolveDepth || unresolveStencil)
867     {
868         // Even if stencil is taking a special path and is not being unresolved with color and
869         // depth, the input index is still consumed so the ExportStencil shader can operate on it.
870         ++*nextInputIndex;
871     }
872 }
873 
InsertDerivativeTypes(spirv::IdRef baseId,spirv::IdRef vec4Id,spirv::IdRef vec4OutId,spirv::IdRef imageTypeId,spirv::IdRef inputTypeId,angle::spirv::Blob * blobOut)874 void InsertDerivativeTypes(spirv::IdRef baseId,
875                            spirv::IdRef vec4Id,
876                            spirv::IdRef vec4OutId,
877                            spirv::IdRef imageTypeId,
878                            spirv::IdRef inputTypeId,
879                            angle::spirv::Blob *blobOut)
880 {
881     spirv::WriteTypeVector(blobOut, vec4Id, baseId, spirv::LiteralInteger(4));
882     spirv::WriteTypePointer(blobOut, vec4OutId, spv::StorageClassOutput, vec4Id);
883     spirv::WriteTypeImage(blobOut, imageTypeId, baseId, spv::DimSubpassData,
884                           // Unused with subpass inputs
885                           spirv::LiteralInteger(0),
886                           // Not arrayed
887                           spirv::LiteralInteger(0),
888                           // Not multisampled
889                           spirv::LiteralInteger(0),
890                           // Used without a sampler
891                           spirv::LiteralInteger(2), spv::ImageFormatUnknown, nullptr);
892     spirv::WriteTypePointer(blobOut, inputTypeId, spv::StorageClassUniformConstant, imageTypeId);
893 }
894 
InsertCommonTypes(angle::spirv::Blob * blobOut)895 void InsertCommonTypes(angle::spirv::Blob *blobOut)
896 {
897     // Types to support main().
898     spirv::WriteTypeVoid(blobOut, spirv::IdRef(kIdVoid));
899     spirv::WriteTypeFunction(blobOut, spirv::IdRef(kIdMainType), spirv::IdRef(kIdVoid), {});
900 
901     // Float types
902     spirv::WriteTypeFloat(blobOut, spirv::IdRef(kIdFloatType), spirv::LiteralInteger(32), nullptr);
903     InsertDerivativeTypes(spirv::IdRef(kIdFloatType), spirv::IdRef(kIdFloat4Type),
904                           spirv::IdRef(kIdFloat4OutType), spirv::IdRef(kIdFloatSubpassImageType),
905                           spirv::IdRef(kIdFloatSubpassInputType), blobOut);
906 
907     // Int types
908     spirv::WriteTypeInt(blobOut, spirv::IdRef(kIdSIntType), spirv::LiteralInteger(32),
909                         spirv::LiteralInteger(1));
910     InsertDerivativeTypes(spirv::IdRef(kIdSIntType), spirv::IdRef(kIdSInt4Type),
911                           spirv::IdRef(kIdSInt4OutType), spirv::IdRef(kIdSIntSubpassImageType),
912                           spirv::IdRef(kIdSIntSubpassInputType), blobOut);
913 
914     // Unsigned int types
915     spirv::WriteTypeInt(blobOut, spirv::IdRef(kIdUIntType), spirv::LiteralInteger(32),
916                         spirv::LiteralInteger(0));
917     InsertDerivativeTypes(spirv::IdRef(kIdUIntType), spirv::IdRef(kIdUInt4Type),
918                           spirv::IdRef(kIdUInt4OutType), spirv::IdRef(kIdUIntSubpassImageType),
919                           spirv::IdRef(kIdUIntSubpassInputType), blobOut);
920 
921     // Types to support depth/stencil
922     spirv::WriteTypePointer(blobOut, spirv::IdRef(kIdFloatOutType), spv::StorageClassOutput,
923                             spirv::IdRef(kIdFloatType));
924     spirv::WriteTypePointer(blobOut, spirv::IdRef(kIdSIntOutType), spv::StorageClassOutput,
925                             spirv::IdRef(kIdSIntType));
926 
927     // Constants used to load from subpass inputs
928     spirv::WriteConstant(blobOut, spirv::IdRef(kIdSIntType), spirv::IdRef(kIdSIntZero),
929                          spirv::LiteralInteger(0));
930     spirv::WriteTypeVector(blobOut, spirv::IdRef(kIdSInt2Type), spirv::IdRef(kIdSIntType),
931                            spirv::LiteralInteger(2));
932     spirv::WriteConstantComposite(blobOut, spirv::IdRef(kIdSInt2Type), spirv::IdRef(kIdSInt2Zero),
933                                   {spirv::IdRef(kIdSIntZero), spirv::IdRef(kIdSIntZero)});
934 }
935 
InsertVariableDecl(spirv::IdRef outType,spirv::IdRef outId,spirv::IdRef inType,spirv::IdRef inId,angle::spirv::Blob * blobOut)936 void InsertVariableDecl(spirv::IdRef outType,
937                         spirv::IdRef outId,
938                         spirv::IdRef inType,
939                         spirv::IdRef inId,
940                         angle::spirv::Blob *blobOut)
941 {
942     // Declare both the output and subpass input variables.
943     spirv::WriteVariable(blobOut, outType, outId, spv::StorageClassOutput, nullptr);
944     spirv::WriteVariable(blobOut, inType, inId, spv::StorageClassUniformConstant, nullptr);
945 }
946 
InsertColorVariableDecl(uint32_t colorIndex,UnresolveColorAttachmentType type,angle::spirv::Blob * blobOut)947 void InsertColorVariableDecl(uint32_t colorIndex,
948                              UnresolveColorAttachmentType type,
949                              angle::spirv::Blob *blobOut)
950 {
951     // Find the correct types for color variable declarations.
952     spirv::IdRef outType(kIdFloat4OutType);
953     spirv::IdRef outId(kIdColor0Out + colorIndex);
954     spirv::IdRef inType(kIdFloatSubpassInputType);
955     spirv::IdRef inId(kIdColor0In + colorIndex);
956     switch (type)
957     {
958         case kUnresolveTypeSint:
959             outType = spirv::IdRef(kIdSInt4OutType);
960             inType  = spirv::IdRef(kIdSIntSubpassInputType);
961             break;
962         case kUnresolveTypeUint:
963             outType = spirv::IdRef(kIdUInt4OutType);
964             inType  = spirv::IdRef(kIdUIntSubpassInputType);
965             break;
966         default:
967             break;
968     }
969     InsertVariableDecl(outType, outId, inType, inId, blobOut);
970 }
971 
InsertDepthStencilVariableDecl(bool unresolveDepth,bool unresolveStencil,angle::spirv::Blob * blobOut)972 void InsertDepthStencilVariableDecl(bool unresolveDepth,
973                                     bool unresolveStencil,
974                                     angle::spirv::Blob *blobOut)
975 {
976     if (unresolveDepth)
977     {
978         InsertVariableDecl(spirv::IdRef(kIdFloatOutType), spirv::IdRef(kIdDepthOut),
979                            spirv::IdRef(kIdFloatSubpassInputType), spirv::IdRef(kIdDepthIn),
980                            blobOut);
981     }
982     if (unresolveStencil)
983     {
984         InsertVariableDecl(spirv::IdRef(kIdSIntOutType), spirv::IdRef(kIdStencilOut),
985                            spirv::IdRef(kIdUIntSubpassInputType), spirv::IdRef(kIdStencilIn),
986                            blobOut);
987     }
988 }
989 
InsertTopOfMain(angle::spirv::Blob * blobOut)990 void InsertTopOfMain(angle::spirv::Blob *blobOut)
991 {
992     spirv::WriteFunction(blobOut, spirv::IdRef(kIdVoid), spirv::IdRef(kIdMain),
993                          spv::FunctionControlMaskNone, spirv::IdRef(kIdMainType));
994     spirv::WriteLabel(blobOut, spirv::IdRef(kIdMainLabel));
995 }
996 
InsertColorUnresolveLoadStore(uint32_t colorIndex,UnresolveColorAttachmentType type,angle::spirv::Blob * blobOut)997 void InsertColorUnresolveLoadStore(uint32_t colorIndex,
998                                    UnresolveColorAttachmentType type,
999                                    angle::spirv::Blob *blobOut)
1000 {
1001     spirv::IdRef loadResult(kIdColor0Load + colorIndex * 2);
1002     spirv::IdRef imageReadResult(loadResult + 1);
1003 
1004     // Find the correct types for load/store.
1005     spirv::IdRef loadType(kIdFloatSubpassImageType);
1006     spirv::IdRef readType(kIdFloat4Type);
1007     spirv::IdRef inId(kIdColor0In + colorIndex);
1008     spirv::IdRef outId(kIdColor0Out + colorIndex);
1009     switch (type)
1010     {
1011         case kUnresolveTypeSint:
1012             loadType = spirv::IdRef(kIdSIntSubpassImageType);
1013             readType = spirv::IdRef(kIdSInt4Type);
1014             break;
1015         case kUnresolveTypeUint:
1016             loadType = spirv::IdRef(kIdUIntSubpassImageType);
1017             readType = spirv::IdRef(kIdUInt4Type);
1018             break;
1019         default:
1020             break;
1021     }
1022 
1023     // Load the subpass input image, read from it, and store in output.
1024     spirv::WriteLoad(blobOut, loadType, loadResult, inId, nullptr);
1025     spirv::WriteImageRead(blobOut, readType, imageReadResult, loadResult,
1026                           spirv::IdRef(kIdSInt2Zero), nullptr, {});
1027     spirv::WriteStore(blobOut, outId, imageReadResult, nullptr);
1028 }
1029 
InsertDepthStencilUnresolveLoadStore(bool unresolveDepth,bool unresolveStencil,angle::spirv::Blob * blobOut)1030 void InsertDepthStencilUnresolveLoadStore(bool unresolveDepth,
1031                                           bool unresolveStencil,
1032                                           angle::spirv::Blob *blobOut)
1033 {
1034     if (unresolveDepth)
1035     {
1036         spirv::IdRef loadResult(kIdDepthLoad);
1037         spirv::IdRef imageReadResult(loadResult + 1);
1038         spirv::IdRef extractResult(imageReadResult + 1);
1039 
1040         spirv::IdRef loadType(kIdFloatSubpassImageType);
1041         spirv::IdRef readType(kIdFloat4Type);
1042         spirv::IdRef inId(kIdDepthIn);
1043         spirv::IdRef outId(kIdDepthOut);
1044 
1045         // Load the subpass input image, read from it, select .x, and store in output.
1046         spirv::WriteLoad(blobOut, loadType, loadResult, inId, nullptr);
1047         spirv::WriteImageRead(blobOut, readType, imageReadResult, loadResult,
1048                               spirv::IdRef(kIdSInt2Zero), nullptr, {});
1049         spirv::WriteCompositeExtract(blobOut, spirv::IdRef(kIdFloatType), extractResult,
1050                                      imageReadResult, {spirv::LiteralInteger(0)});
1051         spirv::WriteStore(blobOut, outId, extractResult, nullptr);
1052     }
1053     if (unresolveStencil)
1054     {
1055         spirv::IdRef loadResult(kIdStencilLoad);
1056         spirv::IdRef imageReadResult(loadResult + 1);
1057         spirv::IdRef extractResult(imageReadResult + 1);
1058         spirv::IdRef bitcastResult(extractResult + 1);
1059 
1060         spirv::IdRef loadType(kIdUIntSubpassImageType);
1061         spirv::IdRef readType(kIdUInt4Type);
1062         spirv::IdRef inId(kIdStencilIn);
1063         spirv::IdRef outId(kIdStencilOut);
1064 
1065         // Load the subpass input image, read from it, select .x, and store in output.  There's a
1066         // bitcast involved since the stencil subpass input has unsigned type, while
1067         // gl_FragStencilRefARB is signed!
1068         spirv::WriteLoad(blobOut, loadType, loadResult, inId, nullptr);
1069         spirv::WriteImageRead(blobOut, readType, imageReadResult, loadResult,
1070                               spirv::IdRef(kIdSInt2Zero), nullptr, {});
1071         spirv::WriteCompositeExtract(blobOut, spirv::IdRef(kIdUIntType), extractResult,
1072                                      imageReadResult, {spirv::LiteralInteger(0)});
1073         spirv::WriteBitcast(blobOut, spirv::IdRef(kIdSIntType), bitcastResult, extractResult);
1074         spirv::WriteStore(blobOut, outId, bitcastResult, nullptr);
1075     }
1076 }
1077 
InsertBottomOfMain(angle::spirv::Blob * blobOut)1078 void InsertBottomOfMain(angle::spirv::Blob *blobOut)
1079 {
1080     spirv::WriteReturn(blobOut);
1081     spirv::WriteFunctionEnd(blobOut);
1082 }
1083 
MakeFragShader(uint32_t colorAttachmentCount,gl::DrawBuffersArray<UnresolveColorAttachmentType> & colorAttachmentTypes,bool unresolveDepth,bool unresolveStencil,bool supportsShaderStencilExport)1084 angle::spirv::Blob MakeFragShader(
1085     uint32_t colorAttachmentCount,
1086     gl::DrawBuffersArray<UnresolveColorAttachmentType> &colorAttachmentTypes,
1087     bool unresolveDepth,
1088     bool unresolveStencil,
1089     bool supportsShaderStencilExport)
1090 {
1091     const bool unresolveStencilWithShaderExport = unresolveStencil && supportsShaderStencilExport;
1092 
1093     angle::spirv::Blob code;
1094 
1095     // Reserve a sensible amount of memory.  A single-attachment shader is 169 words.
1096     code.reserve(169);
1097 
1098     // Header
1099     spirv::WriteSpirvHeader(&code, spirv::kVersion_1_0, kIdCount);
1100 
1101     // The preamble
1102     InsertPreamble(colorAttachmentCount, unresolveDepth, unresolveStencilWithShaderExport, &code);
1103 
1104     // Depth stencil decorations
1105     uint32_t colorInputIndexStart   = 0;
1106     uint32_t colorBindingIndexStart = 0;
1107     InsertDepthStencilDecorations(unresolveDepth, unresolveStencil, supportsShaderStencilExport,
1108                                   &colorInputIndexStart, &colorBindingIndexStart, &code);
1109 
1110     // Color attachment decorations
1111     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; ++colorIndex)
1112     {
1113         InsertColorDecorations(colorIndex, colorInputIndexStart, colorBindingIndexStart, &code);
1114     }
1115 
1116     // Common types
1117     InsertCommonTypes(&code);
1118 
1119     // Attachment declarations
1120     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; ++colorIndex)
1121     {
1122         InsertColorVariableDecl(colorIndex, colorAttachmentTypes[colorIndex], &code);
1123     }
1124     InsertDepthStencilVariableDecl(unresolveDepth, unresolveStencilWithShaderExport, &code);
1125 
1126     // Top of main
1127     InsertTopOfMain(&code);
1128 
1129     // Load and store for each attachment
1130     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; ++colorIndex)
1131     {
1132         InsertColorUnresolveLoadStore(colorIndex, colorAttachmentTypes[colorIndex], &code);
1133     }
1134     InsertDepthStencilUnresolveLoadStore(unresolveDepth, unresolveStencilWithShaderExport, &code);
1135 
1136     // Bottom of main
1137     InsertBottomOfMain(&code);
1138 
1139     return code;
1140 }
1141 }  // namespace unresolve
1142 
GetUnresolveFrag(vk::ErrorContext * context,uint32_t colorAttachmentCount,gl::DrawBuffersArray<UnresolveColorAttachmentType> & colorAttachmentTypes,bool unresolveDepth,bool unresolveStencil,vk::ShaderModulePtr * shader)1143 angle::Result GetUnresolveFrag(
1144     vk::ErrorContext *context,
1145     uint32_t colorAttachmentCount,
1146     gl::DrawBuffersArray<UnresolveColorAttachmentType> &colorAttachmentTypes,
1147     bool unresolveDepth,
1148     bool unresolveStencil,
1149     vk::ShaderModulePtr *shader)
1150 {
1151     if (*shader)
1152     {
1153         ASSERT((*shader)->valid());
1154         return angle::Result::Continue;
1155     }
1156 
1157     angle::spirv::Blob shaderCode = unresolve::MakeFragShader(
1158         colorAttachmentCount, colorAttachmentTypes, unresolveDepth, unresolveStencil,
1159         context->getFeatures().supportsShaderStencilExport.enabled);
1160 
1161     ASSERT(spirv::Validate(shaderCode));
1162 
1163     // Create shader lazily. Access will need to be locked for multi-threading.
1164     return vk::InitShaderModule(context, shader, shaderCode.data(), shaderCode.size() * 4);
1165 }
1166 
MakeColorBufferMask(uint32_t colorAttachmentIndexGL)1167 gl::DrawBufferMask MakeColorBufferMask(uint32_t colorAttachmentIndexGL)
1168 {
1169     gl::DrawBufferMask mask;
1170     mask.set(colorAttachmentIndexGL);
1171     return mask;
1172 }
1173 
UpdateColorAccess(ContextVk * contextVk,gl::DrawBufferMask colorAttachmentMask,gl::DrawBufferMask colorEnabledMask)1174 void UpdateColorAccess(ContextVk *contextVk,
1175                        gl::DrawBufferMask colorAttachmentMask,
1176                        gl::DrawBufferMask colorEnabledMask)
1177 {
1178     vk::RenderPassCommandBufferHelper *renderPassCommands =
1179         &contextVk->getStartedRenderPassCommands();
1180 
1181     // Explicitly mark a color write because we are modifying the color buffer.
1182     vk::PackedAttachmentIndex colorIndexVk(0);
1183     for (size_t colorIndexGL : colorAttachmentMask)
1184     {
1185         if (colorEnabledMask.test(colorIndexGL))
1186         {
1187             renderPassCommands->onColorAccess(colorIndexVk, vk::ResourceAccess::ReadWrite);
1188         }
1189         ++colorIndexVk;
1190     }
1191 }
1192 
UpdateDepthStencilAccess(ContextVk * contextVk,bool depthWrite,bool stencilWrite)1193 void UpdateDepthStencilAccess(ContextVk *contextVk, bool depthWrite, bool stencilWrite)
1194 {
1195     vk::RenderPassCommandBufferHelper *renderPassCommands =
1196         &contextVk->getStartedRenderPassCommands();
1197 
1198     if (depthWrite)
1199     {
1200         // Explicitly mark a depth write because we are modifying the depth buffer.
1201         renderPassCommands->onDepthAccess(vk::ResourceAccess::ReadWrite);
1202         // Because we may have changed the depth access mode, update read only depth mode.
1203         renderPassCommands->updateDepthReadOnlyMode(contextVk->getDepthStencilAttachmentFlags());
1204     }
1205     if (stencilWrite)
1206     {
1207         // Explicitly mark a stencil write because we are modifying the stencil buffer.
1208         renderPassCommands->onStencilAccess(vk::ResourceAccess::ReadWrite);
1209         // Because we may have changed the stencil access mode, update read only stencil mode.
1210         renderPassCommands->updateStencilReadOnlyMode(contextVk->getDepthStencilAttachmentFlags());
1211     }
1212 }
1213 
ResetDynamicState(ContextVk * contextVk,vk::RenderPassCommandBuffer * commandBuffer)1214 void ResetDynamicState(ContextVk *contextVk, vk::RenderPassCommandBuffer *commandBuffer)
1215 {
1216     // Reset dynamic state that might affect UtilsVk.  Mark all dynamic state dirty for simplicity.
1217     // Ideally, only dynamic state that is changed by UtilsVk will be marked dirty but, until such
1218     // time as extensive transition tests are written, this approach is less bug-prone.
1219 
1220     // Notes: the following dynamic state doesn't apply to UtilsVk functions:
1221     //
1222     // - line width: UtilsVk doesn't use line primitives
1223     // - depth bias: UtilsVk doesn't enable depth bias
1224     // - blend constants: UtilsVk doesn't enable blending
1225     // - logic op: UtilsVk doesn't enable logic op
1226     //
1227     // The following dynamic state is always set by UtilsVk when effective:
1228     //
1229     // - depth write mask: UtilsVk sets this when enabling depth test
1230     // - depth compare op: UtilsVk sets this when enabling depth test
1231     // - stencil compare mask: UtilsVk sets this when enabling stencil test
1232     // - stencil write mask: UtilsVk sets this when enabling stencil test
1233     // - stencil reference: UtilsVk sets this when enabling stencil test
1234     // - stencil func: UtilsVk sets this when enabling stencil test
1235     // - stencil ops: UtilsVk sets this when enabling stencil test
1236 
1237     vk::Renderer *renderer = contextVk->getRenderer();
1238 
1239     // Reset all other dynamic state, since it can affect UtilsVk functions:
1240     if (renderer->getFeatures().useCullModeDynamicState.enabled)
1241     {
1242         commandBuffer->setCullMode(VK_CULL_MODE_NONE);
1243     }
1244     if (renderer->getFeatures().useFrontFaceDynamicState.enabled)
1245     {
1246         commandBuffer->setFrontFace(VK_FRONT_FACE_COUNTER_CLOCKWISE);
1247     }
1248     if (renderer->getFeatures().useDepthTestEnableDynamicState.enabled)
1249     {
1250         commandBuffer->setDepthTestEnable(VK_FALSE);
1251     }
1252     if (renderer->getFeatures().useStencilTestEnableDynamicState.enabled)
1253     {
1254         commandBuffer->setStencilTestEnable(VK_FALSE);
1255     }
1256     if (renderer->getFeatures().useRasterizerDiscardEnableDynamicState.enabled)
1257     {
1258         commandBuffer->setRasterizerDiscardEnable(VK_FALSE);
1259     }
1260     if (renderer->getFeatures().useDepthBiasEnableDynamicState.enabled)
1261     {
1262         commandBuffer->setDepthBiasEnable(VK_FALSE);
1263     }
1264     if (renderer->getFeatures().usePrimitiveRestartEnableDynamicState.enabled)
1265     {
1266         commandBuffer->setPrimitiveRestartEnable(VK_FALSE);
1267     }
1268     if (contextVk->getFeatures().supportsFragmentShadingRate.enabled)
1269     {
1270         VkExtent2D fragmentSize                                     = {1, 1};
1271         VkFragmentShadingRateCombinerOpKHR shadingRateCombinerOp[2] = {
1272             VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
1273             VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR};
1274         commandBuffer->setFragmentShadingRate(&fragmentSize, shadingRateCombinerOp);
1275     }
1276     if (renderer->getFeatures().supportsLogicOpDynamicState.enabled)
1277     {
1278         commandBuffer->setLogicOp(VK_LOGIC_OP_COPY);
1279     }
1280     if (contextVk->getFeatures().supportsVertexInputDynamicState.enabled)
1281     {
1282         commandBuffer->setVertexInput(0, nullptr, 0, nullptr);
1283     }
1284 
1285     // Let ContextVk know that it should refresh all dynamic state.
1286     contextVk->invalidateAllDynamicState();
1287 }
1288 }  // namespace
1289 
1290 UtilsVk::ConvertVertexShaderParams::ConvertVertexShaderParams() = default;
1291 
1292 UtilsVk::ImageCopyShaderParams::ImageCopyShaderParams() = default;
1293 
GetGenerateMipmapMaxLevels(ContextVk * contextVk)1294 uint32_t UtilsVk::GetGenerateMipmapMaxLevels(ContextVk *contextVk)
1295 {
1296     vk::Renderer *renderer = contextVk->getRenderer();
1297 
1298     uint32_t maxPerStageDescriptorStorageImages =
1299         renderer->getPhysicalDeviceProperties().limits.maxPerStageDescriptorStorageImages;
1300 
1301     // Vulkan requires that there be support for at least 4 storage images per stage.
1302     constexpr uint32_t kMinimumStorageImagesLimit = 4;
1303     ASSERT(maxPerStageDescriptorStorageImages >= kMinimumStorageImagesLimit);
1304 
1305     // If fewer than max-levels are supported, use 4 levels (which is the minimum required number
1306     // of storage image bindings).
1307     return maxPerStageDescriptorStorageImages < kGenerateMipmapMaxLevels
1308                ? kMinimumStorageImagesLimit
1309                : kGenerateMipmapMaxLevels;
1310 }
1311 
1312 UtilsVk::UtilsVk() = default;
1313 
1314 UtilsVk::~UtilsVk() = default;
1315 
destroy(ContextVk * contextVk)1316 void UtilsVk::destroy(ContextVk *contextVk)
1317 {
1318     vk::Renderer *renderer = contextVk->getRenderer();
1319     VkDevice device        = renderer->getDevice();
1320 
1321     for (Function f : angle::AllEnums<Function>())
1322     {
1323         for (auto &descriptorSetLayout : mDescriptorSetLayouts[f])
1324         {
1325             descriptorSetLayout.reset();
1326         }
1327         mPipelineLayouts[f].reset();
1328         mDescriptorPools[f].destroy(device);
1329     }
1330 
1331     for (auto &item : mImageCopyWithSamplerPipelineLayouts)
1332     {
1333         const vk::SamplerDesc &samplerDesc = item.first;
1334 
1335         for (auto &descriptorSetLayout : mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc])
1336         {
1337             descriptorSetLayout.reset();
1338         }
1339         mImageCopyWithSamplerPipelineLayouts[samplerDesc].reset();
1340         mImageCopyWithSamplerDescriptorPools[samplerDesc].destroy(device);
1341     }
1342 
1343     for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertIndex)
1344     {
1345         programAndPipelines.program.destroy(renderer);
1346         programAndPipelines.pipelines.destroy(contextVk);
1347     }
1348     for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertIndirectLineLoop)
1349     {
1350         programAndPipelines.program.destroy(renderer);
1351         programAndPipelines.pipelines.destroy(contextVk);
1352     }
1353     for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertIndexIndirectLineLoop)
1354     {
1355         programAndPipelines.program.destroy(renderer);
1356         programAndPipelines.pipelines.destroy(contextVk);
1357     }
1358     for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertVertex)
1359     {
1360         programAndPipelines.program.destroy(renderer);
1361         programAndPipelines.pipelines.destroy(contextVk);
1362     }
1363     mImageClearVSOnly.program.destroy(renderer);
1364     mImageClearVSOnly.pipelines.destroy(contextVk);
1365     for (GraphicsShaderProgramAndPipelines &programAndPipelines : mImageClear)
1366     {
1367         programAndPipelines.program.destroy(renderer);
1368         programAndPipelines.pipelines.destroy(contextVk);
1369     }
1370     for (GraphicsShaderProgramAndPipelines &programAndPipelines : mImageCopy)
1371     {
1372         programAndPipelines.program.destroy(renderer);
1373         programAndPipelines.pipelines.destroy(contextVk);
1374     }
1375     mImageCopyFloat.program.destroy(renderer);
1376     mImageCopyFloat.pipelines.destroy(contextVk);
1377     for (auto &iter : mImageCopyWithSampler)
1378     {
1379         GraphicsShaderProgramAndPipelines &programAndPipelines = iter.second;
1380         programAndPipelines.program.destroy(renderer);
1381         programAndPipelines.pipelines.destroy(contextVk);
1382     }
1383     for (ComputeShaderProgramAndPipelines &programAndPipelines : mCopyImageToBuffer)
1384     {
1385         programAndPipelines.program.destroy(renderer);
1386         programAndPipelines.pipelines.destroy(contextVk);
1387     }
1388     for (GraphicsShaderProgramAndPipelines &programAndPipelines : mBlitResolve)
1389     {
1390         programAndPipelines.program.destroy(renderer);
1391         programAndPipelines.pipelines.destroy(contextVk);
1392     }
1393     for (GraphicsShaderProgramAndPipelines &programAndPipelines : mBlit3DSrc)
1394     {
1395         programAndPipelines.program.destroy(renderer);
1396         programAndPipelines.pipelines.destroy(contextVk);
1397     }
1398     for (ComputeShaderProgramAndPipelines &programAndPipelines : mBlitResolveStencilNoExport)
1399     {
1400         programAndPipelines.program.destroy(renderer);
1401         programAndPipelines.pipelines.destroy(contextVk);
1402     }
1403     mExportStencil.program.destroy(renderer);
1404     mExportStencil.pipelines.destroy(contextVk);
1405     mOverlayDraw.program.destroy(renderer);
1406     mOverlayDraw.pipelines.destroy(contextVk);
1407     for (ComputeShaderProgramAndPipelines &programAndPipelines : mGenerateMipmap)
1408     {
1409         programAndPipelines.program.destroy(renderer);
1410         programAndPipelines.pipelines.destroy(contextVk);
1411     }
1412     for (ComputeShaderProgramAndPipelines &programAndPipelines : mEtcToBc)
1413     {
1414         programAndPipelines.program.destroy(renderer);
1415         programAndPipelines.pipelines.destroy(contextVk);
1416     }
1417     for (auto &programIter : mUnresolve)
1418     {
1419         GraphicsShaderProgramAndPipelines &programAndPipelines = programIter.second;
1420         programAndPipelines.program.destroy(renderer);
1421         programAndPipelines.pipelines.destroy(contextVk);
1422     }
1423     mUnresolve.clear();
1424 
1425     mUnresolveFragShaders.clear();
1426 
1427     mPointSampler.destroy(device);
1428     mLinearSampler.destroy(device);
1429 
1430     mGenerateFragmentShadingRateAttachment.program.destroy(renderer);
1431     mGenerateFragmentShadingRateAttachment.pipelines.destroy(contextVk);
1432 }
1433 
ensureResourcesInitialized(ContextVk * contextVk,Function function,VkDescriptorPoolSize * setSizes,size_t setSizesCount,size_t pushConstantsSize)1434 angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
1435                                                   Function function,
1436                                                   VkDescriptorPoolSize *setSizes,
1437                                                   size_t setSizesCount,
1438                                                   size_t pushConstantsSize)
1439 {
1440     vk::DescriptorSetLayoutDesc descriptorSetDesc;
1441     bool isCompute = function >= Function::ComputeStartIndex;
1442     VkShaderStageFlags descStages =
1443         isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
1444     if (function == Function::OverlayDraw)
1445     {
1446         descStages |= VK_SHADER_STAGE_VERTEX_BIT;
1447     }
1448 
1449     uint32_t currentBinding = 0;
1450     for (size_t i = 0; i < setSizesCount; ++i)
1451     {
1452         descriptorSetDesc.addBinding(currentBinding, setSizes[i].type, setSizes[i].descriptorCount,
1453                                      descStages, nullptr);
1454         ++currentBinding;
1455     }
1456 
1457     ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1458         contextVk, descriptorSetDesc,
1459         &mDescriptorSetLayouts[function][DescriptorSetIndex::Internal]));
1460 
1461     vk::DescriptorSetLayoutBindingVector bindingVector;
1462     descriptorSetDesc.unpackBindings(&bindingVector);
1463     std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
1464 
1465     for (const VkDescriptorSetLayoutBinding &binding : bindingVector)
1466     {
1467         if (binding.descriptorCount > 0)
1468         {
1469             VkDescriptorPoolSize poolSize = {};
1470 
1471             poolSize.type            = binding.descriptorType;
1472             poolSize.descriptorCount = binding.descriptorCount;
1473             descriptorPoolSizes.emplace_back(poolSize);
1474         }
1475     }
1476     if (!descriptorPoolSizes.empty())
1477     {
1478         ANGLE_TRY(mDescriptorPools[function].init(
1479             contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
1480             *mDescriptorSetLayouts[function][DescriptorSetIndex::Internal]));
1481     }
1482 
1483     // Corresponding pipeline layouts:
1484     vk::PipelineLayoutDesc pipelineLayoutDesc;
1485 
1486     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Internal, descriptorSetDesc);
1487     if (pushConstantsSize)
1488     {
1489         pipelineLayoutDesc.updatePushConstantRange(descStages, 0,
1490                                                    static_cast<uint32_t>(pushConstantsSize));
1491     }
1492 
1493     ANGLE_TRY(contextVk->getPipelineLayoutCache().getPipelineLayout(contextVk, pipelineLayoutDesc,
1494                                                                     mDescriptorSetLayouts[function],
1495                                                                     &mPipelineLayouts[function]));
1496 
1497     return angle::Result::Continue;
1498 }
1499 
ensureConvertIndexResourcesInitialized(ContextVk * contextVk)1500 angle::Result UtilsVk::ensureConvertIndexResourcesInitialized(ContextVk *contextVk)
1501 {
1502     if (mPipelineLayouts[Function::ConvertIndexBuffer])
1503     {
1504         return angle::Result::Continue;
1505     }
1506 
1507     VkDescriptorPoolSize setSizes[2] = {
1508         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1509         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1510     };
1511 
1512     return ensureResourcesInitialized(contextVk, Function::ConvertIndexBuffer, setSizes,
1513                                       ArraySize(setSizes), sizeof(ConvertIndexShaderParams));
1514 }
1515 
ensureConvertIndexIndirectResourcesInitialized(ContextVk * contextVk)1516 angle::Result UtilsVk::ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk)
1517 {
1518     if (mPipelineLayouts[Function::ConvertIndexIndirectBuffer])
1519     {
1520         return angle::Result::Continue;
1521     }
1522 
1523     VkDescriptorPoolSize setSizes[4] = {
1524         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst index buffer
1525         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // source index buffer
1526         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // src indirect buffer
1527         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst indirect buffer
1528     };
1529 
1530     return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectBuffer, setSizes,
1531                                       ArraySize(setSizes),
1532                                       sizeof(ConvertIndexIndirectShaderParams));
1533 }
1534 
ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk * contextVk)1535 angle::Result UtilsVk::ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
1536 {
1537     if (mPipelineLayouts[Function::ConvertIndexIndirectLineLoopBuffer])
1538     {
1539         return angle::Result::Continue;
1540     }
1541 
1542     VkDescriptorPoolSize setSizes[4] = {
1543         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // cmd buffer
1544         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst cmd buffer
1545         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // source index buffer
1546         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst index buffer
1547     };
1548 
1549     return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
1550                                       setSizes, ArraySize(setSizes),
1551                                       sizeof(ConvertIndexIndirectLineLoopShaderParams));
1552 }
1553 
ensureConvertIndirectLineLoopResourcesInitialized(ContextVk * contextVk)1554 angle::Result UtilsVk::ensureConvertIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
1555 {
1556     if (mPipelineLayouts[Function::ConvertIndirectLineLoopBuffer])
1557     {
1558         return angle::Result::Continue;
1559     }
1560 
1561     VkDescriptorPoolSize setSizes[3] = {
1562         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // cmd buffer
1563         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst cmd buffer
1564         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst index buffer
1565     };
1566 
1567     return ensureResourcesInitialized(contextVk, Function::ConvertIndirectLineLoopBuffer, setSizes,
1568                                       ArraySize(setSizes),
1569                                       sizeof(ConvertIndirectLineLoopShaderParams));
1570 }
1571 
ensureConvertVertexResourcesInitialized(ContextVk * contextVk)1572 angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk)
1573 {
1574     if (mPipelineLayouts[Function::ConvertVertexBuffer])
1575     {
1576         return angle::Result::Continue;
1577     }
1578 
1579     VkDescriptorPoolSize setSizes[2] = {
1580         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1581         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1582     };
1583 
1584     return ensureResourcesInitialized(contextVk, Function::ConvertVertexBuffer, setSizes,
1585                                       ArraySize(setSizes), sizeof(ConvertVertexShaderParams));
1586 }
1587 
ensureImageClearResourcesInitialized(ContextVk * contextVk)1588 angle::Result UtilsVk::ensureImageClearResourcesInitialized(ContextVk *contextVk)
1589 {
1590     if (mPipelineLayouts[Function::ImageClear])
1591     {
1592         return angle::Result::Continue;
1593     }
1594 
1595     // The shader does not use any descriptor sets.
1596     return ensureResourcesInitialized(contextVk, Function::ImageClear, nullptr, 0,
1597                                       sizeof(ImageClearShaderParams));
1598 }
1599 
ensureImageCopyResourcesInitialized(ContextVk * contextVk)1600 angle::Result UtilsVk::ensureImageCopyResourcesInitialized(ContextVk *contextVk)
1601 {
1602     if (mPipelineLayouts[Function::ImageCopy])
1603     {
1604         return angle::Result::Continue;
1605     }
1606 
1607     VkDescriptorPoolSize setSizes[1] = {
1608         {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1609     };
1610 
1611     return ensureResourcesInitialized(contextVk, Function::ImageCopy, setSizes, ArraySize(setSizes),
1612                                       sizeof(ImageCopyShaderParams));
1613 }
1614 
ensureImageCopyResourcesInitializedWithSampler(ContextVk * contextVk,const vk::SamplerDesc & samplerDesc)1615 angle::Result UtilsVk::ensureImageCopyResourcesInitializedWithSampler(
1616     ContextVk *contextVk,
1617     const vk::SamplerDesc &samplerDesc)
1618 {
1619     if (mImageCopyWithSamplerPipelineLayouts[samplerDesc])
1620     {
1621         return angle::Result::Continue;
1622     }
1623 
1624     vk::SharedSamplerPtr sampler;
1625     ANGLE_TRY(
1626         contextVk->getRenderer()->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler));
1627 
1628     vk::DescriptorSetLayoutDesc descriptorSetDesc;
1629     descriptorSetDesc.addBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1,
1630                                  VK_SHADER_STAGE_FRAGMENT_BIT, &sampler->get());
1631 
1632     ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1633         contextVk, descriptorSetDesc,
1634         &mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc][DescriptorSetIndex::Internal]));
1635 
1636     VkDescriptorPoolSize setSizes[1] = {
1637         // A single YCbCr sampler may consume up to 3 descriptors.
1638         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3},
1639     };
1640     ANGLE_TRY(mImageCopyWithSamplerDescriptorPools[samplerDesc].init(
1641         contextVk, setSizes, 1,
1642         *mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc][DescriptorSetIndex::Internal]));
1643 
1644     vk::PipelineLayoutDesc pipelineLayoutDesc;
1645     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Internal, descriptorSetDesc);
1646     pipelineLayoutDesc.updatePushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0,
1647                                                sizeof(ImageCopyShaderParams));
1648 
1649     ANGLE_TRY(contextVk->getPipelineLayoutCache().getPipelineLayout(
1650         contextVk, pipelineLayoutDesc, mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc],
1651         &mImageCopyWithSamplerPipelineLayouts[samplerDesc]));
1652 
1653     return angle::Result::Continue;
1654 }
1655 
ensureCopyImageToBufferResourcesInitialized(ContextVk * contextVk)1656 angle::Result UtilsVk::ensureCopyImageToBufferResourcesInitialized(ContextVk *contextVk)
1657 {
1658     if (mPipelineLayouts[Function::CopyImageToBuffer])
1659     {
1660         return angle::Result::Continue;
1661     }
1662 
1663     VkDescriptorPoolSize setSizes[2] = {
1664         {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1665         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1666     };
1667 
1668     return ensureResourcesInitialized(contextVk, Function::CopyImageToBuffer, setSizes,
1669                                       ArraySize(setSizes), sizeof(CopyImageToBufferShaderParams));
1670 }
1671 
ensureBlitResolveResourcesInitialized(ContextVk * contextVk)1672 angle::Result UtilsVk::ensureBlitResolveResourcesInitialized(ContextVk *contextVk)
1673 {
1674     if (!mPipelineLayouts[Function::BlitResolve])
1675     {
1676         VkDescriptorPoolSize setSizes[3] = {
1677             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1678             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1679             {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
1680         };
1681 
1682         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolve, setSizes,
1683                                              ArraySize(setSizes), sizeof(BlitResolveShaderParams)));
1684     }
1685 
1686     return ensureSamplersInitialized(contextVk);
1687 }
1688 
ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk * contextVk)1689 angle::Result UtilsVk::ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk *contextVk)
1690 {
1691     if (!mPipelineLayouts[Function::BlitResolveStencilNoExport])
1692     {
1693         VkDescriptorPoolSize setSizes[3] = {
1694             {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1695             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1696             {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
1697         };
1698 
1699         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolveStencilNoExport,
1700                                              setSizes, ArraySize(setSizes),
1701                                              sizeof(BlitResolveStencilNoExportShaderParams)));
1702     }
1703 
1704     return ensureSamplersInitialized(contextVk);
1705 }
1706 
ensureExportStencilResourcesInitialized(ContextVk * contextVk)1707 angle::Result UtilsVk::ensureExportStencilResourcesInitialized(ContextVk *contextVk)
1708 {
1709     if (mPipelineLayouts[Function::ExportStencil])
1710     {
1711         return angle::Result::Continue;
1712     }
1713 
1714     VkDescriptorPoolSize setSizes[1] = {
1715         {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1},
1716     };
1717 
1718     return ensureResourcesInitialized(contextVk, Function::ExportStencil, setSizes,
1719                                       ArraySize(setSizes), sizeof(ExportStencilShaderParams));
1720 }
1721 
ensureOverlayDrawResourcesInitialized(ContextVk * contextVk)1722 angle::Result UtilsVk::ensureOverlayDrawResourcesInitialized(ContextVk *contextVk)
1723 {
1724     if (!mPipelineLayouts[Function::OverlayDraw])
1725     {
1726         VkDescriptorPoolSize setSizes[3] = {
1727             {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
1728             {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
1729             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1730         };
1731 
1732         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::OverlayDraw, setSizes,
1733                                              ArraySize(setSizes), sizeof(OverlayDrawShaderParams)));
1734     }
1735 
1736     return ensureSamplersInitialized(contextVk);
1737 }
1738 
ensureGenerateMipmapResourcesInitialized(ContextVk * contextVk)1739 angle::Result UtilsVk::ensureGenerateMipmapResourcesInitialized(ContextVk *contextVk)
1740 {
1741     if (mPipelineLayouts[Function::GenerateMipmap])
1742     {
1743         return angle::Result::Continue;
1744     }
1745 
1746     VkDescriptorPoolSize setSizes[2] = {
1747         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, GetGenerateMipmapMaxLevels(contextVk)},
1748         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1},
1749     };
1750 
1751     return ensureResourcesInitialized(contextVk, Function::GenerateMipmap, setSizes,
1752                                       ArraySize(setSizes), sizeof(GenerateMipmapShaderParams));
1753 }
1754 
ensureTransCodeEtcToBcResourcesInitialized(ContextVk * contextVk)1755 angle::Result UtilsVk::ensureTransCodeEtcToBcResourcesInitialized(ContextVk *contextVk)
1756 {
1757     if (mPipelineLayouts[Function::TransCodeEtcToBc])
1758     {
1759         return angle::Result::Continue;
1760     }
1761     VkDescriptorPoolSize setSizes[2] = {
1762         {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1},
1763         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
1764     };
1765 
1766     return ensureResourcesInitialized(contextVk, Function::TransCodeEtcToBc, setSizes,
1767                                       ArraySize(setSizes), sizeof(EtcToBcShaderParams));
1768 }
1769 
ensureUnresolveResourcesInitialized(ContextVk * contextVk,Function function,uint32_t attachmentCount)1770 angle::Result UtilsVk::ensureUnresolveResourcesInitialized(ContextVk *contextVk,
1771                                                            Function function,
1772                                                            uint32_t attachmentCount)
1773 {
1774     ASSERT(static_cast<uint32_t>(function) -
1775                static_cast<uint32_t>(Function::Unresolve1Attachment) ==
1776            attachmentCount - 1);
1777 
1778     if (mPipelineLayouts[function])
1779     {
1780         return angle::Result::Continue;
1781     }
1782 
1783     vk::FramebufferAttachmentArray<VkDescriptorPoolSize> setSizes;
1784     std::fill(setSizes.begin(), setSizes.end(),
1785               VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1});
1786 
1787     return ensureResourcesInitialized(contextVk, function, setSizes.data(), attachmentCount, 0);
1788 }
1789 
ensureSamplersInitialized(ContextVk * contextVk)1790 angle::Result UtilsVk::ensureSamplersInitialized(ContextVk *contextVk)
1791 {
1792     VkSamplerCreateInfo samplerInfo     = {};
1793     samplerInfo.sType                   = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
1794     samplerInfo.flags                   = 0;
1795     samplerInfo.magFilter               = VK_FILTER_NEAREST;
1796     samplerInfo.minFilter               = VK_FILTER_NEAREST;
1797     samplerInfo.mipmapMode              = VK_SAMPLER_MIPMAP_MODE_NEAREST;
1798     samplerInfo.addressModeU            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1799     samplerInfo.addressModeV            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1800     samplerInfo.addressModeW            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1801     samplerInfo.mipLodBias              = 0.0f;
1802     samplerInfo.anisotropyEnable        = VK_FALSE;
1803     samplerInfo.maxAnisotropy           = 1;
1804     samplerInfo.compareEnable           = VK_FALSE;
1805     samplerInfo.compareOp               = VK_COMPARE_OP_ALWAYS;
1806     samplerInfo.minLod                  = 0;
1807     samplerInfo.maxLod                  = 0;
1808     samplerInfo.borderColor             = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
1809     samplerInfo.unnormalizedCoordinates = VK_FALSE;
1810 
1811     if (!mPointSampler.valid())
1812     {
1813         ANGLE_VK_TRY(contextVk, mPointSampler.init(contextVk->getDevice(), samplerInfo));
1814     }
1815 
1816     samplerInfo.magFilter = VK_FILTER_LINEAR;
1817     samplerInfo.minFilter = VK_FILTER_LINEAR;
1818 
1819     if (!mLinearSampler.valid())
1820     {
1821         ANGLE_VK_TRY(contextVk, mLinearSampler.init(contextVk->getDevice(), samplerInfo));
1822     }
1823 
1824     return angle::Result::Continue;
1825 }
1826 
ensureGenerateFragmentShadingRateResourcesInitialized(ContextVk * contextVk)1827 angle::Result UtilsVk::ensureGenerateFragmentShadingRateResourcesInitialized(ContextVk *contextVk)
1828 {
1829     if (mGenerateFragmentShadingRateAttachment.program.valid(gl::ShaderType::Compute))
1830     {
1831         return angle::Result::Continue;
1832     }
1833 
1834     VkDescriptorPoolSize setSizes[1] = {
1835         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
1836     };
1837 
1838     return ensureResourcesInitialized(contextVk, Function::GenerateFragmentShadingRate, setSizes,
1839                                       ArraySize(setSizes),
1840                                       sizeof(GenerateFragmentShadingRateParameters));
1841 }
1842 
setupComputeProgram(ContextVk * contextVk,Function function,const vk::ShaderModulePtr & csShader,ComputeShaderProgramAndPipelines * programAndPipelines,const VkDescriptorSet descriptorSet,const void * pushConstants,size_t pushConstantsSize,vk::OutsideRenderPassCommandBufferHelper * commandBufferHelper)1843 angle::Result UtilsVk::setupComputeProgram(
1844     ContextVk *contextVk,
1845     Function function,
1846     const vk::ShaderModulePtr &csShader,
1847     ComputeShaderProgramAndPipelines *programAndPipelines,
1848     const VkDescriptorSet descriptorSet,
1849     const void *pushConstants,
1850     size_t pushConstantsSize,
1851     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper)
1852 {
1853     vk::Renderer *renderer = contextVk->getRenderer();
1854 
1855     ASSERT(function >= Function::ComputeStartIndex);
1856 
1857     const vk::PipelineLayoutPtr &pipelineLayout = mPipelineLayouts[function];
1858 
1859     if (!programAndPipelines->program.valid(gl::ShaderType::Compute))
1860     {
1861         programAndPipelines->program.setShader(gl::ShaderType::Compute, csShader);
1862     }
1863 
1864     vk::PipelineHelper *pipeline;
1865     vk::PipelineCacheAccess pipelineCache;
1866     ANGLE_TRY(renderer->getPipelineCache(contextVk, &pipelineCache));
1867     ANGLE_TRY(programAndPipelines->program.getOrCreateComputePipeline(
1868         contextVk, &programAndPipelines->pipelines, &pipelineCache, *pipelineLayout,
1869         vk::GetComputePipelineOptions(contextVk->pipelineRobustness(),
1870                                       contextVk->pipelineProtectedAccess()),
1871         PipelineSource::Utils, &pipeline, nullptr, nullptr));
1872     commandBufferHelper->retainResource(pipeline);
1873 
1874     vk::OutsideRenderPassCommandBuffer *commandBuffer = &commandBufferHelper->getCommandBuffer();
1875     commandBuffer->bindComputePipeline(pipeline->getPipeline());
1876 
1877     contextVk->invalidateComputePipelineBinding();
1878 
1879     if (descriptorSet != VK_NULL_HANDLE)
1880     {
1881         commandBuffer->bindDescriptorSets(*pipelineLayout, VK_PIPELINE_BIND_POINT_COMPUTE,
1882                                           DescriptorSetIndex::Internal, 1, &descriptorSet, 0,
1883                                           nullptr);
1884         contextVk->invalidateComputeDescriptorSet(DescriptorSetIndex::Internal);
1885     }
1886 
1887     if (pushConstants)
1888     {
1889         commandBuffer->pushConstants(*pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
1890                                      static_cast<uint32_t>(pushConstantsSize), pushConstants);
1891     }
1892 
1893     return angle::Result::Continue;
1894 }
1895 
setupGraphicsProgramWithLayout(ContextVk * contextVk,const vk::PipelineLayout & pipelineLayout,const vk::ShaderModulePtr & vsShader,const vk::ShaderModulePtr & fsShader,GraphicsShaderProgramAndPipelines * programAndPipelines,const vk::GraphicsPipelineDesc * pipelineDesc,const VkDescriptorSet descriptorSet,const void * pushConstants,size_t pushConstantsSize,vk::RenderPassCommandBuffer * commandBuffer)1896 angle::Result UtilsVk::setupGraphicsProgramWithLayout(
1897     ContextVk *contextVk,
1898     const vk::PipelineLayout &pipelineLayout,
1899     const vk::ShaderModulePtr &vsShader,
1900     const vk::ShaderModulePtr &fsShader,
1901     GraphicsShaderProgramAndPipelines *programAndPipelines,
1902     const vk::GraphicsPipelineDesc *pipelineDesc,
1903     const VkDescriptorSet descriptorSet,
1904     const void *pushConstants,
1905     size_t pushConstantsSize,
1906     vk::RenderPassCommandBuffer *commandBuffer)
1907 {
1908     vk::Renderer *renderer = contextVk->getRenderer();
1909 
1910     if (!programAndPipelines->program.valid(gl::ShaderType::Vertex))
1911     {
1912         programAndPipelines->program.setShader(gl::ShaderType::Vertex, vsShader);
1913         if (fsShader)
1914         {
1915             programAndPipelines->program.setShader(gl::ShaderType::Fragment, fsShader);
1916         }
1917     }
1918 
1919     // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
1920     vk::PipelineCacheAccess pipelineCache;
1921     ANGLE_TRY(renderer->getPipelineCache(contextVk, &pipelineCache));
1922 
1923     // Pull in a compatible RenderPass.
1924     const vk::RenderPass *compatibleRenderPass = nullptr;
1925     ANGLE_TRY(contextVk->getCompatibleRenderPass(pipelineDesc->getRenderPassDesc(),
1926                                                  &compatibleRenderPass));
1927 
1928     const vk::GraphicsPipelineDesc *descPtr;
1929     vk::PipelineHelper *helper;
1930 
1931     if (!programAndPipelines->pipelines.getPipeline(*pipelineDesc, &descPtr, &helper))
1932     {
1933         ANGLE_TRY(programAndPipelines->program.createGraphicsPipeline(
1934             contextVk, &programAndPipelines->pipelines, &pipelineCache, *compatibleRenderPass,
1935             pipelineLayout, PipelineSource::Utils, *pipelineDesc, {}, &descPtr, &helper));
1936     }
1937 
1938     contextVk->getStartedRenderPassCommands().retainResource(helper);
1939     commandBuffer->bindGraphicsPipeline(helper->getPipeline());
1940 
1941     contextVk->invalidateGraphicsPipelineBinding();
1942 
1943     if (descriptorSet != VK_NULL_HANDLE)
1944     {
1945         commandBuffer->bindDescriptorSets(pipelineLayout, VK_PIPELINE_BIND_POINT_GRAPHICS,
1946                                           DescriptorSetIndex::Internal, 1, &descriptorSet, 0,
1947                                           nullptr);
1948         contextVk->invalidateGraphicsDescriptorSet(DescriptorSetIndex::Internal);
1949     }
1950 
1951     if (pushConstants)
1952     {
1953         commandBuffer->pushConstants(pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0,
1954                                      static_cast<uint32_t>(pushConstantsSize), pushConstants);
1955     }
1956 
1957     ResetDynamicState(contextVk, commandBuffer);
1958 
1959     return angle::Result::Continue;
1960 }
1961 
setupGraphicsProgram(ContextVk * contextVk,Function function,const vk::ShaderModulePtr & vsShader,const vk::ShaderModulePtr & fsShader,GraphicsShaderProgramAndPipelines * programAndPipelines,const vk::GraphicsPipelineDesc * pipelineDesc,const VkDescriptorSet descriptorSet,const void * pushConstants,size_t pushConstantsSize,vk::RenderPassCommandBuffer * commandBuffer)1962 angle::Result UtilsVk::setupGraphicsProgram(ContextVk *contextVk,
1963                                             Function function,
1964                                             const vk::ShaderModulePtr &vsShader,
1965                                             const vk::ShaderModulePtr &fsShader,
1966                                             GraphicsShaderProgramAndPipelines *programAndPipelines,
1967                                             const vk::GraphicsPipelineDesc *pipelineDesc,
1968                                             const VkDescriptorSet descriptorSet,
1969                                             const void *pushConstants,
1970                                             size_t pushConstantsSize,
1971                                             vk::RenderPassCommandBuffer *commandBuffer)
1972 {
1973     ASSERT(function < Function::ComputeStartIndex);
1974 
1975     return setupGraphicsProgramWithLayout(
1976         contextVk, *mPipelineLayouts[function], vsShader, fsShader, programAndPipelines,
1977         pipelineDesc, descriptorSet, pushConstants, pushConstantsSize, commandBuffer);
1978 }
1979 
convertIndexBuffer(ContextVk * contextVk,vk::BufferHelper * dst,vk::BufferHelper * src,const ConvertIndexParameters & params)1980 angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
1981                                           vk::BufferHelper *dst,
1982                                           vk::BufferHelper *src,
1983                                           const ConvertIndexParameters &params)
1984 {
1985     ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk));
1986 
1987     vk::CommandBufferAccess access;
1988     access.onBufferComputeShaderRead(src);
1989     access.onBufferComputeShaderWrite(dst);
1990 
1991     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
1992     vk::OutsideRenderPassCommandBuffer *commandBuffer;
1993     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
1994     commandBuffer = &commandBufferHelper->getCommandBuffer();
1995 
1996     VkDescriptorSet descriptorSet;
1997     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::ConvertIndexBuffer,
1998                                     &descriptorSet));
1999 
2000     std::array<VkDescriptorBufferInfo, 2> buffers = {{
2001         {dst->getBuffer().getHandle(), dst->getOffset(), dst->getSize()},
2002         {src->getBuffer().getHandle(), src->getOffset(), src->getSize()},
2003     }};
2004 
2005     VkWriteDescriptorSet writeInfo = {};
2006     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2007     writeInfo.dstSet               = descriptorSet;
2008     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
2009     writeInfo.descriptorCount      = 2;
2010     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2011     writeInfo.pBufferInfo          = buffers.data();
2012 
2013     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2014 
2015     ConvertIndexShaderParams shaderParams = {params.srcOffset, params.dstOffset >> 2,
2016                                              params.maxIndex, 0};
2017 
2018     uint32_t flags = 0;
2019     if (contextVk->getState().isPrimitiveRestartEnabled())
2020     {
2021         flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
2022     }
2023 
2024     vk::ShaderModulePtr shader;
2025     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
2026 
2027     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexBuffer, shader,
2028                                   &mConvertIndex[flags], descriptorSet, &shaderParams,
2029                                   sizeof(ConvertIndexShaderParams), commandBufferHelper));
2030 
2031     constexpr uint32_t kInvocationsPerGroup = 64;
2032     constexpr uint32_t kInvocationsPerIndex = 2;
2033     const uint32_t kIndexCount              = params.maxIndex;
2034     const uint32_t kGroupCount =
2035         UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
2036     commandBuffer->dispatch(kGroupCount, 1, 1);
2037 
2038     return angle::Result::Continue;
2039 }
2040 
convertIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuf,vk::BufferHelper * srcIndexBuf,vk::BufferHelper * dstIndirectBuf,vk::BufferHelper * dstIndexBuf,const ConvertIndexIndirectParameters & params)2041 angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
2042                                                   vk::BufferHelper *srcIndirectBuf,
2043                                                   vk::BufferHelper *srcIndexBuf,
2044                                                   vk::BufferHelper *dstIndirectBuf,
2045                                                   vk::BufferHelper *dstIndexBuf,
2046                                                   const ConvertIndexIndirectParameters &params)
2047 {
2048     ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk));
2049 
2050     vk::CommandBufferAccess access;
2051     access.onBufferComputeShaderRead(srcIndirectBuf);
2052     access.onBufferComputeShaderRead(srcIndexBuf);
2053     access.onBufferComputeShaderWrite(dstIndirectBuf);
2054     access.onBufferComputeShaderWrite(dstIndexBuf);
2055 
2056     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2057     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2058     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2059     commandBuffer = &commandBufferHelper->getCommandBuffer();
2060 
2061     VkDescriptorSet descriptorSet;
2062     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
2063                                     Function::ConvertIndexIndirectBuffer, &descriptorSet));
2064 
2065     std::array<VkDescriptorBufferInfo, 4> buffers = {{
2066         {dstIndexBuf->getBuffer().getHandle(), dstIndexBuf->getOffset(), dstIndexBuf->getSize()},
2067         {srcIndexBuf->getBuffer().getHandle(), srcIndexBuf->getOffset(), srcIndexBuf->getSize()},
2068         {srcIndirectBuf->getBuffer().getHandle(), srcIndirectBuf->getOffset(),
2069          srcIndirectBuf->getSize()},
2070         {dstIndirectBuf->getBuffer().getHandle(), dstIndirectBuf->getOffset(),
2071          dstIndirectBuf->getSize()},
2072     }};
2073 
2074     VkWriteDescriptorSet writeInfo = {};
2075     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2076     writeInfo.dstSet               = descriptorSet;
2077     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
2078     writeInfo.descriptorCount      = 4;
2079     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2080     writeInfo.pBufferInfo          = buffers.data();
2081 
2082     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2083 
2084     ConvertIndexIndirectShaderParams shaderParams = {
2085         params.srcIndirectBufOffset >> 2, params.srcIndexBufOffset, params.dstIndexBufOffset >> 2,
2086         params.maxIndex, params.dstIndirectBufOffset >> 2};
2087 
2088     uint32_t flags = vk::InternalShader::ConvertIndex_comp::kIsIndirect;
2089     if (contextVk->getState().isPrimitiveRestartEnabled())
2090     {
2091         flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
2092     }
2093 
2094     vk::ShaderModulePtr shader;
2095     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
2096 
2097     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader,
2098                                   &mConvertIndex[flags], descriptorSet, &shaderParams,
2099                                   sizeof(ConvertIndexIndirectShaderParams), commandBufferHelper));
2100 
2101     constexpr uint32_t kInvocationsPerGroup = 64;
2102     constexpr uint32_t kInvocationsPerIndex = 2;
2103     const uint32_t kIndexCount              = params.maxIndex;
2104     const uint32_t kGroupCount =
2105         UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
2106     commandBuffer->dispatch(kGroupCount, 1, 1);
2107 
2108     return angle::Result::Continue;
2109 }
2110 
convertLineLoopIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * srcIndexBuffer,vk::BufferHelper * dstIndirectBuffer,vk::BufferHelper * dstIndexBuffer,const ConvertLineLoopIndexIndirectParameters & params)2111 angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
2112     ContextVk *contextVk,
2113     vk::BufferHelper *srcIndirectBuffer,
2114     vk::BufferHelper *srcIndexBuffer,
2115     vk::BufferHelper *dstIndirectBuffer,
2116     vk::BufferHelper *dstIndexBuffer,
2117     const ConvertLineLoopIndexIndirectParameters &params)
2118 {
2119     ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk));
2120 
2121     vk::CommandBufferAccess access;
2122     access.onBufferComputeShaderRead(srcIndirectBuffer);
2123     access.onBufferComputeShaderRead(srcIndexBuffer);
2124     access.onBufferComputeShaderWrite(dstIndirectBuffer);
2125     access.onBufferComputeShaderWrite(dstIndexBuffer);
2126 
2127     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2128     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2129     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2130     commandBuffer = &commandBufferHelper->getCommandBuffer();
2131 
2132     VkDescriptorSet descriptorSet;
2133     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
2134                                     Function::ConvertIndexIndirectLineLoopBuffer, &descriptorSet));
2135 
2136     std::array<VkDescriptorBufferInfo, 4> buffers = {{
2137         {dstIndexBuffer->getBuffer().getHandle(), dstIndexBuffer->getOffset(),
2138          dstIndexBuffer->getSize()},
2139         {srcIndexBuffer->getBuffer().getHandle(), srcIndexBuffer->getOffset(),
2140          srcIndexBuffer->getSize()},
2141         {srcIndirectBuffer->getBuffer().getHandle(), srcIndirectBuffer->getOffset(),
2142          srcIndirectBuffer->getSize()},
2143         {dstIndirectBuffer->getBuffer().getHandle(), dstIndirectBuffer->getOffset(),
2144          dstIndirectBuffer->getSize()},
2145     }};
2146 
2147     VkWriteDescriptorSet writeInfo = {};
2148     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2149     writeInfo.dstSet               = descriptorSet;
2150     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
2151     writeInfo.descriptorCount      = 4;
2152     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2153     writeInfo.pBufferInfo          = buffers.data();
2154 
2155     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2156 
2157     ConvertIndexIndirectLineLoopShaderParams shaderParams = {
2158         params.indirectBufferOffset >> 2, params.dstIndirectBufferOffset >> 2,
2159         params.srcIndexBufferOffset, params.dstIndexBufferOffset >> 2,
2160         contextVk->getState().isPrimitiveRestartEnabled()};
2161 
2162     uint32_t flags = GetConvertIndexIndirectLineLoopFlag(params.indicesBitsWidth);
2163 
2164     vk::ShaderModulePtr shader;
2165     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndexIndirectLineLoop_comp(contextVk, flags,
2166                                                                                  &shader));
2167 
2168     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader,
2169                                   &mConvertIndexIndirectLineLoop[flags], descriptorSet,
2170                                   &shaderParams, sizeof(ConvertIndexIndirectLineLoopShaderParams),
2171                                   commandBufferHelper));
2172 
2173     commandBuffer->dispatch(1, 1, 1);
2174 
2175     return angle::Result::Continue;
2176 }
2177 
convertLineLoopArrayIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * dstIndirectBuffer,vk::BufferHelper * dstIndexBuffer,const ConvertLineLoopArrayIndirectParameters & params)2178 angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer(
2179     ContextVk *contextVk,
2180     vk::BufferHelper *srcIndirectBuffer,
2181     vk::BufferHelper *dstIndirectBuffer,
2182     vk::BufferHelper *dstIndexBuffer,
2183     const ConvertLineLoopArrayIndirectParameters &params)
2184 {
2185     ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk));
2186 
2187     vk::CommandBufferAccess access;
2188     access.onBufferComputeShaderRead(srcIndirectBuffer);
2189     access.onBufferComputeShaderWrite(dstIndirectBuffer);
2190     access.onBufferComputeShaderWrite(dstIndexBuffer);
2191 
2192     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2193     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2194     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2195     commandBuffer = &commandBufferHelper->getCommandBuffer();
2196 
2197     VkDescriptorSet descriptorSet;
2198     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
2199                                     Function::ConvertIndirectLineLoopBuffer, &descriptorSet));
2200 
2201     std::array<VkDescriptorBufferInfo, 3> buffers = {{
2202         {srcIndirectBuffer->getBuffer().getHandle(), srcIndirectBuffer->getOffset(),
2203          srcIndirectBuffer->getSize()},
2204         {dstIndirectBuffer->getBuffer().getHandle(), dstIndirectBuffer->getOffset(),
2205          dstIndirectBuffer->getSize()},
2206         {dstIndexBuffer->getBuffer().getHandle(), dstIndexBuffer->getOffset(),
2207          dstIndexBuffer->getSize()},
2208     }};
2209 
2210     VkWriteDescriptorSet writeInfo = {};
2211     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2212     writeInfo.dstSet               = descriptorSet;
2213     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
2214     writeInfo.descriptorCount      = 3;
2215     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2216     writeInfo.pBufferInfo          = buffers.data();
2217 
2218     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2219 
2220     ConvertIndirectLineLoopShaderParams shaderParams = {params.indirectBufferOffset >> 2,
2221                                                         params.dstIndirectBufferOffset >> 2,
2222                                                         params.dstIndexBufferOffset >> 2};
2223 
2224     uint32_t flags = 0;
2225 
2226     vk::ShaderModulePtr shader;
2227     ANGLE_TRY(
2228         contextVk->getShaderLibrary().getConvertIndirectLineLoop_comp(contextVk, flags, &shader));
2229 
2230     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndirectLineLoopBuffer, shader,
2231                                   &mConvertIndirectLineLoop[flags], descriptorSet, &shaderParams,
2232                                   sizeof(ConvertIndirectLineLoopShaderParams),
2233                                   commandBufferHelper));
2234 
2235     commandBuffer->dispatch(1, 1, 1);
2236 
2237     return angle::Result::Continue;
2238 }
2239 
2240 // Used to clear a layer of a renderable texture in part or whole (EXT_clear_texture).
clearTexture(ContextVk * contextVk,vk::ImageHelper * dst,ClearTextureParameters & params)2241 angle::Result UtilsVk::clearTexture(ContextVk *contextVk,
2242                                     vk::ImageHelper *dst,
2243                                     ClearTextureParameters &params)
2244 {
2245     const angle::Format &dstActualFormat = dst->getActualFormat();
2246     bool isDepthOrStencil                = dstActualFormat.hasDepthOrStencilBits();
2247     bool isFormatDS                      = dstActualFormat.hasDepthAndStencilBits();
2248 
2249     vk::DeviceScoped<vk::ImageView> destView(contextVk->getDevice());
2250     const gl::TextureType destViewType = vk::Get2DTextureType(1, dst->getSamples());
2251 
2252     ANGLE_TRY(dst->initLayerImageView(contextVk, destViewType, params.aspectFlags,
2253                                       gl::SwizzleState(), &destView.get(), params.level, 1,
2254                                       params.layer, 1));
2255 
2256     gl::Rectangle renderArea = {};
2257     renderArea.x             = params.clearArea.x;
2258     renderArea.y             = params.clearArea.y;
2259     renderArea.width         = params.clearArea.width;
2260     renderArea.height        = params.clearArea.height;
2261 
2262     vk::RenderPassDesc renderPassDesc;
2263     renderPassDesc.setSamples(dst->getSamples());
2264 
2265     if (!isDepthOrStencil)
2266     {
2267         renderPassDesc.packColorAttachment(0, dstActualFormat.id);
2268     }
2269     else
2270     {
2271         renderPassDesc.packDepthStencilAttachment(dstActualFormat.id);
2272     }
2273     vk::RenderPassCommandBuffer *commandBuffer;
2274     vk::ImageLayout imageLayout =
2275         isDepthOrStencil ? vk::ImageLayout::DepthWriteStencilWrite : vk::ImageLayout::ColorWrite;
2276 
2277     ANGLE_TRY(startRenderPass(contextVk, dst, &destView.get(), renderPassDesc, renderArea,
2278                               params.aspectFlags, &params.clearValue,
2279                               vk::RenderPassSource::InternalUtils, &commandBuffer));
2280 
2281     // If the format contains both depth and stencil, the barrier aspect mask for the image should
2282     // include both bits.
2283     contextVk->onImageRenderPassWrite(
2284         dst->toGLLevel(params.level), params.layer, 1,
2285         isFormatDS ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : params.aspectFlags,
2286         imageLayout, dst);
2287 
2288     vk::ImageView destViewObject = destView.release();
2289     contextVk->addGarbage(&destViewObject);
2290 
2291     // Close the render pass for this temporary framebuffer. If the render pass is not immediately
2292     // closed and the render area grows due to scissor change, the clear area unexpectedly changes.
2293     // This can be avoided if the scissor code takes LOAD_OP_CLEAR into account before deciding to
2294     // grow the render pass's render area.
2295     return contextVk->flushCommandsAndEndRenderPass(
2296         RenderPassClosureReason::TemporaryForClearTexture);
2297 }
2298 
convertVertexBuffer(ContextVk * contextVk,vk::BufferHelper * dst,vk::BufferHelper * src,const ConvertVertexParameters & params,const OffsetAndVertexCounts & additionalOffsetVertexCounts)2299 angle::Result UtilsVk::convertVertexBuffer(
2300     ContextVk *contextVk,
2301     vk::BufferHelper *dst,
2302     vk::BufferHelper *src,
2303     const ConvertVertexParameters &params,
2304     const OffsetAndVertexCounts &additionalOffsetVertexCounts)
2305 {
2306     vk::CommandBufferAccess access;
2307     access.onBufferComputeShaderRead(src);
2308     access.onBufferComputeShaderWrite(dst);
2309 
2310     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2311     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2312 
2313     ConvertVertexShaderParams shaderParams;
2314     shaderParams.Ns = params.srcFormat->channelCount;
2315     shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount;
2316     shaderParams.Ss = static_cast<uint32_t>(params.srcStride);
2317     shaderParams.Nd = params.dstFormat->channelCount;
2318     shaderParams.Bd = params.dstFormat->pixelBytes / params.dstFormat->channelCount;
2319     shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
2320     // The component size is expected to either be 1, 2 or 4 bytes.
2321     ASSERT(4 % shaderParams.Bs == 0);
2322     ASSERT(4 % shaderParams.Bd == 0);
2323     shaderParams.Es = 4 / shaderParams.Bs;
2324     shaderParams.Ed = 4 / shaderParams.Bd;
2325     // Total number of output components is simply the number of vertices by number of components in
2326     // each.
2327     shaderParams.componentCount = static_cast<uint32_t>(params.vertexCount * shaderParams.Nd);
2328     // Total number of 4-byte outputs is the number of components divided by how many components can
2329     // fit in a 4-byte value.  Note that this value is also the invocation size of the shader.
2330     shaderParams.outputCount = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
2331     shaderParams.srcOffset   = static_cast<uint32_t>(params.srcOffset);
2332     shaderParams.dstOffset   = static_cast<uint32_t>(params.dstOffset);
2333 
2334     bool isSrcA2BGR10 =
2335         params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt2101010 ||
2336         params.srcFormat->vertexAttribType == gl::VertexAttribType::Int2101010;
2337     bool isSrcRGB10A2 =
2338         params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt1010102 ||
2339         params.srcFormat->vertexAttribType == gl::VertexAttribType::Int1010102;
2340 
2341     shaderParams.isSrcHDR     = isSrcA2BGR10 || isSrcRGB10A2;
2342     shaderParams.isSrcA2BGR10 = isSrcA2BGR10;
2343 
2344     uint32_t flags = GetConvertVertexFlags(params);
2345 
2346     // See GLES3.0 section 2.9.1 Transferring Array Elements
2347     const uint32_t srcValueBits = shaderParams.isSrcHDR ? 2 : shaderParams.Bs * 8;
2348     const uint32_t srcValueMask =
2349         srcValueBits == 32 ? 0xFFFFFFFFu : angle::BitMask<uint32_t>(srcValueBits);
2350     switch (flags)
2351     {
2352         case ConvertVertex_comp::kSintToSint:
2353         case ConvertVertex_comp::kSintToFloat:
2354         case ConvertVertex_comp::kUintToFloat:
2355             // For integers, alpha should take a value of 1.
2356             shaderParams.srcEmulatedAlpha = 1;
2357             break;
2358 
2359         case ConvertVertex_comp::kUintToUint:
2360             // For integers, alpha should take a value of 1.  However, uint->uint is also used to
2361             // add channels to RGB snorm, unorm and half formats.
2362             if (params.dstFormat->isSnorm())
2363             {
2364                 // See case ConvertVertex_comp::kSnormToFloat below.
2365                 shaderParams.srcEmulatedAlpha = srcValueMask >> 1;
2366             }
2367             else if (params.dstFormat->isUnorm())
2368             {
2369                 // See case ConvertVertex_comp::kUnormToFloat below.
2370                 shaderParams.srcEmulatedAlpha = srcValueMask;
2371             }
2372             else if (params.dstFormat->isVertexTypeHalfFloat())
2373             {
2374                 shaderParams.srcEmulatedAlpha = gl::Float16One;
2375             }
2376             else
2377             {
2378                 shaderParams.srcEmulatedAlpha = 1;
2379             }
2380             break;
2381 
2382         case ConvertVertex_comp::kSnormToFloat:
2383             // The largest signed number with as many bits as the alpha channel of the source is
2384             // 0b011...1 which is srcValueMask >> 1
2385             shaderParams.srcEmulatedAlpha = srcValueMask >> 1;
2386             break;
2387 
2388         case ConvertVertex_comp::kUnormToFloat:
2389             // The largest unsigned number with as many bits as the alpha channel of the source is
2390             // 0b11...1 which is srcValueMask
2391             shaderParams.srcEmulatedAlpha = srcValueMask;
2392             break;
2393 
2394         case ConvertVertex_comp::kFixedToFloat:
2395             // 1.0 in fixed point is 0x10000
2396             shaderParams.srcEmulatedAlpha = 0x10000;
2397             break;
2398 
2399         case ConvertVertex_comp::kFloatToFloat:
2400             ASSERT(ValidateFloatOneAsUint());
2401             shaderParams.srcEmulatedAlpha = gl::Float32One;
2402             break;
2403 
2404         default:
2405             UNREACHABLE();
2406     }
2407 
2408     return convertVertexBufferImpl(contextVk, dst, src, flags, commandBufferHelper, shaderParams,
2409                                    additionalOffsetVertexCounts);
2410 }
2411 
convertVertexBufferImpl(ContextVk * contextVk,vk::BufferHelper * dst,vk::BufferHelper * src,uint32_t flags,vk::OutsideRenderPassCommandBufferHelper * commandBufferHelper,const ConvertVertexShaderParams & shaderParams,const OffsetAndVertexCounts & additionalOffsetVertexCounts)2412 angle::Result UtilsVk::convertVertexBufferImpl(
2413     ContextVk *contextVk,
2414     vk::BufferHelper *dst,
2415     vk::BufferHelper *src,
2416     uint32_t flags,
2417     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper,
2418     const ConvertVertexShaderParams &shaderParams,
2419     const OffsetAndVertexCounts &additionalOffsetVertexCounts)
2420 {
2421     ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk));
2422 
2423     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2424     commandBuffer = &commandBufferHelper->getCommandBuffer();
2425 
2426     VkDescriptorSet descriptorSet;
2427     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::ConvertVertexBuffer,
2428                                     &descriptorSet));
2429 
2430     // ConvertVertexBuffer writes whole 4 bytes to dstOffset. Caller must ensure dstOffset is
2431     // aligned on 4 bytes boundary.
2432     ASSERT(dst->getOffset() % 4 == 0);
2433 
2434     VkWriteDescriptorSet writeInfo    = {};
2435     VkDescriptorBufferInfo buffers[2] = {
2436         {dst->getBuffer().getHandle(), dst->getOffset(), dst->getSize()},
2437         {src->getBuffer().getHandle(), src->getOffset(), src->getSize()},
2438     };
2439     static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
2440                   "Update write info");
2441 
2442     writeInfo.sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2443     writeInfo.dstSet          = descriptorSet;
2444     writeInfo.dstBinding      = kConvertVertexDestinationBinding;
2445     writeInfo.descriptorCount = 2;
2446     writeInfo.descriptorType  = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2447     writeInfo.pBufferInfo     = buffers;
2448 
2449     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2450 
2451     vk::ShaderModulePtr shader;
2452     ANGLE_TRY(contextVk->getShaderLibrary().getConvertVertex_comp(contextVk, flags, &shader));
2453 
2454     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertVertexBuffer, shader,
2455                                   &mConvertVertex[flags], descriptorSet, &shaderParams,
2456                                   sizeof(shaderParams), commandBufferHelper));
2457 
2458     commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
2459 
2460     if (!additionalOffsetVertexCounts.empty())
2461     {
2462         ConvertVertexShaderParams constants = shaderParams;
2463 
2464         for (const OffsetAndVertexCount &offsetAndVertexCount : additionalOffsetVertexCounts)
2465         {
2466             // Total number of output components is simply the number of vertices by number of
2467             // components in each.
2468             constants.componentCount =
2469                 static_cast<uint32_t>(offsetAndVertexCount.vertexCount * shaderParams.Nd);
2470             // Total number of 4-byte outputs is the number of components divided by how many
2471             // components can fit in a 4-byte value.  Note that this value is also the invocation
2472             // size of the shader.
2473             constants.outputCount = UnsignedCeilDivide(constants.componentCount, shaderParams.Ed);
2474             constants.srcOffset   = static_cast<uint32_t>(offsetAndVertexCount.srcOffset);
2475             constants.dstOffset   = static_cast<uint32_t>(offsetAndVertexCount.dstOffset);
2476 
2477             commandBuffer->pushConstants(*mPipelineLayouts[Function::ConvertVertexBuffer],
2478                                          VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(constants),
2479                                          &constants);
2480             // Since multiple compute dispatch all convert from the same srcBuffer and write to the
2481             // same dstBuffer, even if the ranges overlap, they should end up with writing the same
2482             // values, thus no barrier is needed here.
2483             commandBuffer->dispatch(UnsignedCeilDivide(constants.outputCount, 64), 1, 1);
2484         }
2485     }
2486 
2487     return angle::Result::Continue;
2488 }
2489 
startRenderPass(ContextVk * contextVk,vk::ImageHelper * image,const vk::ImageView * imageView,const vk::RenderPassDesc & renderPassDesc,const gl::Rectangle & renderArea,const VkImageAspectFlags aspectFlags,const VkClearValue * clearValue,vk::RenderPassSource renderPassSource,vk::RenderPassCommandBuffer ** commandBufferOut)2490 angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
2491                                        vk::ImageHelper *image,
2492                                        const vk::ImageView *imageView,
2493                                        const vk::RenderPassDesc &renderPassDesc,
2494                                        const gl::Rectangle &renderArea,
2495                                        const VkImageAspectFlags aspectFlags,
2496                                        const VkClearValue *clearValue,
2497                                        vk::RenderPassSource renderPassSource,
2498                                        vk::RenderPassCommandBuffer **commandBufferOut)
2499 {
2500     ASSERT(aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT ||
2501            (aspectFlags & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0);
2502     vk::ImageLayout imageLayout = aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT
2503                                       ? vk::ImageLayout::ColorWrite
2504                                       : vk::ImageLayout::DepthWriteStencilWrite;
2505     vk::Framebuffer framebuffer;
2506     vk::Framebuffer framebufferHandle;
2507     vk::RenderPassFramebuffer renderPassFramebuffer;
2508 
2509     const uint32_t framebufferWidth    = renderArea.x + renderArea.width;
2510     const uint32_t framebufferHeight   = renderArea.y + renderArea.height;
2511     const uint32_t framebufferLayers   = 1;
2512     vk::ImagelessFramebuffer imageless = vk::ImagelessFramebuffer::Yes;
2513 
2514     if (!contextVk->getFeatures().preferDynamicRendering.enabled)
2515     {
2516         imageless = vk::ImagelessFramebuffer::No;
2517 
2518         const vk::RenderPass *compatibleRenderPass = nullptr;
2519         ANGLE_TRY(contextVk->getCompatibleRenderPass(renderPassDesc, &compatibleRenderPass));
2520 
2521         VkFramebufferCreateInfo framebufferInfo = {};
2522 
2523         // Minimize the framebuffer coverage to only cover up to the render area.
2524         framebufferInfo.sType           = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2525         framebufferInfo.flags           = 0;
2526         framebufferInfo.renderPass      = compatibleRenderPass->getHandle();
2527         framebufferInfo.attachmentCount = 1;
2528         framebufferInfo.pAttachments    = imageView->ptr();
2529         framebufferInfo.width           = framebufferWidth;
2530         framebufferInfo.height          = framebufferHeight;
2531         framebufferInfo.layers          = framebufferLayers;
2532 
2533         ANGLE_VK_TRY(contextVk, framebuffer.init(contextVk->getDevice(), framebufferInfo));
2534 
2535         framebufferHandle.setHandle(framebuffer.getHandle());
2536     }
2537 
2538     renderPassFramebuffer.setFramebuffer(
2539         contextVk, std::move(framebufferHandle), {imageView->getHandle()}, framebufferWidth,
2540         framebufferHeight, framebufferLayers, imageless, renderPassSource);
2541 
2542     // If a clear value has been provided, the load op is set to clear.
2543     vk::AttachmentOpsArray renderPassAttachmentOps;
2544     vk::PackedClearValuesArray clearValues;
2545     VkClearValue attachmentClearValue = {};
2546 
2547     if (clearValue == nullptr)
2548     {
2549         renderPassAttachmentOps.initWithLoadStore(vk::kAttachmentIndexZero, imageLayout,
2550                                                   imageLayout);
2551     }
2552     else
2553     {
2554         attachmentClearValue = *clearValue;
2555         renderPassAttachmentOps.setLayouts(vk::kAttachmentIndexZero, imageLayout, imageLayout);
2556         renderPassAttachmentOps.setClearOp(vk::kAttachmentIndexZero);
2557         renderPassAttachmentOps.setClearStencilOp(vk::kAttachmentIndexZero);
2558     }
2559 
2560     if (aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT)
2561     {
2562         clearValues.storeColor(vk::kAttachmentIndexZero, attachmentClearValue);
2563     }
2564     else
2565     {
2566         clearValues.storeDepthStencil(vk::kAttachmentIndexZero, attachmentClearValue);
2567     }
2568 
2569     ANGLE_TRY(contextVk->beginNewRenderPass(
2570         std::move(renderPassFramebuffer), renderArea, renderPassDesc, renderPassAttachmentOps,
2571         vk::PackedAttachmentCount(1), vk::kAttachmentIndexInvalid, clearValues, commandBufferOut));
2572 
2573     contextVk->addGarbage(&framebuffer);
2574 
2575     return angle::Result::Continue;
2576 }
2577 
clearFramebuffer(ContextVk * contextVk,FramebufferVk * framebuffer,const ClearFramebufferParameters & params)2578 angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
2579                                         FramebufferVk *framebuffer,
2580                                         const ClearFramebufferParameters &params)
2581 {
2582     vk::Renderer *renderer = contextVk->getRenderer();
2583 
2584     ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
2585 
2586     const gl::Rectangle &scissoredRenderArea = params.clearArea;
2587     vk::RenderPassCommandBuffer *commandBuffer;
2588 
2589     // Start a new render pass if not already started
2590     if (contextVk->hasActiveRenderPass() &&
2591         contextVk->hasStartedRenderPassWithQueueSerial(framebuffer->getLastRenderPassQueueSerial()))
2592     {
2593         vk::RenderPassCommandBufferHelper *renderPassCommands =
2594             &contextVk->getStartedRenderPassCommands();
2595         renderPassCommands->growRenderArea(contextVk, scissoredRenderArea);
2596 
2597         commandBuffer = &renderPassCommands->getCommandBuffer();
2598     }
2599     else
2600     {
2601         // Deferred clears should be handled already.
2602         ASSERT(!framebuffer->hasDeferredClears());
2603         ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer, nullptr));
2604     }
2605 
2606     UpdateColorAccess(contextVk, framebuffer->getState().getColorAttachmentsMask(),
2607                       MakeColorBufferMask(params.colorAttachmentIndexGL));
2608     UpdateDepthStencilAccess(contextVk, params.clearDepth, params.clearStencil);
2609 
2610     ImageClearShaderParams shaderParams;
2611     shaderParams.clearValue = params.colorClearValue;
2612     shaderParams.clearDepth = params.depthStencilClearValue.depth;
2613 
2614     vk::GraphicsPipelineDesc pipelineDesc;
2615     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
2616                               contextVk->pipelineRobustness(),
2617                               contextVk->pipelineProtectedAccess());
2618     pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
2619     pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags);
2620     pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
2621     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
2622     // Clears can be done on a currently open render pass, so make sure the correct subpass index is
2623     // used.
2624     pipelineDesc.setSubpass(contextVk->getCurrentSubpassIndex());
2625 
2626     // Clear depth by enabling depth clamping and setting the viewport depth range to the clear
2627     // value if possible.  Otherwise use the shader to export depth.
2628     const bool supportsDepthClamp = renderer->getPhysicalDeviceFeatures().depthClamp == VK_TRUE;
2629     if (params.clearDepth)
2630     {
2631         SetDepthStateForWrite(renderer, &pipelineDesc);
2632         if (supportsDepthClamp)
2633         {
2634             // Note: this path requires the depthClamp Vulkan feature.
2635             pipelineDesc.setDepthClampEnabled(true);
2636         }
2637     }
2638 
2639     // Clear stencil by enabling stencil write with the right mask.
2640     if (params.clearStencil)
2641     {
2642         SetStencilStateForWrite(renderer, &pipelineDesc);
2643     }
2644 
2645     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
2646     vk::ShaderModulePtr vertexShader;
2647     vk::ShaderModulePtr fragmentShader;
2648     GraphicsShaderProgramAndPipelines *imageClearProgramAndPipelines = &mImageClearVSOnly;
2649 
2650     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
2651     if (params.clearColor)
2652     {
2653         const uint32_t flags =
2654             GetImageClearFlags(*params.colorFormat, params.colorAttachmentIndexGL,
2655                                params.clearDepth && !supportsDepthClamp);
2656         ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
2657         imageClearProgramAndPipelines = &mImageClear[flags];
2658     }
2659 
2660     // Make sure transform feedback is paused.  Needs to be done before binding the pipeline as
2661     // that's not allowed in Vulkan.
2662     const bool isTransformFeedbackActiveUnpaused =
2663         contextVk->getStartedRenderPassCommands().isTransformFeedbackActiveUnpaused();
2664     contextVk->pauseTransformFeedbackIfActiveUnpaused();
2665 
2666     ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageClear, vertexShader, fragmentShader,
2667                                    imageClearProgramAndPipelines, &pipelineDesc, VK_NULL_HANDLE,
2668                                    &shaderParams, sizeof(shaderParams), commandBuffer));
2669 
2670     // Set dynamic state
2671     VkViewport viewport;
2672     gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
2673     bool invertViewport              = contextVk->isViewportFlipEnabledForDrawFBO();
2674     bool clipSpaceOriginUpperLeft =
2675         contextVk->getState().getClipOrigin() == gl::ClipOrigin::UpperLeft;
2676     // Set depth range to clear value.  If clearing depth, the vertex shader depth output is clamped
2677     // to this value, thus clearing the depth buffer to the desired clear value.
2678     const float clearDepthValue = params.depthStencilClearValue.depth;
2679     gl_vk::GetViewport(completeRenderArea, clearDepthValue, clearDepthValue, invertViewport,
2680                        clipSpaceOriginUpperLeft, completeRenderArea.height, &viewport);
2681     commandBuffer->setViewport(0, 1, &viewport);
2682 
2683     const VkRect2D scissor = gl_vk::GetRect(params.clearArea);
2684     commandBuffer->setScissor(0, 1, &scissor);
2685 
2686     if (params.clearDepth)
2687     {
2688         SetDepthDynamicStateForWrite(renderer, commandBuffer);
2689     }
2690     else
2691     {
2692         SetDepthDynamicStateForUnused(renderer, commandBuffer);
2693     }
2694 
2695     if (params.clearStencil)
2696     {
2697         constexpr uint8_t kCompareMask = 0xFF;
2698         const uint8_t clearStencilValue =
2699             static_cast<uint8_t>(params.depthStencilClearValue.stencil);
2700 
2701         commandBuffer->setStencilCompareMask(kCompareMask, kCompareMask);
2702         commandBuffer->setStencilWriteMask(params.stencilMask, params.stencilMask);
2703         commandBuffer->setStencilReference(clearStencilValue, clearStencilValue);
2704 
2705         SetStencilDynamicStateForWrite(renderer, commandBuffer);
2706     }
2707     else
2708     {
2709         SetStencilDynamicStateForUnused(renderer, commandBuffer);
2710     }
2711 
2712     ASSERT(contextVk->hasStartedRenderPassWithQueueSerial(
2713         framebuffer->getLastRenderPassQueueSerial()));
2714     // Make sure this draw call doesn't count towards occlusion query results.
2715     contextVk->pauseRenderPassQueriesIfActive();
2716     commandBuffer->draw(3, 0);
2717     ANGLE_TRY(contextVk->resumeRenderPassQueriesIfActive());
2718 
2719     // If transform feedback was active, we can't pause and resume it in the same render pass
2720     // because we can't insert a memory barrier for the counter buffers.  In that case, break the
2721     // render pass.
2722     if (isTransformFeedbackActiveUnpaused)
2723     {
2724         ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
2725             RenderPassClosureReason::XfbResumeAfterDrawBasedClear));
2726     }
2727 
2728     return angle::Result::Continue;
2729 }
2730 
clearImage(ContextVk * contextVk,vk::ImageHelper * dst,const ClearImageParameters & params)2731 angle::Result UtilsVk::clearImage(ContextVk *contextVk,
2732                                   vk::ImageHelper *dst,
2733                                   const ClearImageParameters &params)
2734 {
2735     vk::Renderer *renderer = contextVk->getRenderer();
2736 
2737     ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
2738 
2739     const angle::Format &dstActualFormat = dst->getActualFormat();
2740 
2741     // Currently, this function is only used to clear emulated channels of color images.
2742     ASSERT(!dstActualFormat.hasDepthOrStencilBits());
2743 
2744     // TODO: currently this function is only implemented for images that are drawable.  If needed,
2745     // for images that are not drawable, the following algorithm can be used.
2746     //
2747     // - Copy image to temp buffer
2748     // - Use convertVertexBufferImpl to overwrite the alpha channel
2749     // - Copy the result back to the image
2750     //
2751     // Note that the following check is not enough; if the image is AHB-imported, then the draw path
2752     // cannot be taken if AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER hasn't been specified, even if the
2753     // format is renderable.
2754     //
2755     // http://anglebug.com/42264676
2756     if (!vk::FormatHasNecessaryFeature(renderer, dstActualFormat.id, dst->getTilingMode(),
2757                                        VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
2758     {
2759         UNIMPLEMENTED();
2760         return angle::Result::Continue;
2761     }
2762 
2763     vk::DeviceScoped<vk::ImageView> destView(contextVk->getDevice());
2764     const gl::TextureType destViewType = vk::Get2DTextureType(1, dst->getSamples());
2765 
2766     ANGLE_TRY(dst->initLayerImageView(contextVk, destViewType, VK_IMAGE_ASPECT_COLOR_BIT,
2767                                       gl::SwizzleState(), &destView.get(), params.dstMip, 1,
2768                                       params.dstLayer, 1));
2769 
2770     const gl::Rectangle &renderArea = params.clearArea;
2771 
2772     ImageClearShaderParams shaderParams;
2773     shaderParams.clearValue = params.colorClearValue;
2774     shaderParams.clearDepth = 0;
2775 
2776     vk::RenderPassDesc renderPassDesc;
2777     renderPassDesc.setSamples(dst->getSamples());
2778     renderPassDesc.packColorAttachment(0, dstActualFormat.id);
2779 
2780     vk::GraphicsPipelineDesc pipelineDesc;
2781     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
2782                               contextVk->pipelineRobustness(),
2783                               contextVk->pipelineProtectedAccess());
2784     pipelineDesc.setSingleColorWriteMask(0, params.colorMaskFlags);
2785     pipelineDesc.setRasterizationSamples(dst->getSamples());
2786     pipelineDesc.setRenderPassDesc(renderPassDesc);
2787 
2788     vk::RenderPassCommandBuffer *commandBuffer;
2789     ANGLE_TRY(startRenderPass(contextVk, dst, &destView.get(), renderPassDesc, renderArea,
2790                               VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
2791                               vk::RenderPassSource::InternalUtils, &commandBuffer));
2792 
2793     UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
2794 
2795     contextVk->onImageRenderPassWrite(dst->toGLLevel(params.dstMip), params.dstLayer, 1,
2796                                       VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorWrite, dst);
2797 
2798     const uint32_t flags = GetImageClearFlags(dstActualFormat, 0, false);
2799 
2800     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
2801     vk::ShaderModulePtr vertexShader;
2802     vk::ShaderModulePtr fragmentShader;
2803     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
2804     ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
2805 
2806     ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageClear, vertexShader, fragmentShader,
2807                                    &mImageClear[flags], &pipelineDesc, VK_NULL_HANDLE,
2808                                    &shaderParams, sizeof(shaderParams), commandBuffer));
2809 
2810     // Set dynamic state
2811     VkViewport viewport;
2812     gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dst->getExtents().height, &viewport);
2813     commandBuffer->setViewport(0, 1, &viewport);
2814 
2815     VkRect2D scissor = gl_vk::GetRect(renderArea);
2816     commandBuffer->setScissor(0, 1, &scissor);
2817 
2818     SetDepthDynamicStateForUnused(renderer, commandBuffer);
2819     SetStencilDynamicStateForUnused(renderer, commandBuffer);
2820 
2821     // Note: this utility creates its own framebuffer, thus bypassing ContextVk::startRenderPass.
2822     // As such, occlusion queries are not enabled.
2823     commandBuffer->draw(3, 0);
2824 
2825     vk::ImageView destViewObject = destView.release();
2826     contextVk->addGarbage(&destViewObject);
2827 
2828     // Close the render pass for this temporary framebuffer.
2829     return contextVk->flushCommandsAndEndRenderPass(
2830         RenderPassClosureReason::TemporaryForImageClear);
2831 }
2832 
colorBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcView,const BlitResolveParameters & params)2833 angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk,
2834                                         FramebufferVk *framebuffer,
2835                                         vk::ImageHelper *src,
2836                                         const vk::ImageView *srcView,
2837                                         const BlitResolveParameters &params)
2838 {
2839     // The views passed to this function are already retained, so a render pass cannot be already
2840     // open.  Otherwise, this function closes the render pass, which may incur a vkQueueSubmit and
2841     // then the views are used in a new command buffer without having been retained for it.
2842     // http://crbug.com/1272266#c22
2843     //
2844     // Note that depth/stencil views for blit are not derived from a |Resource| class and are
2845     // retained differently.
2846     ASSERT(!contextVk->hasActiveRenderPass());
2847 
2848     return blitResolveImpl(contextVk, framebuffer, src, srcView, nullptr, nullptr, params);
2849 }
2850 
depthStencilBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)2851 angle::Result UtilsVk::depthStencilBlitResolve(ContextVk *contextVk,
2852                                                FramebufferVk *framebuffer,
2853                                                vk::ImageHelper *src,
2854                                                const vk::ImageView *srcDepthView,
2855                                                const vk::ImageView *srcStencilView,
2856                                                const BlitResolveParameters &params)
2857 {
2858     return blitResolveImpl(contextVk, framebuffer, src, nullptr, srcDepthView, srcStencilView,
2859                            params);
2860 }
2861 
blitResolveImpl(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcColorView,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)2862 angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
2863                                        FramebufferVk *framebuffer,
2864                                        vk::ImageHelper *src,
2865                                        const vk::ImageView *srcColorView,
2866                                        const vk::ImageView *srcDepthView,
2867                                        const vk::ImageView *srcStencilView,
2868                                        const BlitResolveParameters &params)
2869 {
2870     // Possible ways to resolve color are:
2871     //
2872     // - vkCmdResolveImage: This is by far the easiest method, but lacks the ability to flip
2873     //   images during resolve.
2874     // - Manual resolve: A shader can read all samples from input, average them and output.
2875     // - Using subpass resolve attachment: A shader can transform the sample colors from source to
2876     //   destination coordinates and the subpass resolve would finish the job.
2877     //
2878     // The first method is unable to handle flipping, so it's not generally applicable.  The last
2879     // method would have been great were we able to modify the last render pass that rendered into
2880     // source, but still wouldn't be able to handle flipping.  The second method is implemented in
2881     // this function for complete control.
2882 
2883     // Possible ways to resolve depth/stencil are:
2884     //
2885     // - Manual resolve: A shader can read a samples from input and choose that for output.
2886     // - Using subpass resolve attachment through VkSubpassDescriptionDepthStencilResolveKHR: This
2887     //   requires an extension that's not very well supported.
2888     //
2889     // The first method is implemented in this function.
2890 
2891     // Possible ways to blit color, depth or stencil are:
2892     //
2893     // - vkCmdBlitImage: This function works if the source and destination formats have the blit
2894     //   feature.
2895     // - Manual blit: A shader can sample from the source image and write it to the destination.
2896     //
2897     // The first method has a serious shortcoming.  GLES allows blit parameters to exceed the
2898     // source or destination boundaries.  The actual blit is clipped to these limits, but the
2899     // scaling applied is determined solely by the input areas.  Vulkan requires the blit parameters
2900     // to be within the source and destination bounds.  This makes it hard to keep the scaling
2901     // constant.
2902     //
2903     // The second method is implemented in this function, which shares code with the resolve method.
2904     vk::Renderer *renderer = contextVk->getRenderer();
2905 
2906     ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
2907 
2908     bool isResolve = src->getSamples() > 1;
2909 
2910     BlitResolveShaderParams shaderParams;
2911     // Note: adjustments made for pre-rotatation in FramebufferVk::blit() affect these
2912     // Calculate*Offset() functions.
2913     if (isResolve)
2914     {
2915         CalculateResolveOffset(params, shaderParams.offset.resolve);
2916     }
2917     else
2918     {
2919         CalculateBlitOffset(params, shaderParams.offset.blit);
2920     }
2921     shaderParams.stretch[0]      = params.stretch[0];
2922     shaderParams.stretch[1]      = params.stretch[1];
2923     shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
2924     shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
2925     shaderParams.srcLayer        = params.srcLayer;
2926     shaderParams.samples         = src->getSamples();
2927     shaderParams.invSamples      = 1.0f / shaderParams.samples;
2928     shaderParams.outputMask      = framebuffer->getState().getEnabledDrawBuffers().bits();
2929     shaderParams.flipX           = params.flipX;
2930     shaderParams.flipY           = params.flipY;
2931     shaderParams.rotateXY        = 0;
2932 
2933     // Potentially make adjustments for pre-rotation.  Depending on the angle some of the
2934     // shaderParams need to be adjusted.
2935     switch (params.rotation)
2936     {
2937         case SurfaceRotation::Identity:
2938         case SurfaceRotation::Rotated90Degrees:
2939             break;
2940         case SurfaceRotation::Rotated180Degrees:
2941         case SurfaceRotation::Rotated270Degrees:
2942             if (isResolve)
2943             {
2944                 // Align the offset with minus 1, or the sample position near the edge will be
2945                 // wrong.
2946                 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0] - 1;
2947                 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1] - 1;
2948             }
2949             else
2950             {
2951                 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0];
2952                 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1];
2953             }
2954             break;
2955         default:
2956             UNREACHABLE();
2957             break;
2958     }
2959 
2960     shaderParams.rotateXY = IsRotatedAspectRatio(params.rotation);
2961 
2962     bool blitColor   = srcColorView != nullptr;
2963     bool blitDepth   = srcDepthView != nullptr;
2964     bool blitStencil = srcStencilView != nullptr;
2965 
2966     // Either color is blitted/resolved or depth/stencil, but not both.
2967     ASSERT(blitColor != (blitDepth || blitStencil));
2968 
2969     // Linear sampling is only valid with color blitting.
2970     ASSERT((blitColor && !isResolve) || !params.linear);
2971 
2972     uint32_t flags =
2973         GetBlitResolveFlags(blitColor, blitDepth, blitStencil, src->getIntendedFormat());
2974     flags |= src->getLayerCount() > 1 ? BlitResolve_frag::kSrcIsArray : 0;
2975     flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
2976     Function function = Function::BlitResolve;
2977 
2978     // Note: a different shader is used for 3D color blits, but otherwise the desc sets, parameters
2979     // etc are identical.
2980     const bool isSrc3D = src->getType() == VK_IMAGE_TYPE_3D;
2981     ASSERT(!isSrc3D || (blitColor && !isResolve));
2982     if (isSrc3D)
2983     {
2984         flags = GetFormatFlags(src->getIntendedFormat(), Blit3DSrc_frag::kBlitInt,
2985                                Blit3DSrc_frag::kBlitUint, Blit3DSrc_frag::kBlitFloat);
2986     }
2987 
2988     vk::GraphicsPipelineDesc pipelineDesc;
2989     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
2990                               contextVk->pipelineRobustness(),
2991                               contextVk->pipelineProtectedAccess());
2992     if (blitColor)
2993     {
2994         constexpr VkColorComponentFlags kAllColorComponents =
2995             VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
2996             VK_COLOR_COMPONENT_A_BIT;
2997 
2998         pipelineDesc.setColorWriteMasks(
2999             gl::BlendStateExt::ColorMaskStorage::GetReplicatedValue(
3000                 kAllColorComponents, gl::BlendStateExt::ColorMaskStorage::GetMask(
3001                                          framebuffer->getRenderPassDesc().colorAttachmentRange())),
3002             framebuffer->getEmulatedAlphaAttachmentMask(), ~gl::DrawBufferMask());
3003     }
3004     else
3005     {
3006         pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
3007     }
3008     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
3009     if (blitDepth)
3010     {
3011         SetDepthStateForWrite(renderer, &pipelineDesc);
3012     }
3013 
3014     if (blitStencil)
3015     {
3016         SetStencilStateForWrite(renderer, &pipelineDesc);
3017     }
3018 
3019     // All deferred clear must have been flushed, otherwise it will conflict with params.blitArea.
3020     ASSERT(!framebuffer->hasDeferredClears());
3021     vk::RenderPassCommandBuffer *commandBuffer;
3022     ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer, nullptr));
3023 
3024     VkDescriptorSet descriptorSet;
3025     ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
3026                                     Function::BlitResolve, &descriptorSet));
3027 
3028     // Pick layout consistent with GetImageReadLayout() to avoid unnecessary layout change.
3029     vk::ImageLayout srcImagelayout = src->isDepthOrStencil()
3030                                          ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead
3031                                          : vk::ImageLayout::FragmentShaderReadOnly;
3032     contextVk->onImageRenderPassRead(src->getAspectFlags(), srcImagelayout, src);
3033 
3034     UpdateColorAccess(contextVk, framebuffer->getState().getColorAttachmentsMask(),
3035                       framebuffer->getState().getEnabledDrawBuffers());
3036     UpdateDepthStencilAccess(contextVk, blitDepth, blitStencil);
3037 
3038     VkDescriptorImageInfo imageInfos[2] = {};
3039 
3040     if (blitColor)
3041     {
3042         imageInfos[0].imageView   = srcColorView->getHandle();
3043         imageInfos[0].imageLayout = src->getCurrentLayout();
3044     }
3045     if (blitDepth)
3046     {
3047         imageInfos[0].imageView   = srcDepthView->getHandle();
3048         imageInfos[0].imageLayout = src->getCurrentLayout();
3049     }
3050     if (blitStencil)
3051     {
3052         imageInfos[1].imageView   = srcStencilView->getHandle();
3053         imageInfos[1].imageLayout = src->getCurrentLayout();
3054     }
3055 
3056     VkDescriptorImageInfo samplerInfo = {};
3057     samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
3058 
3059     VkWriteDescriptorSet writeInfos[3] = {};
3060     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3061     writeInfos[0].dstSet               = descriptorSet;
3062     writeInfos[0].dstBinding           = kBlitResolveColorOrDepthBinding;
3063     writeInfos[0].descriptorCount      = 1;
3064     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3065     writeInfos[0].pImageInfo           = &imageInfos[0];
3066 
3067     writeInfos[1]            = writeInfos[0];
3068     writeInfos[1].dstBinding = kBlitResolveStencilBinding;
3069     writeInfos[1].pImageInfo = &imageInfos[1];
3070 
3071     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3072     writeInfos[2].dstSet          = descriptorSet;
3073     writeInfos[2].dstBinding      = kBlitResolveSamplerBinding;
3074     writeInfos[2].descriptorCount = 1;
3075     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
3076     writeInfos[2].pImageInfo      = &samplerInfo;
3077 
3078     // If resolving color, there's one write info; index 0
3079     // If resolving depth, write info index 0 must be written
3080     // If resolving stencil, write info index 1 must also be written
3081     //
3082     // Note again that resolving color and depth/stencil are mutually exclusive here.
3083     uint32_t writeInfoOffset = blitDepth || blitColor ? 0 : 1;
3084     uint32_t writeInfoCount  = blitColor + blitDepth + blitStencil;
3085 
3086     vkUpdateDescriptorSets(contextVk->getDevice(), writeInfoCount, writeInfos + writeInfoOffset, 0,
3087                            nullptr);
3088     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfos[2], 0, nullptr);
3089 
3090     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
3091     vk::ShaderModulePtr vertexShader;
3092     vk::ShaderModulePtr fragmentShader;
3093     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
3094     if (isSrc3D)
3095     {
3096         ANGLE_TRY(shaderLibrary.getBlit3DSrc_frag(contextVk, flags, &fragmentShader));
3097     }
3098     else
3099     {
3100         ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
3101     }
3102 
3103     ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
3104                                    isSrc3D ? &mBlit3DSrc[flags] : &mBlitResolve[flags],
3105                                    &pipelineDesc, descriptorSet, &shaderParams,
3106                                    sizeof(shaderParams), commandBuffer));
3107 
3108     // Set dynamic state
3109     VkViewport viewport;
3110     gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
3111     gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, false, completeRenderArea.height,
3112                        &viewport);
3113     commandBuffer->setViewport(0, 1, &viewport);
3114 
3115     VkRect2D scissor = gl_vk::GetRect(params.blitArea);
3116     commandBuffer->setScissor(0, 1, &scissor);
3117 
3118     if (blitDepth)
3119     {
3120         SetDepthDynamicStateForWrite(renderer, commandBuffer);
3121     }
3122     else
3123     {
3124         SetDepthDynamicStateForUnused(renderer, commandBuffer);
3125     }
3126 
3127     if (blitStencil)
3128     {
3129         constexpr uint8_t kCompleteMask    = 0xFF;
3130         constexpr uint8_t kUnusedReference = 0x00;
3131 
3132         commandBuffer->setStencilCompareMask(kCompleteMask, kCompleteMask);
3133         commandBuffer->setStencilWriteMask(kCompleteMask, kCompleteMask);
3134         commandBuffer->setStencilReference(kUnusedReference, kUnusedReference);
3135 
3136         SetStencilDynamicStateForWrite(renderer, commandBuffer);
3137     }
3138     else
3139     {
3140         SetStencilDynamicStateForUnused(renderer, commandBuffer);
3141     }
3142 
3143     // Note: this utility starts the render pass directly, thus bypassing
3144     // ContextVk::startRenderPass. As such, occlusion queries are not enabled.
3145     commandBuffer->draw(3, 0);
3146 
3147     // Don't allow this render pass to be reactivated by the user's draw call due to test flakiness
3148     // on win/intel bot.
3149     contextVk->disableRenderPassReactivation();
3150 
3151     return angle::Result::Continue;
3152 }
3153 
stencilBlitResolveNoShaderExport(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)3154 angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
3155                                                         FramebufferVk *framebuffer,
3156                                                         vk::ImageHelper *src,
3157                                                         const vk::ImageView *srcStencilView,
3158                                                         const BlitResolveParameters &params)
3159 {
3160     vk::Renderer *renderer = contextVk->getRenderer();
3161 
3162     // When VK_EXT_shader_stencil_export is not available, stencil is blitted/resolved into a
3163     // temporary buffer which is then copied into the stencil aspect of the image.
3164     ANGLE_TRY(ensureBlitResolveStencilNoExportResourcesInitialized(contextVk));
3165 
3166     bool isResolve = src->getSamples() > 1;
3167 
3168     // Create a temporary buffer to blit/resolve stencil into.
3169     vk::RendererScoped<vk::BufferHelper> blitBuffer(renderer);
3170 
3171     uint32_t bufferRowLengthInUints = UnsignedCeilDivide(params.blitArea.width, sizeof(uint32_t));
3172     VkDeviceSize bufferSize = bufferRowLengthInUints * sizeof(uint32_t) * params.blitArea.height;
3173 
3174     ANGLE_TRY(contextVk->initBufferAllocation(
3175         &blitBuffer.get(), renderer->getDeviceLocalMemoryTypeIndex(),
3176         static_cast<size_t>(bufferSize), renderer->getDefaultBufferAlignment(),
3177         BufferUsageType::Static));
3178 
3179     BlitResolveStencilNoExportShaderParams shaderParams;
3180     // Note: adjustments made for pre-rotatation in FramebufferVk::blit() affect these
3181     // Calculate*Offset() functions.
3182     if (isResolve)
3183     {
3184         CalculateResolveOffset(params, shaderParams.offset.resolve);
3185     }
3186     else
3187     {
3188         CalculateBlitOffset(params, shaderParams.offset.blit);
3189     }
3190     shaderParams.stretch[0]      = params.stretch[0];
3191     shaderParams.stretch[1]      = params.stretch[1];
3192     shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
3193     shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
3194     shaderParams.srcLayer        = params.srcLayer;
3195     shaderParams.srcWidth        = params.srcExtents[0];
3196     shaderParams.srcHeight       = params.srcExtents[1];
3197     shaderParams.dstPitch        = bufferRowLengthInUints;
3198     shaderParams.blitArea[0]     = params.blitArea.x;
3199     shaderParams.blitArea[1]     = params.blitArea.y;
3200     shaderParams.blitArea[2]     = params.blitArea.width;
3201     shaderParams.blitArea[3]     = params.blitArea.height;
3202     shaderParams.flipX           = params.flipX;
3203     shaderParams.flipY           = params.flipY;
3204     shaderParams.rotateXY        = 0;
3205 
3206     // Potentially make adjustments for pre-rotatation.  Depending on the angle some of the
3207     // shaderParams need to be adjusted.
3208     switch (params.rotation)
3209     {
3210         case SurfaceRotation::Identity:
3211         case SurfaceRotation::Rotated90Degrees:
3212             break;
3213         case SurfaceRotation::Rotated180Degrees:
3214         case SurfaceRotation::Rotated270Degrees:
3215             if (isResolve)
3216             {
3217                 // Align the offset with minus 1, or the sample position near the edge will be
3218                 // wrong.
3219                 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0] - 1;
3220                 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1] - 1;
3221             }
3222             else
3223             {
3224                 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0];
3225                 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1];
3226             }
3227             break;
3228         default:
3229             UNREACHABLE();
3230             break;
3231     }
3232 
3233     shaderParams.rotateXY = IsRotatedAspectRatio(params.rotation);
3234 
3235     // Linear sampling is only valid with color blitting.
3236     ASSERT(!params.linear);
3237 
3238     uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0;
3239     flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
3240 
3241     RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
3242     ASSERT(depthStencilRenderTarget != nullptr);
3243     vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImageForWrite();
3244 
3245     // Change layouts prior to computation.
3246     vk::CommandBufferAccess access;
3247     access.onImageComputeShaderRead(src->getAspectFlags(), src);
3248     access.onImageTransferWrite(depthStencilRenderTarget->getLevelIndex(), 1,
3249                                 depthStencilRenderTarget->getLayerIndex(), 1,
3250                                 depthStencilImage->getAspectFlags(), depthStencilImage);
3251     access.onBufferComputeShaderWrite(&blitBuffer.get());
3252 
3253     VkDescriptorSet descriptorSet;
3254     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3255     vk::OutsideRenderPassCommandBuffer *commandBuffer;
3256     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3257     commandBuffer = &commandBufferHelper->getCommandBuffer();
3258     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
3259                                     Function::BlitResolveStencilNoExport, &descriptorSet));
3260 
3261     // Blit/resolve stencil into the buffer.
3262     VkDescriptorImageInfo imageInfo = {};
3263     imageInfo.imageView             = srcStencilView->getHandle();
3264     imageInfo.imageLayout           = src->getCurrentLayout();
3265 
3266     VkDescriptorBufferInfo bufferInfo = {};
3267     bufferInfo.buffer                 = blitBuffer.get().getBuffer().getHandle();
3268     bufferInfo.offset                 = blitBuffer.get().getOffset();
3269     bufferInfo.range                  = blitBuffer.get().getSize();
3270 
3271     VkDescriptorImageInfo samplerInfo = {};
3272     samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
3273 
3274     VkWriteDescriptorSet writeInfos[3] = {};
3275     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3276     writeInfos[0].dstSet               = descriptorSet;
3277     writeInfos[0].dstBinding           = kBlitResolveStencilNoExportDestBinding;
3278     writeInfos[0].descriptorCount      = 1;
3279     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3280     writeInfos[0].pBufferInfo          = &bufferInfo;
3281 
3282     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3283     writeInfos[1].dstSet          = descriptorSet;
3284     writeInfos[1].dstBinding      = kBlitResolveStencilNoExportSrcBinding;
3285     writeInfos[1].descriptorCount = 1;
3286     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3287     writeInfos[1].pImageInfo      = &imageInfo;
3288 
3289     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3290     writeInfos[2].dstSet          = descriptorSet;
3291     writeInfos[2].dstBinding      = kBlitResolveStencilNoExportSamplerBinding;
3292     writeInfos[2].descriptorCount = 1;
3293     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
3294     writeInfos[2].pImageInfo      = &samplerInfo;
3295 
3296     vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
3297 
3298     vk::ShaderModulePtr shader;
3299     ANGLE_TRY(contextVk->getShaderLibrary().getBlitResolveStencilNoExport_comp(contextVk, flags,
3300                                                                                &shader));
3301 
3302     ANGLE_TRY(setupComputeProgram(contextVk, Function::BlitResolveStencilNoExport, shader,
3303                                   &mBlitResolveStencilNoExport[flags], descriptorSet, &shaderParams,
3304                                   sizeof(shaderParams), commandBufferHelper));
3305     commandBuffer->dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
3306                             UnsignedCeilDivide(params.blitArea.height, 8), 1);
3307 
3308     // Add a barrier prior to copy.
3309     VkMemoryBarrier memoryBarrier = {};
3310     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
3311     memoryBarrier.srcAccessMask   = VK_ACCESS_SHADER_WRITE_BIT;
3312     memoryBarrier.dstAccessMask   = VK_ACCESS_TRANSFER_READ_BIT;
3313 
3314     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3315                                  VK_PIPELINE_STAGE_TRANSFER_BIT, memoryBarrier);
3316 
3317     // Copy the resulting buffer into dst.
3318     VkBufferImageCopy region           = {};
3319     region.bufferOffset                = blitBuffer.get().getOffset();
3320     region.bufferRowLength             = bufferRowLengthInUints * sizeof(uint32_t);
3321     region.bufferImageHeight           = params.blitArea.height;
3322     region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
3323     region.imageSubresource.mipLevel =
3324         depthStencilImage->toVkLevel(depthStencilRenderTarget->getLevelIndex()).get();
3325     region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex();
3326     region.imageSubresource.layerCount     = 1;
3327     region.imageOffset.x                   = params.blitArea.x;
3328     region.imageOffset.y                   = params.blitArea.y;
3329     region.imageOffset.z                   = 0;
3330     region.imageExtent.width               = params.blitArea.width;
3331     region.imageExtent.height              = params.blitArea.height;
3332     region.imageExtent.depth               = 1;
3333 
3334     commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(),
3335                                      depthStencilImage->getImage(),
3336                                      depthStencilImage->getCurrentLayout(), 1, &region);
3337 
3338     return angle::Result::Continue;
3339 }
3340 
copyImage(ContextVk * contextVk,vk::ImageHelper * dst,const vk::ImageView * destView,vk::ImageHelper * src,const vk::ImageView * srcView,const CopyImageParameters & params)3341 angle::Result UtilsVk::copyImage(ContextVk *contextVk,
3342                                  vk::ImageHelper *dst,
3343                                  const vk::ImageView *destView,
3344                                  vk::ImageHelper *src,
3345                                  const vk::ImageView *srcView,
3346                                  const CopyImageParameters &params)
3347 {
3348     vk::Renderer *renderer = contextVk->getRenderer();
3349 
3350     // The views passed to this function are already retained, so a render pass cannot be already
3351     // open.  Otherwise, this function closes the render pass, which may incur a vkQueueSubmit and
3352     // then the views are used in a new command buffer without having been retained for it.
3353     // http://crbug.com/1272266#c22
3354     ASSERT(!contextVk->hasActiveRenderPass());
3355 
3356     const angle::Format &srcIntendedFormat = src->getIntendedFormat();
3357     const angle::Format &dstIntendedFormat = dst->getIntendedFormat();
3358 
3359     const bool isYUV             = src->getYcbcrConversionDesc().valid();
3360     const bool isSrcMultisampled = params.srcSampleCount > 1;
3361 
3362     vk::SamplerDesc samplerDesc;
3363     if (isYUV)
3364     {
3365         samplerDesc = vk::SamplerDesc(contextVk, gl::SamplerState(), false,
3366                                       &src->getYcbcrConversionDesc(), srcIntendedFormat.id);
3367 
3368         ANGLE_TRY(ensureImageCopyResourcesInitializedWithSampler(contextVk, samplerDesc));
3369     }
3370     else
3371     {
3372         ANGLE_TRY(ensureImageCopyResourcesInitialized(contextVk));
3373     }
3374 
3375     ImageCopyShaderParams shaderParams;
3376     shaderParams.flipX            = 0;
3377     shaderParams.flipY            = params.srcFlipY || params.dstFlipY;
3378     shaderParams.premultiplyAlpha = params.srcPremultiplyAlpha;
3379     shaderParams.unmultiplyAlpha  = params.srcUnmultiplyAlpha;
3380     shaderParams.dstHasLuminance  = dstIntendedFormat.luminanceBits > 0;
3381     shaderParams.dstIsAlpha       = dstIntendedFormat.isLUMA() && dstIntendedFormat.alphaBits > 0;
3382     shaderParams.dstDefaultChannelsMask =
3383         GetFormatDefaultChannelMask(dst->getIntendedFormat(), dst->getActualFormat());
3384     shaderParams.srcMip       = params.srcMip;
3385     shaderParams.srcLayer     = params.srcLayer;
3386     shaderParams.srcSampleCount = params.srcSampleCount;
3387     shaderParams.srcOffset[0] = params.srcOffset[0];
3388     shaderParams.srcOffset[1] = params.srcOffset[1];
3389     shaderParams.dstOffset[0] = params.dstOffset[0];
3390     shaderParams.dstOffset[1] = params.dstOffset[1];
3391     shaderParams.rotateXY     = 0;
3392 
3393     shaderParams.srcIsSRGB = params.srcColorEncoding == GL_SRGB;
3394     shaderParams.dstIsSRGB = params.dstColorEncoding == GL_SRGB;
3395 
3396     // If both src and dst are sRGB, and there is no alpha multiplication/division necessary, then
3397     // the shader can work with sRGB data and pretend they are linear.
3398     if (shaderParams.srcIsSRGB && shaderParams.dstIsSRGB && !shaderParams.premultiplyAlpha &&
3399         !shaderParams.unmultiplyAlpha)
3400     {
3401         shaderParams.srcIsSRGB = false;
3402         shaderParams.dstIsSRGB = false;
3403     }
3404 
3405     ASSERT(!(params.srcFlipY && params.dstFlipY));
3406     if (params.srcFlipY)
3407     {
3408         // If viewport is flipped, the shader expects srcOffset[1] to have the
3409         // last row's index instead of the first's.
3410         shaderParams.srcOffset[1] = params.srcHeight - params.srcOffset[1] - 1;
3411     }
3412     else if (params.dstFlipY)
3413     {
3414         // If image is flipped during copy, the shader uses the same code path as above,
3415         // with srcOffset being set to the last row's index instead of the first's.
3416         shaderParams.srcOffset[1] = params.srcOffset[1] + params.srcExtents[1] - 1;
3417     }
3418 
3419     switch (params.srcRotation)
3420     {
3421         case SurfaceRotation::Identity:
3422             break;
3423         case SurfaceRotation::Rotated90Degrees:
3424             shaderParams.rotateXY = 1;
3425             break;
3426         case SurfaceRotation::Rotated180Degrees:
3427             shaderParams.flipX = true;
3428             ASSERT(shaderParams.flipY);
3429             shaderParams.flipY = false;
3430             shaderParams.srcOffset[0] += params.srcExtents[0];
3431             shaderParams.srcOffset[1] -= params.srcExtents[1];
3432             break;
3433         case SurfaceRotation::Rotated270Degrees:
3434             shaderParams.flipX = true;
3435             ASSERT(!shaderParams.flipY);
3436             shaderParams.flipY = true;
3437             shaderParams.srcOffset[0] += params.srcExtents[0];
3438             shaderParams.srcOffset[1] += params.srcExtents[1];
3439             shaderParams.rotateXY = 1;
3440             break;
3441         default:
3442             UNREACHABLE();
3443             break;
3444     }
3445 
3446     vk::RenderPassDesc renderPassDesc;
3447     renderPassDesc.setSamples(dst->getSamples());
3448     renderPassDesc.packColorAttachment(0, dst->getActualFormatID());
3449 
3450     vk::GraphicsPipelineDesc pipelineDesc;
3451     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
3452                               contextVk->pipelineRobustness(),
3453                               contextVk->pipelineProtectedAccess());
3454     pipelineDesc.setRenderPassDesc(renderPassDesc);
3455     pipelineDesc.setRasterizationSamples(dst->getSamples());
3456 
3457     gl::Rectangle renderArea;
3458     renderArea.x      = params.dstOffset[0];
3459     renderArea.y      = params.dstOffset[1];
3460     renderArea.width  = params.srcExtents[0];
3461     renderArea.height = params.srcExtents[1];
3462     if ((params.srcRotation == SurfaceRotation::Rotated90Degrees) ||
3463         (params.srcRotation == SurfaceRotation::Rotated270Degrees))
3464     {
3465         // The surface is rotated 90/270 degrees.  This changes the aspect ratio of the surface.
3466         std::swap(renderArea.width, renderArea.height);
3467     }
3468 
3469     vk::RenderPassCommandBuffer *commandBuffer;
3470     ANGLE_TRY(startRenderPass(contextVk, dst, destView, renderPassDesc, renderArea,
3471                               VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
3472                               vk::RenderPassSource::InternalUtils, &commandBuffer));
3473 
3474     VkDescriptorSet descriptorSet;
3475     if (isYUV)
3476     {
3477         ANGLE_TRY(allocateDescriptorSetForImageCopyWithSampler(
3478             contextVk, &contextVk->getStartedRenderPassCommands(), samplerDesc, &descriptorSet));
3479     }
3480     else
3481     {
3482         ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
3483                                         Function::ImageCopy, &descriptorSet));
3484     }
3485 
3486     UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
3487 
3488     // Change source layout inside render pass.
3489     contextVk->onImageRenderPassRead(VK_IMAGE_ASPECT_COLOR_BIT,
3490                                      vk::ImageLayout::FragmentShaderReadOnly, src);
3491     contextVk->onImageRenderPassWrite(params.dstMip, params.dstLayer, 1, VK_IMAGE_ASPECT_COLOR_BIT,
3492                                       vk::ImageLayout::ColorWrite, dst);
3493 
3494     VkDescriptorImageInfo imageInfo = {};
3495     imageInfo.imageView             = srcView->getHandle();
3496     imageInfo.imageLayout           = src->getCurrentLayout();
3497 
3498     VkWriteDescriptorSet writeInfo = {};
3499     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3500     writeInfo.dstSet               = descriptorSet;
3501     writeInfo.dstBinding           = kImageCopySourceBinding;
3502     writeInfo.descriptorCount      = 1;
3503     writeInfo.descriptorType =
3504         isYUV ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3505     writeInfo.pImageInfo = &imageInfo;
3506 
3507     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
3508 
3509     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
3510     vk::ShaderModulePtr vertexShader;
3511     vk::ShaderModulePtr fragmentShader;
3512     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
3513 
3514     if (isYUV)
3515     {
3516         ASSERT(src->getType() == VK_IMAGE_TYPE_2D);
3517         ANGLE_TRY(shaderLibrary.getImageCopyFloat_frag(contextVk, ImageCopyFloat_frag::kSrcIsYUV,
3518                                                        &fragmentShader));
3519         ANGLE_TRY(setupGraphicsProgramWithLayout(
3520             contextVk, *mImageCopyWithSamplerPipelineLayouts[samplerDesc], vertexShader,
3521             fragmentShader, &mImageCopyWithSampler[samplerDesc], &pipelineDesc, descriptorSet,
3522             &shaderParams, sizeof(shaderParams), commandBuffer));
3523     }
3524     else if (isSrcMultisampled)
3525     {
3526         ANGLE_TRY(shaderLibrary.getImageCopyFloat_frag(contextVk, ImageCopyFloat_frag::kSrcIs2DMS,
3527                                                        &fragmentShader));
3528         ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageCopy, vertexShader, fragmentShader,
3529                                        &mImageCopyFloat, &pipelineDesc, descriptorSet,
3530                                        &shaderParams, sizeof(shaderParams), commandBuffer));
3531     }
3532     else
3533     {
3534         uint32_t flags = GetImageCopyFlags(srcIntendedFormat, dstIntendedFormat);
3535         if (src->getType() == VK_IMAGE_TYPE_3D)
3536         {
3537             flags |= ImageCopy_frag::kSrcIs3D;
3538         }
3539         else if (src->getLayerCount() > 1)
3540         {
3541             flags |= ImageCopy_frag::kSrcIs2DArray;
3542         }
3543         else
3544         {
3545             ASSERT(src->getType() == VK_IMAGE_TYPE_2D);
3546             flags |= ImageCopy_frag::kSrcIs2D;
3547         }
3548 
3549         ANGLE_TRY(shaderLibrary.getImageCopy_frag(contextVk, flags, &fragmentShader));
3550         ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageCopy, vertexShader, fragmentShader,
3551                                        &mImageCopy[flags], &pipelineDesc, descriptorSet,
3552                                        &shaderParams, sizeof(shaderParams), commandBuffer));
3553     }
3554 
3555     // Set dynamic state
3556     VkViewport viewport;
3557     gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dst->getExtents().height, &viewport);
3558     commandBuffer->setViewport(0, 1, &viewport);
3559 
3560     VkRect2D scissor = gl_vk::GetRect(renderArea);
3561     commandBuffer->setScissor(0, 1, &scissor);
3562 
3563     SetDepthDynamicStateForUnused(renderer, commandBuffer);
3564     SetStencilDynamicStateForUnused(renderer, commandBuffer);
3565 
3566     // Note: this utility creates its own framebuffer, thus bypassing ContextVk::startRenderPass.
3567     // As such, occlusion queries are not enabled.
3568     commandBuffer->draw(3, 0);
3569 
3570     // Close the render pass for this temporary framebuffer.
3571     return contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::TemporaryForImageCopy);
3572 }
3573 
copyImageBits(ContextVk * contextVk,vk::ImageHelper * dst,vk::ImageHelper * src,const CopyImageBitsParameters & params)3574 angle::Result UtilsVk::copyImageBits(ContextVk *contextVk,
3575                                      vk::ImageHelper *dst,
3576                                      vk::ImageHelper *src,
3577                                      const CopyImageBitsParameters &params)
3578 {
3579     vk::Renderer *renderer = contextVk->getRenderer();
3580 
3581     // This function is used to copy the bit representation of an image to another, and is used to
3582     // support EXT_copy_image when a format is emulated.  Currently, only RGB->RGBA emulation is
3583     // possible, and so this function is tailored to this specific kind of emulation.
3584     //
3585     // The copy can be done with various degrees of efficiency:
3586     //
3587     // - If the UINT reinterpretation format for src supports SAMPLED usage, texels can be read
3588     //   directly from that.  Otherwise vkCmdCopyImageToBuffer can be used and data then read from
3589     //   the buffer.
3590     // - If the UINT reinterpretation format for dst supports STORAGE usage, texels can be written
3591     //   directly to that.  Otherwise conversion can be done to a buffer and then
3592     //   vkCmdCopyBufferToImage used.
3593     //
3594     // This requires four different shaders.  For simplicity, this function unconditionally copies
3595     // src to a temp buffer, transforms to another temp buffer and copies to the dst.  No known
3596     // applications use EXT_copy_image on RGB formats, so no further optimization is currently
3597     // necessary.
3598     //
3599     // The conversion between buffers can be done with ConvertVertex.comp in UintToUint mode, so no
3600     // new shader is necessary.  The srcEmulatedAlpha parameter is used to make sure the destination
3601     // alpha value is correct, if dst is RGBA.
3602 
3603     // This path should only be necessary for when RGBA is used as fallback for RGB.  No other
3604     // format which can be used with EXT_copy_image has a fallback.
3605     ASSERT(src->getIntendedFormat().blueBits > 0 && src->getIntendedFormat().alphaBits == 0);
3606     ASSERT(dst->getIntendedFormat().blueBits > 0 && dst->getIntendedFormat().alphaBits == 0);
3607 
3608     const angle::Format &srcImageFormat = src->getActualFormat();
3609     const angle::Format &dstImageFormat = dst->getActualFormat();
3610 
3611     // Create temporary buffers.
3612     vk::RendererScoped<vk::BufferHelper> srcBuffer(renderer);
3613     vk::RendererScoped<vk::BufferHelper> dstBuffer(renderer);
3614 
3615     const uint32_t srcPixelBytes = srcImageFormat.pixelBytes;
3616     const uint32_t dstPixelBytes = dstImageFormat.pixelBytes;
3617 
3618     const uint32_t totalPixelCount =
3619         params.copyExtents[0] * params.copyExtents[1] * params.copyExtents[2];
3620     // Note that buffer sizes are rounded up a multiple of uint size, as that the granularity in
3621     // which the compute shader accesses these buffers.
3622     const VkDeviceSize srcBufferSize =
3623         roundUpPow2<uint32_t>(srcPixelBytes * totalPixelCount, sizeof(uint32_t));
3624     const VkDeviceSize dstBufferSize =
3625         roundUpPow2<uint32_t>(dstPixelBytes * totalPixelCount, sizeof(uint32_t));
3626 
3627     VkBufferCreateInfo bufferInfo = {};
3628     bufferInfo.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
3629     bufferInfo.flags              = 0;
3630     bufferInfo.size               = srcBufferSize;
3631     bufferInfo.usage       = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3632     bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
3633     bufferInfo.queueFamilyIndexCount = 0;
3634     bufferInfo.pQueueFamilyIndices   = nullptr;
3635 
3636     ANGLE_TRY(srcBuffer.get().init(contextVk, bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
3637 
3638     bufferInfo.size  = dstBufferSize;
3639     bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
3640 
3641     ANGLE_TRY(dstBuffer.get().init(contextVk, bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
3642 
3643     bool isSrc3D = src->getType() == VK_IMAGE_TYPE_3D;
3644     bool isDst3D = dst->getType() == VK_IMAGE_TYPE_3D;
3645 
3646     // Change layouts prior to computation.
3647     vk::CommandBufferAccess access;
3648     access.onImageTransferRead(src->getAspectFlags(), src);
3649     access.onImageTransferWrite(params.dstLevel, 1, isDst3D ? 0 : params.dstOffset[2],
3650                                 isDst3D ? 1 : params.copyExtents[2], VK_IMAGE_ASPECT_COLOR_BIT,
3651                                 dst);
3652 
3653     // srcBuffer is the destination of copyImageToBuffer() below.
3654     access.onBufferTransferWrite(&srcBuffer.get());
3655     access.onBufferComputeShaderWrite(&dstBuffer.get());
3656 
3657     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3658     vk::OutsideRenderPassCommandBuffer *commandBuffer;
3659     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3660     commandBuffer = &commandBufferHelper->getCommandBuffer();
3661 
3662     // Copy src into buffer, completely packed.
3663     VkBufferImageCopy srcRegion               = {};
3664     srcRegion.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
3665     srcRegion.imageSubresource.mipLevel       = src->toVkLevel(params.srcLevel).get();
3666     srcRegion.imageSubresource.baseArrayLayer = isSrc3D ? 0 : params.srcOffset[2];
3667     srcRegion.imageSubresource.layerCount     = isSrc3D ? 1 : params.copyExtents[2];
3668     srcRegion.imageOffset.x                   = params.srcOffset[0];
3669     srcRegion.imageOffset.y                   = params.srcOffset[1];
3670     srcRegion.imageOffset.z                   = isSrc3D ? params.srcOffset[2] : 0;
3671     srcRegion.imageExtent.width               = params.copyExtents[0];
3672     srcRegion.imageExtent.height              = params.copyExtents[1];
3673     srcRegion.imageExtent.depth               = isSrc3D ? params.copyExtents[2] : 1;
3674 
3675     commandBuffer->copyImageToBuffer(src->getImage(), src->getCurrentLayout(),
3676                                      srcBuffer.get().getBuffer().getHandle(), 1, &srcRegion);
3677 
3678     // Add a barrier prior to dispatch call.
3679     VkMemoryBarrier memoryBarrier = {};
3680     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
3681     memoryBarrier.srcAccessMask   = VK_ACCESS_TRANSFER_WRITE_BIT;
3682     memoryBarrier.dstAccessMask   = VK_ACCESS_SHADER_READ_BIT;
3683 
3684     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
3685                                  VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, memoryBarrier);
3686 
3687     // Set up ConvertVertex shader to convert between the formats.  Only the following three cases
3688     // are possible:
3689     //
3690     // - RGB -> RGBA: Ns = 3, Ss = src.pixelBytes,
3691     //                Nd = 4, Sd = dst.pixelBytes, use srcEmulatedAlpha
3692     //
3693     // - RGBA -> RGBA: Ns = 3, Ss = src.pixelBytes,
3694     //                 Nd = 4, Sd = dst.pixelBytes, use srcEmulatedAlpha
3695     //
3696     // - RGBA -> RGB:  Ns = 3, Ss = src.pixelBytes,
3697     //                 Nd = 3, Sd = dst.pixelBytes
3698     //
3699     // The trick here is with RGBA -> RGBA, where Ns is specified as 3, so that the emulated alpha
3700     // from source is not taken (as uint), but rather one is provided such that the destination
3701     // alpha would contain the correct emulated alpha.
3702     //
3703     ConvertVertexShaderParams shaderParams;
3704     shaderParams.Ns = 3;
3705     shaderParams.Bs = srcImageFormat.pixelBytes / srcImageFormat.channelCount;
3706     shaderParams.Ss = srcImageFormat.pixelBytes;
3707     shaderParams.Nd = dstImageFormat.channelCount;
3708     shaderParams.Bd = dstImageFormat.pixelBytes / dstImageFormat.channelCount;
3709     shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
3710     // The component size is expected to either be 1, 2 or 4 bytes.
3711     ASSERT(4 % shaderParams.Bs == 0);
3712     ASSERT(4 % shaderParams.Bd == 0);
3713     shaderParams.Es = 4 / shaderParams.Bs;
3714     shaderParams.Ed = 4 / shaderParams.Bd;
3715     // Total number of output components is simply the number of pixels by number of components in
3716     // each.
3717     shaderParams.componentCount = totalPixelCount * shaderParams.Nd;
3718     // Total number of 4-byte outputs is the number of components divided by how many components can
3719     // fit in a 4-byte value.  Note that this value is also the invocation size of the shader.
3720     shaderParams.outputCount  = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
3721     shaderParams.srcOffset    = 0;
3722     shaderParams.dstOffset    = 0;
3723     shaderParams.isSrcHDR     = 0;
3724     shaderParams.isSrcA2BGR10 = 0;
3725 
3726     // Due to the requirements of EXT_copy_image, the channel size of src and dst must be
3727     // identical.  Usage of srcEmulatedAlpha relies on this as it's used to output an alpha value in
3728     // dst through the source.
3729     ASSERT(shaderParams.Bs == shaderParams.Bd);
3730 
3731     // The following RGB formats are allowed in EXT_copy_image:
3732     //
3733     // - RGB32F, RGB32UI, RGB32I
3734     // - RGB16F, RGB16UI, RGB16I
3735     // - RGB8, RGB8_SNORM, SRGB8, RGB8UI, RGB8I
3736     //
3737     // The value of emulated alpha is:
3738     //
3739     // - 1 for all RGB*I and RGB*UI formats
3740     // - bit representation of 1.0f for RGB32F
3741     // - bit representation of half-float 1.0f for RGB16F
3742     // - 0xFF for RGB8 and SRGB8
3743     // - 0x7F for RGB8_SNORM
3744     if (dstImageFormat.isInt())
3745     {
3746         shaderParams.srcEmulatedAlpha = 1;
3747     }
3748     else if (dstImageFormat.isUnorm())
3749     {
3750         ASSERT(shaderParams.Bd == 1);
3751         shaderParams.srcEmulatedAlpha = 0xFF;
3752     }
3753     else if (dstImageFormat.isSnorm())
3754     {
3755         ASSERT(shaderParams.Bd == 1);
3756         shaderParams.srcEmulatedAlpha = 0x7F;
3757     }
3758     else if (shaderParams.Bd == 2)
3759     {
3760         ASSERT(dstImageFormat.isFloat());
3761         shaderParams.srcEmulatedAlpha = gl::Float16One;
3762     }
3763     else if (shaderParams.Bd == 4)
3764     {
3765         ASSERT(dstImageFormat.isFloat());
3766         ASSERT(ValidateFloatOneAsUint());
3767         shaderParams.srcEmulatedAlpha = gl::Float32One;
3768     }
3769     else
3770     {
3771         UNREACHABLE();
3772     }
3773 
3774     // Use UintToUint conversion to preserve the bit pattern during transfer.
3775     const uint32_t flags = ConvertVertex_comp::kUintToUint;
3776     ANGLE_TRY(convertVertexBufferImpl(contextVk, &dstBuffer.get(), &srcBuffer.get(), flags,
3777                                       commandBufferHelper, shaderParams, {}));
3778 
3779     // Add a barrier prior to copy.
3780     memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
3781     memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
3782 
3783     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3784                                  VK_PIPELINE_STAGE_TRANSFER_BIT, memoryBarrier);
3785 
3786     // Copy buffer into dst.  It's completely packed.
3787     VkBufferImageCopy dstRegion               = {};
3788     dstRegion.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
3789     dstRegion.imageSubresource.mipLevel       = dst->toVkLevel(params.dstLevel).get();
3790     dstRegion.imageSubresource.baseArrayLayer = isDst3D ? 0 : params.dstOffset[2];
3791     dstRegion.imageSubresource.layerCount     = isDst3D ? 1 : params.copyExtents[2];
3792     dstRegion.imageOffset.x                   = params.dstOffset[0];
3793     dstRegion.imageOffset.y                   = params.dstOffset[1];
3794     dstRegion.imageOffset.z                   = isDst3D ? params.dstOffset[2] : 0;
3795     dstRegion.imageExtent.width               = params.copyExtents[0];
3796     dstRegion.imageExtent.height              = params.copyExtents[1];
3797     dstRegion.imageExtent.depth               = isDst3D ? params.copyExtents[2] : 1;
3798 
3799     commandBuffer->copyBufferToImage(dstBuffer.get().getBuffer().getHandle(), dst->getImage(),
3800                                      dst->getCurrentLayout(), 1, &dstRegion);
3801 
3802     return angle::Result::Continue;
3803 }
3804 
copyImageToBuffer(ContextVk * contextVk,vk::BufferHelper * dst,vk::ImageHelper * src,const CopyImageToBufferParameters & params)3805 angle::Result UtilsVk::copyImageToBuffer(ContextVk *contextVk,
3806                                          vk::BufferHelper *dst,
3807                                          vk::ImageHelper *src,
3808                                          const CopyImageToBufferParameters &params)
3809 {
3810     ANGLE_TRY(ensureCopyImageToBufferResourcesInitialized(contextVk));
3811 
3812     const angle::Format &srcFormat = src->getActualFormat();
3813 
3814     ASSERT(params.outputOffset % sizeof(uint32_t) == 0);
3815     ASSERT(params.outputPitch % sizeof(uint32_t) == 0);
3816 
3817     CopyImageToBufferShaderParams shaderParams;
3818     shaderParams.srcOffset[0]    = params.srcOffset[0];
3819     shaderParams.srcOffset[1]    = params.srcOffset[1];
3820     shaderParams.srcDepth        = params.srcLayer;
3821     shaderParams.reverseRowOrder = params.reverseRowOrder;
3822     shaderParams.size[0]         = params.size[0];
3823     shaderParams.size[1]         = params.size[1];
3824     shaderParams.outputOffset    = static_cast<uint32_t>(params.outputOffset / sizeof(uint32_t));
3825     shaderParams.outputPitch     = params.outputPitch / sizeof(uint32_t);
3826     shaderParams.isDstSnorm      = params.outputFormat->isSnorm();
3827 
3828     gl::SwizzleState swizzle;
3829     if (params.outputFormat->isBGRA())
3830     {
3831         swizzle.swizzleRed  = GL_BLUE;
3832         swizzle.swizzleBlue = GL_RED;
3833     }
3834 
3835     uint32_t flags = GetCopyImageToBufferFlags(srcFormat);
3836     gl::TextureType textureType;
3837     if (src->getType() == VK_IMAGE_TYPE_3D)
3838     {
3839         flags |= CopyImageToBuffer_comp::kSrcIs3D;
3840         textureType = gl::TextureType::_3D;
3841     }
3842     else
3843     {
3844         flags |= CopyImageToBuffer_comp::kSrcIs2D;
3845         textureType = gl::TextureType::_2D;
3846     }
3847 
3848     // Don't decode to linear colorspace when copying an image
3849     angle::FormatID imageFormat = src->getActualFormatID();
3850     angle::FormatID linearFormat =
3851         src->getActualFormat().isSRGB ? ConvertToLinear(imageFormat) : imageFormat;
3852     ASSERT(linearFormat != angle::FormatID::NONE);
3853 
3854     vk::DeviceScoped<vk::ImageView> srcView(contextVk->getDevice());
3855     ANGLE_TRY(src->initReinterpretedLayerImageView(
3856         contextVk, textureType, src->getAspectFlags(), swizzle, &srcView.get(), params.srcMip, 1,
3857         textureType == gl::TextureType::_2D ? params.srcLayer : 0, 1, VK_IMAGE_USAGE_SAMPLED_BIT,
3858         linearFormat));
3859 
3860     vk::CommandBufferAccess access;
3861     access.onImageComputeShaderRead(src->getAspectFlags(), src);
3862     access.onBufferComputeShaderWrite(dst);
3863 
3864     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3865     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3866 
3867     vk::OutsideRenderPassCommandBuffer *commandBuffer;
3868     commandBuffer = &commandBufferHelper->getCommandBuffer();
3869 
3870     VkDescriptorSet descriptorSet;
3871     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::CopyImageToBuffer,
3872                                     &descriptorSet));
3873 
3874     VkDescriptorImageInfo imageInfo = {};
3875     imageInfo.imageView             = srcView.get().getHandle();
3876     imageInfo.imageLayout           = src->getCurrentLayout();
3877 
3878     VkDescriptorBufferInfo bufferInfo = {};
3879     bufferInfo.buffer                 = dst->getBuffer().getHandle();
3880     bufferInfo.offset                 = dst->getOffset();
3881     bufferInfo.range                  = dst->getSize();
3882 
3883     VkWriteDescriptorSet writeInfo[2] = {};
3884 
3885     writeInfo[0].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3886     writeInfo[0].dstSet          = descriptorSet;
3887     writeInfo[0].dstBinding      = kCopyImageToBufferSourceBinding;
3888     writeInfo[0].descriptorCount = 1;
3889     writeInfo[0].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3890     writeInfo[0].pImageInfo      = &imageInfo;
3891 
3892     writeInfo[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3893     writeInfo[1].dstSet          = descriptorSet;
3894     writeInfo[1].dstBinding      = kCopyImageToBufferDestinationBinding;
3895     writeInfo[1].descriptorCount = 1;
3896     writeInfo[1].descriptorType  = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3897     writeInfo[1].pBufferInfo     = &bufferInfo;
3898 
3899     vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfo, 0, nullptr);
3900 
3901     vk::ShaderModulePtr shader;
3902     ANGLE_TRY(contextVk->getShaderLibrary().getCopyImageToBuffer_comp(contextVk, flags, &shader));
3903 
3904     ANGLE_TRY(setupComputeProgram(contextVk, Function::CopyImageToBuffer, shader,
3905                                   &mCopyImageToBuffer[flags], descriptorSet, &shaderParams,
3906                                   sizeof(shaderParams), commandBufferHelper));
3907 
3908     commandBuffer->dispatch(UnsignedCeilDivide(params.size[0], 8),
3909                             UnsignedCeilDivide(params.size[1], 8), 1);
3910 
3911     vk::ImageView srcViewObject = srcView.release();
3912     contextVk->addGarbage(&srcViewObject);
3913 
3914     return angle::Result::Continue;
3915 }
3916 
copyRgbToRgba(ContextVk * contextVk,const angle::Format & srcFormat,vk::BufferHelper * srcBuffer,uint32_t srcOffset,uint32_t pixelCount,vk::BufferHelper * dstBuffer)3917 angle::Result UtilsVk::copyRgbToRgba(ContextVk *contextVk,
3918                                      const angle::Format &srcFormat,
3919                                      vk::BufferHelper *srcBuffer,
3920                                      uint32_t srcOffset,
3921                                      uint32_t pixelCount,
3922                                      vk::BufferHelper *dstBuffer)
3923 {
3924     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3925 
3926     vk::CommandBufferAccess access;
3927     access.onBufferComputeShaderRead(srcBuffer);
3928     access.onBufferComputeShaderWrite(dstBuffer);
3929 
3930     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3931 
3932     rx::UtilsVk::ConvertVertexShaderParams shaderParams;
3933     shaderParams.Ns = 3;   // src channels
3934     shaderParams.Bs = 4;   // src bytes per channel
3935     shaderParams.Ss = 12;  // src stride
3936     shaderParams.Nd = 4;   // dest channels
3937     shaderParams.Bd = 4;   // dest bytes per channel
3938     shaderParams.Sd = 16;  // dest stride
3939     shaderParams.Es = 4 / shaderParams.Bs;
3940     shaderParams.Ed = 4 / shaderParams.Bd;
3941     // Total number of output components is simply the number of pixels by number of components in
3942     // each.
3943     shaderParams.componentCount = pixelCount * shaderParams.Nd;
3944     // Total number of 4-byte outputs is the number of components divided by how many components can
3945     // fit in a 4-byte value.  Note that this value is also the invocation size of the shader.
3946     shaderParams.outputCount  = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
3947     shaderParams.srcOffset    = srcOffset;
3948     shaderParams.dstOffset    = 0;
3949     shaderParams.isSrcHDR     = 0;
3950     shaderParams.isSrcA2BGR10 = 0;
3951 
3952     uint32_t flags = 0;
3953     switch (srcFormat.id)
3954     {
3955         case angle::FormatID::R32G32B32_UINT:
3956             flags                         = ConvertVertex_comp::kUintToUint;
3957             shaderParams.srcEmulatedAlpha = 1;
3958             break;
3959         case angle::FormatID::R32G32B32_SINT:
3960             flags                         = ConvertVertex_comp::kSintToSint;
3961             shaderParams.srcEmulatedAlpha = 1;
3962             break;
3963         case angle::FormatID::R32G32B32_FLOAT:
3964             flags                         = ConvertVertex_comp::kFloatToFloat;
3965             shaderParams.srcEmulatedAlpha = gl::Float32One;
3966             break;
3967         default:
3968             UNREACHABLE();
3969     }
3970 
3971     return convertVertexBufferImpl(contextVk, dstBuffer, srcBuffer, flags, commandBufferHelper,
3972                                    shaderParams, {});
3973 }
3974 
GetEtcToBcFlags(const angle::Format & format)3975 uint32_t GetEtcToBcFlags(const angle::Format &format)
3976 {
3977     switch (format.id)
3978     {
3979         case angle::FormatID::ETC1_R8G8B8_UNORM_BLOCK:
3980         case angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK:
3981         case angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK:
3982         case angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK:
3983         case angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK:
3984         case angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK:
3985         case angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK:
3986         case angle::FormatID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK:
3987             return EtcToBc_comp::kEtcRgba8ToBC3;
3988         case angle::FormatID::EAC_R11_SNORM_BLOCK:
3989         case angle::FormatID::EAC_R11_UNORM_BLOCK:
3990         case angle::FormatID::EAC_R11G11_SNORM_BLOCK:
3991         case angle::FormatID::EAC_R11G11_UNORM_BLOCK:
3992             return EtcToBc_comp::kEtcRg11ToBC5;
3993         default:
3994             UNREACHABLE();
3995             return EtcToBc_comp::kEtcRgba8ToBC3;
3996     }
3997 }
3998 
GetCompactibleUINTFormat(const angle::Format & format)3999 angle::FormatID GetCompactibleUINTFormat(const angle::Format &format)
4000 {
4001     ASSERT(format.pixelBytes == 8 || format.pixelBytes == 16);
4002     return format.pixelBytes != 8 ? angle::FormatID::R32G32B32A32_UINT
4003                                   : angle::FormatID::R32G32_UINT;
4004 }
4005 
transCodeEtcToBc(ContextVk * contextVk,vk::BufferHelper * srcBuffer,vk::ImageHelper * dstImage,const VkBufferImageCopy * copyRegion)4006 angle::Result UtilsVk::transCodeEtcToBc(ContextVk *contextVk,
4007                                         vk::BufferHelper *srcBuffer,
4008                                         vk::ImageHelper *dstImage,
4009                                         const VkBufferImageCopy *copyRegion)
4010 {
4011     ANGLE_TRY(ensureTransCodeEtcToBcResourcesInitialized(contextVk));
4012     vk::Renderer *renderer              = contextVk->getRenderer();
4013     const angle::Format &intendedFormat = dstImage->getIntendedFormat();
4014     vk::ContextScoped<vk::BufferViewHelper> bufferViewHelper(contextVk);
4015     const gl::InternalFormat &info =
4016         gl::GetSizedInternalFormatInfo(intendedFormat.glInternalFormat);
4017 
4018     // According to GLES spec. Etc texture don't support 3D texture type.
4019     ASSERT(copyRegion->bufferRowLength % info.compressedBlockWidth == 0 &&
4020            copyRegion->bufferImageHeight % info.compressedBlockHeight == 0 &&
4021            copyRegion->imageExtent.depth == 1);
4022 
4023     ASSERT(dstImage->getType() != VK_IMAGE_TYPE_1D && dstImage->getType() != VK_IMAGE_TYPE_3D);
4024 
4025     GLuint sliceTexels = (copyRegion->bufferRowLength / info.compressedBlockWidth) *
4026                          (copyRegion->bufferImageHeight / info.compressedBlockHeight);
4027     GLuint sliceSize     = sliceTexels * intendedFormat.pixelBytes;
4028     GLuint texBufferSize = sliceSize * copyRegion->imageSubresource.layerCount;
4029 
4030     // Make sure the texture buffer size not out of limit.
4031     // Usually the limit is more than 128M.
4032     ASSERT(
4033         texBufferSize <
4034         static_cast<GLuint>(renderer->getPhysicalDeviceProperties().limits.maxTexelBufferElements));
4035     const vk::BufferView *srcBufferView = nullptr;
4036     bufferViewHelper.get().init(renderer, 0, texBufferSize);
4037     ANGLE_TRY(bufferViewHelper.get().getView(
4038         contextVk, *srcBuffer, copyRegion->bufferOffset,
4039         renderer->getFormat(GetCompactibleUINTFormat(intendedFormat)), &srcBufferView));
4040 
4041     vk::LevelIndex dstLevel =
4042         gl::LevelIndexWrapper<uint32_t>(copyRegion->imageSubresource.mipLevel);
4043 
4044     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
4045     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper({}, &commandBufferHelper));
4046     const angle::Format &format              = dstImage->getIntendedFormat();
4047     uint32_t flags                           = GetEtcToBcFlags(format);
4048     vk::ShaderModulePtr shader;
4049     ANGLE_TRY(contextVk->getShaderLibrary().getEtcToBc_comp(contextVk, flags, &shader));
4050 
4051     vk::OutsideRenderPassCommandBuffer *commandBuffer;
4052     commandBuffer = &commandBufferHelper->getCommandBuffer();
4053 
4054     // For BC format, shader need width and height to be multiple of four.
4055     uint32_t width  = rx::roundUpPow2(copyRegion->imageExtent.width, 4u);
4056     uint32_t height = rx::roundUpPow2(copyRegion->imageExtent.height, 4u);
4057 
4058     // push constants data
4059     EtcToBcShaderParams shaderParams = {};
4060     shaderParams.offsetX             = static_cast<uint32_t>(copyRegion->imageOffset.x);
4061     shaderParams.offsetY             = static_cast<uint32_t>(copyRegion->imageOffset.y);
4062     shaderParams.texelOffset         = 0;
4063     shaderParams.width               = width;
4064     shaderParams.height              = height;
4065     shaderParams.alphaBits           = format.alphaBits;
4066     shaderParams.isSigned            = format.isSnorm();
4067     shaderParams.isEacRg             = format.channelCount == 2;  // EAC_RG11
4068 
4069     VkBufferView bufferView                    = srcBufferView->getHandle();
4070     VkWriteDescriptorSet writeDescriptorSet[2] = {};
4071     writeDescriptorSet[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4072     writeDescriptorSet[0].descriptorType       = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
4073     writeDescriptorSet[0].dstBinding           = 0;
4074     writeDescriptorSet[0].pBufferInfo          = nullptr;
4075     writeDescriptorSet[0].descriptorCount      = 1;
4076     writeDescriptorSet[0].pTexelBufferView     = &bufferView;
4077 
4078     VkDescriptorImageInfo imageInfo       = {};
4079     imageInfo.imageLayout                 = VK_IMAGE_LAYOUT_GENERAL;
4080     writeDescriptorSet[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4081     writeDescriptorSet[1].descriptorType  = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4082     writeDescriptorSet[1].dstBinding      = 1;
4083     writeDescriptorSet[1].pImageInfo      = &imageInfo;
4084     writeDescriptorSet[1].descriptorCount = 1;
4085     // Due to limitation VUID-VkImageViewCreateInfo-image-07072, we have to copy layer by layer.
4086     for (uint32_t i = 0; i < copyRegion->imageSubresource.layerCount; ++i)
4087     {
4088         vk::DeviceScoped<vk::ImageView> scopedImageView(contextVk->getDevice());
4089         ANGLE_TRY(dstImage->initReinterpretedLayerImageView(
4090             contextVk, gl::TextureType::_2D, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
4091             &scopedImageView.get(), dstLevel, 1, copyRegion->imageSubresource.baseArrayLayer + i, 1,
4092             VK_IMAGE_USAGE_STORAGE_BIT, GetCompactibleUINTFormat(intendedFormat)));
4093         imageInfo.imageView = scopedImageView.get().getHandle();
4094 
4095         VkDescriptorSet descriptorSet;
4096         ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::TransCodeEtcToBc,
4097                                         &descriptorSet));
4098         writeDescriptorSet[0].dstSet = descriptorSet;
4099         writeDescriptorSet[1].dstSet = descriptorSet;
4100         vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeDescriptorSet, 0, nullptr);
4101 
4102         ANGLE_TRY(setupComputeProgram(contextVk, Function::TransCodeEtcToBc, shader,
4103                                       &mEtcToBc[flags], descriptorSet, &shaderParams,
4104                                       sizeof(shaderParams), commandBufferHelper));
4105 
4106         // Work group size is 8 x 8 x 1
4107         commandBuffer->dispatch(UnsignedCeilDivide(width, 8), UnsignedCeilDivide(height, 8), 1);
4108         // Release temporary views
4109         vk::ImageView imageView = scopedImageView.release();
4110         contextVk->addGarbage(&imageView);
4111 
4112         shaderParams.texelOffset += sliceTexels;
4113     }
4114     // Retain buffer view
4115     commandBufferHelper->retainResource(&bufferViewHelper.get());
4116     return angle::Result::Continue;
4117 }
4118 
generateMipmap(ContextVk * contextVk,vk::ImageHelper * src,const vk::ImageView * srcLevelZeroView,vk::ImageHelper * dst,const GenerateMipmapDestLevelViews & destLevelViews,const vk::Sampler & sampler,const GenerateMipmapParameters & params)4119 angle::Result UtilsVk::generateMipmap(ContextVk *contextVk,
4120                                       vk::ImageHelper *src,
4121                                       const vk::ImageView *srcLevelZeroView,
4122                                       vk::ImageHelper *dst,
4123                                       const GenerateMipmapDestLevelViews &destLevelViews,
4124                                       const vk::Sampler &sampler,
4125                                       const GenerateMipmapParameters &params)
4126 {
4127     ANGLE_TRY(ensureGenerateMipmapResourcesInitialized(contextVk));
4128 
4129     const gl::Extents &srcExtents = src->getLevelExtents(vk::LevelIndex(params.srcLevel));
4130     ASSERT(srcExtents.depth == 1);
4131 
4132     // Each workgroup processes a 64x64 tile of the image.
4133     constexpr uint32_t kPixelWorkgroupRatio = 64;
4134     const uint32_t workGroupX = UnsignedCeilDivide(srcExtents.width, kPixelWorkgroupRatio);
4135     const uint32_t workGroupY = UnsignedCeilDivide(srcExtents.height, kPixelWorkgroupRatio);
4136 
4137     GenerateMipmapShaderParams shaderParams;
4138     shaderParams.invSrcExtent[0] = 1.0f / srcExtents.width;
4139     shaderParams.invSrcExtent[1] = 1.0f / srcExtents.height;
4140     shaderParams.levelCount      = params.dstLevelCount;
4141 
4142     uint32_t flags = GetGenerateMipmapFlags(contextVk, src->getActualFormat());
4143 
4144     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
4145     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper({}, &commandBufferHelper));
4146 
4147     VkDescriptorSet descriptorSet;
4148     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::GenerateMipmap,
4149                                     &descriptorSet));
4150 
4151     VkDescriptorImageInfo destImageInfos[kGenerateMipmapMaxLevels] = {};
4152     for (uint32_t level = 0; level < kGenerateMipmapMaxLevels; ++level)
4153     {
4154         destImageInfos[level].imageView   = destLevelViews[level]->getHandle();
4155         destImageInfos[level].imageLayout = dst->getCurrentLayout();
4156     }
4157 
4158     VkDescriptorImageInfo srcImageInfo = {};
4159     srcImageInfo.imageView             = srcLevelZeroView->getHandle();
4160     srcImageInfo.imageLayout           = src->getCurrentLayout();
4161     srcImageInfo.sampler               = sampler.getHandle();
4162 
4163     VkWriteDescriptorSet writeInfos[2] = {};
4164     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4165     writeInfos[0].dstSet               = descriptorSet;
4166     writeInfos[0].dstBinding           = kGenerateMipmapDestinationBinding;
4167     writeInfos[0].descriptorCount      = GetGenerateMipmapMaxLevels(contextVk);
4168     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4169     writeInfos[0].pImageInfo           = destImageInfos;
4170 
4171     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4172     writeInfos[1].dstSet          = descriptorSet;
4173     writeInfos[1].dstBinding      = kGenerateMipmapSourceBinding;
4174     writeInfos[1].descriptorCount = 1;
4175     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
4176     writeInfos[1].pImageInfo      = &srcImageInfo;
4177 
4178     vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
4179 
4180     vk::ShaderModulePtr shader;
4181     ANGLE_TRY(contextVk->getShaderLibrary().getGenerateMipmap_comp(contextVk, flags, &shader));
4182 
4183     // Note: onImageRead/onImageWrite is expected to be called by the caller.  This avoids inserting
4184     // barriers between calls for each layer of the image.
4185     vk::OutsideRenderPassCommandBuffer *commandBuffer;
4186     commandBuffer = &commandBufferHelper->getCommandBuffer();
4187 
4188     ANGLE_TRY(setupComputeProgram(contextVk, Function::GenerateMipmap, shader,
4189                                   &mGenerateMipmap[flags], descriptorSet, &shaderParams,
4190                                   sizeof(shaderParams), commandBufferHelper));
4191 
4192     commandBuffer->dispatch(workGroupX, workGroupY, 1);
4193 
4194     return angle::Result::Continue;
4195 }
4196 
generateMipmapWithDraw(ContextVk * contextVk,vk::ImageHelper * image,const angle::FormatID actualFormatID,const bool isMipmapFiltered)4197 angle::Result UtilsVk::generateMipmapWithDraw(ContextVk *contextVk,
4198                                               vk::ImageHelper *image,
4199                                               const angle::FormatID actualFormatID,
4200                                               const bool isMipmapFiltered)
4201 {
4202     // This function only supports -
4203     // 1. color formats that support color attachment feature
4204     // 2. image is of type VK_IMAGE_TYPE_2D and is not MSAA
4205     ASSERT(image);
4206     ASSERT(image->getType() == VK_IMAGE_TYPE_2D && image->getSamples() == 1);
4207     const angle::Format &actualFormat = angle::Format::Get(actualFormatID);
4208     ASSERT(!actualFormat.hasDepthOrStencilBits());
4209     // TODO: the following check is not enough; if the image is AHB-imported, then the draw path
4210     // cannot be taken if AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER hasn't been specified, even if the
4211     // format is renderable.
4212     vk::Renderer *renderer = contextVk->getRenderer();
4213     ASSERT(vk::FormatHasNecessaryFeature(renderer, actualFormat.id, image->getTilingMode(),
4214                                          VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT));
4215 
4216     // Ensure required resources are initialized
4217     ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
4218 
4219     uint32_t layerCount        = image->getLayerCount();
4220     uint32_t levelCount        = image->getLevelCount();
4221     GLint sampleCount          = image->getSamples();
4222     gl::LevelIndex baseLevelGL = image->getFirstAllocatedLevel();
4223     vk::LevelIndex baseLevelVK = image->toVkLevel(baseLevelGL);
4224     vk::LevelIndex maxLevelVK  = baseLevelVK + (levelCount - 1);
4225 
4226     // Transition entire image to color attachment layout
4227     vk::CommandBufferAccess access;
4228     access.onImageDrawMipmapGenerationWrite(baseLevelGL, levelCount, 0, layerCount,
4229                                             VK_IMAGE_ASPECT_COLOR_BIT, image);
4230     vk::OutsideRenderPassCommandBuffer *outsideCommandBuffer;
4231     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &outsideCommandBuffer));
4232 
4233     gl::TextureType textureType       = vk::Get2DTextureType(layerCount, sampleCount);
4234     gl::SwizzleState swizzle          = {};
4235     VkImageUsageFlags imageUsageFlags = image->getUsage();
4236 
4237     // Setup shaders for draw
4238     uint32_t flags = GetBlitResolveFlags(true, false, false, actualFormat);
4239     flags |= layerCount > 1 ? BlitResolve_frag::kSrcIsArray : 0;
4240     Function function = Function::BlitResolve;
4241 
4242     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
4243     vk::ShaderModulePtr vertexShader;
4244     vk::ShaderModulePtr fragmentShader;
4245     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
4246     ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
4247 
4248     // Setup blit shader parameters
4249     BlitResolveShaderParams shaderParams;
4250     shaderParams.offset.blit[0] = 0.0f;
4251     shaderParams.offset.blit[1] = 0.0f;
4252     shaderParams.stretch[0]     = 1.0f;
4253     shaderParams.stretch[1]     = 1.0f;
4254     shaderParams.samples        = 1;
4255     shaderParams.invSamples     = 1.0f;
4256     shaderParams.outputMask     = 1;
4257     shaderParams.flipX          = 0;
4258     shaderParams.flipY          = 0;
4259     shaderParams.rotateXY       = 0;
4260 
4261     // Setup pipeline for draw
4262     vk::RenderPassDesc renderPassDesc;
4263     renderPassDesc.setSamples(sampleCount);
4264     renderPassDesc.packColorAttachment(0, actualFormatID);
4265 
4266     vk::GraphicsPipelineDesc pipelineDesc;
4267     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
4268                               contextVk->pipelineRobustness(),
4269                               contextVk->pipelineProtectedAccess());
4270     pipelineDesc.setSingleColorWriteMask(0, (VkColorComponentFlagBits::VK_COLOR_COMPONENT_R_BIT |
4271                                              VkColorComponentFlagBits::VK_COLOR_COMPONENT_G_BIT |
4272                                              VkColorComponentFlagBits::VK_COLOR_COMPONENT_B_BIT |
4273                                              VkColorComponentFlagBits::VK_COLOR_COMPONENT_A_BIT));
4274     pipelineDesc.setRasterizationSamples(sampleCount);
4275     pipelineDesc.setRenderPassDesc(renderPassDesc);
4276 
4277     // Setup write descriptors
4278     VkDescriptorImageInfo imageInfos = {};
4279     imageInfos.imageLayout           = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4280 
4281     VkDescriptorImageInfo samplerInfo = {};
4282     samplerInfo.sampler = isMipmapFiltered ? mLinearSampler.getHandle() : mPointSampler.getHandle();
4283 
4284     VkWriteDescriptorSet writeInfos[2] = {};
4285     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4286     writeInfos[0].dstBinding           = kBlitResolveColorOrDepthBinding;
4287     writeInfos[0].descriptorCount      = 1;
4288     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
4289     writeInfos[0].pImageInfo           = &imageInfos;
4290 
4291     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4292     writeInfos[1].dstBinding      = kBlitResolveSamplerBinding;
4293     writeInfos[1].descriptorCount = 1;
4294     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
4295     writeInfos[1].pImageInfo      = &samplerInfo;
4296 
4297     // Setup for read barrier
4298     VkImageMemoryBarrier barrier            = {};
4299     barrier.sType                           = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
4300     barrier.image                           = image->getImage().getHandle();
4301     barrier.srcQueueFamilyIndex             = VK_QUEUE_FAMILY_IGNORED;
4302     barrier.dstQueueFamilyIndex             = VK_QUEUE_FAMILY_IGNORED;
4303     barrier.subresourceRange.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
4304     barrier.subresourceRange.baseArrayLayer = 0;
4305     barrier.subresourceRange.layerCount     = layerCount;
4306     barrier.subresourceRange.baseMipLevel   = baseLevelVK.get();
4307     barrier.subresourceRange.levelCount     = 1;
4308     barrier.oldLayout                       = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4309     barrier.srcAccessMask                   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
4310     barrier.newLayout                       = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4311     barrier.dstAccessMask                   = VK_ACCESS_SHADER_READ_BIT;
4312 
4313     // Sample from mipLevel N and draw to mipLevel N+1
4314     for (vk::LevelIndex srcLevelVk = baseLevelVK; srcLevelVk < maxLevelVK;)
4315     {
4316         // Transition "srcLevel" of all layers to shader read only optimal layout
4317         outsideCommandBuffer = nullptr;
4318         ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &outsideCommandBuffer));
4319 
4320         barrier.subresourceRange.baseMipLevel = srcLevelVk.get();
4321         outsideCommandBuffer->imageBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
4322                                            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier);
4323 
4324         // Update render area
4325         vk::LevelIndex dstLevelVk = srcLevelVk + 1;
4326         ASSERT(dstLevelVk <= baseLevelVK + levelCount);
4327         gl::Extents extents      = image->getLevelExtents(dstLevelVk);
4328         gl::Rectangle renderArea = gl::Rectangle(0, 0, extents.width, extents.height);
4329         VkViewport viewport;
4330         gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, renderArea.height, &viewport);
4331         VkRect2D scissor = gl_vk::GetRect(renderArea);
4332 
4333         shaderParams.invSrcExtent[0] = 1.0f / renderArea.width;
4334         shaderParams.invSrcExtent[1] = 1.0f / renderArea.height;
4335 
4336         // mipLevel N --> mipLevel N+1 must be done for each layer
4337         for (uint32_t currentLayer = 0; currentLayer < layerCount; currentLayer++)
4338         {
4339             // Create image views for currentLayer's srcLevelVk and dstLevelVk
4340             vk::ImageView srcImageView;
4341             ANGLE_TRY(image->initReinterpretedLayerImageView(
4342                 contextVk, textureType, image->getAspectFlags(), swizzle, &srcImageView, srcLevelVk,
4343                 1, currentLayer, 1, imageUsageFlags, actualFormatID));
4344 
4345             vk::ImageView dstImageView;
4346             ANGLE_TRY(image->initReinterpretedLayerImageView(
4347                 contextVk, textureType, image->getAspectFlags(), swizzle, &dstImageView, dstLevelVk,
4348                 1, currentLayer, 1, imageUsageFlags, actualFormatID));
4349 
4350             vk::RenderPassCommandBuffer *commandBuffer = nullptr;
4351             ANGLE_TRY(startRenderPass(contextVk, image, &dstImageView, renderPassDesc, renderArea,
4352                                       VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
4353                                       vk::RenderPassSource::InternalUtils, &commandBuffer));
4354 
4355             UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
4356 
4357             VkDescriptorSet descriptorSet;
4358             ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
4359                                             Function::BlitResolve, &descriptorSet));
4360 
4361             // Update write descriptor info
4362             writeInfos[0].dstSet = descriptorSet;
4363             writeInfos[1].dstSet = descriptorSet;
4364             imageInfos.imageView = srcImageView.getHandle();
4365             vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
4366 
4367             // Update layer index and create pipeline
4368             shaderParams.srcLayer = currentLayer;
4369             ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
4370                                            &mBlitResolve[flags], &pipelineDesc, descriptorSet,
4371                                            &shaderParams, sizeof(shaderParams), commandBuffer));
4372 
4373             // Set dynamic state
4374             commandBuffer->setViewport(0, 1, &viewport);
4375             commandBuffer->setScissor(0, 1, &scissor);
4376             SetDepthDynamicStateForUnused(renderer, commandBuffer);
4377             SetStencilDynamicStateForUnused(renderer, commandBuffer);
4378 
4379             // Note: this utility creates its own framebuffer, thus bypassing
4380             // ContextVk::startRenderPass. As such, occlusion queries are not enabled.
4381             commandBuffer->draw(3, 0);
4382 
4383             contextVk->addGarbage(&srcImageView);
4384             contextVk->addGarbage(&dstImageView);
4385         }
4386 
4387         // Close the render pass for this temporary framebuffer.
4388         ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
4389             RenderPassClosureReason::GenerateMipmapWithDraw));
4390 
4391         srcLevelVk = dstLevelVk;
4392     }
4393 
4394     // Transition the last mipLevel to shader read only optimal layout
4395     outsideCommandBuffer = nullptr;
4396     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &outsideCommandBuffer));
4397 
4398     barrier.subresourceRange.baseMipLevel = maxLevelVK.get();
4399     outsideCommandBuffer->imageBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
4400                                        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier);
4401 
4402     // Update image's layout related state to shader read only optimal layout
4403     image->setCurrentImageLayout(renderer, vk::ImageLayout::FragmentShaderReadOnly);
4404 
4405     return angle::Result::Continue;
4406 }
4407 
unresolve(ContextVk * contextVk,const FramebufferVk * framebuffer,const UnresolveParameters & params)4408 angle::Result UtilsVk::unresolve(ContextVk *contextVk,
4409                                  const FramebufferVk *framebuffer,
4410                                  const UnresolveParameters &params)
4411 {
4412     vk::Renderer *renderer = contextVk->getRenderer();
4413 
4414     // Get attachment count and pointers to resolve images and views.
4415     gl::DrawBuffersArray<vk::ImageHelper *> colorSrc         = {};
4416     gl::DrawBuffersArray<const vk::ImageView *> colorSrcView = {};
4417 
4418     const vk::ImageView *depthSrcView   = nullptr;
4419     const vk::ImageView *stencilSrcView = nullptr;
4420 
4421     // The subpass that initializes the multisampled-render-to-texture attachments packs the
4422     // attachments that need to be unresolved, so the attachment indices of this subpass are not the
4423     // same.  See InitializeUnresolveSubpass for details.
4424     vk::PackedAttachmentIndex colorIndexVk(0);
4425     for (size_t colorIndexGL : params.unresolveColorMask)
4426     {
4427         RenderTargetVk *colorRenderTarget = framebuffer->getColorDrawRenderTarget(colorIndexGL);
4428 
4429         ASSERT(colorRenderTarget->hasResolveAttachment());
4430         ASSERT(colorRenderTarget->isImageTransient());
4431 
4432         colorSrc[colorIndexVk.get()] = &colorRenderTarget->getResolveImageForRenderPass();
4433         ANGLE_TRY(
4434             colorRenderTarget->getResolveImageView(contextVk, &colorSrcView[colorIndexVk.get()]));
4435 
4436         ++colorIndexVk;
4437     }
4438 
4439     if (params.unresolveDepth || params.unresolveStencil)
4440     {
4441         RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
4442 
4443         ASSERT(depthStencilRenderTarget->hasResolveAttachment());
4444         ASSERT(depthStencilRenderTarget->isImageTransient());
4445 
4446         if (params.unresolveDepth)
4447         {
4448             ANGLE_TRY(depthStencilRenderTarget->getResolveDepthOrStencilImageView(
4449                 contextVk, VK_IMAGE_ASPECT_DEPTH_BIT, &depthSrcView));
4450         }
4451 
4452         if (params.unresolveStencil)
4453         {
4454             ANGLE_TRY(depthStencilRenderTarget->getResolveDepthOrStencilImageView(
4455                 contextVk, VK_IMAGE_ASPECT_STENCIL_BIT, &stencilSrcView));
4456         }
4457     }
4458 
4459     vk::GraphicsPipelineDesc pipelineDesc;
4460     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
4461                               contextVk->pipelineRobustness(),
4462                               contextVk->pipelineProtectedAccess());
4463     pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
4464     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
4465 
4466     vk::RenderPassCommandBuffer *commandBuffer =
4467         &contextVk->getStartedRenderPassCommands().getCommandBuffer();
4468 
4469     vk::ShaderLibrary &shaderLibrary               = contextVk->getShaderLibrary();
4470     vk::ShaderModulePtr vertexShader;
4471     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
4472 
4473     // Set dynamic state
4474     VkViewport viewport;
4475     gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
4476     bool invertViewport              = contextVk->isViewportFlipEnabledForDrawFBO();
4477     bool clipSpaceOriginUpperLeft =
4478         contextVk->getState().getClipOrigin() == gl::ClipOrigin::UpperLeft;
4479     gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, clipSpaceOriginUpperLeft,
4480                        completeRenderArea.height, &viewport);
4481     commandBuffer->setViewport(0, 1, &viewport);
4482 
4483     VkRect2D scissor = gl_vk::GetRect(completeRenderArea);
4484     commandBuffer->setScissor(0, 1, &scissor);
4485 
4486     // When VK_EXT_shader_stencil_export is enabled, the draw call can directly read from the
4487     // stencil buffer and export it.  When disabled, a special path is taken after the main
4488     // unresolve draw call.
4489     const bool unresolveStencilWithShaderExport =
4490         params.unresolveStencil && contextVk->getFeatures().supportsShaderStencilExport.enabled;
4491 
4492     const uint32_t colorAttachmentCount = colorIndexVk.get();
4493     const uint32_t depthStencilBindingCount =
4494         (params.unresolveDepth ? 1 : 0) + (unresolveStencilWithShaderExport ? 1 : 0);
4495     const uint32_t totalBindingCount = colorAttachmentCount + depthStencilBindingCount;
4496 
4497     if (totalBindingCount > 0)
4498     {
4499         const Function function = static_cast<Function>(
4500             static_cast<uint32_t>(Function::Unresolve1Attachment) + totalBindingCount - 1);
4501 
4502         ANGLE_TRY(ensureUnresolveResourcesInitialized(contextVk, function, totalBindingCount));
4503 
4504         if (params.unresolveDepth)
4505         {
4506             SetDepthStateForWrite(renderer, &pipelineDesc);
4507         }
4508 
4509         if (unresolveStencilWithShaderExport)
4510         {
4511             SetStencilStateForWrite(renderer, &pipelineDesc);
4512         }
4513 
4514         VkDescriptorSet descriptorSet;
4515         ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
4516                                         function, &descriptorSet));
4517 
4518         vk::FramebufferAttachmentArray<VkDescriptorImageInfo> inputImageInfo = {};
4519         uint32_t inputBindingIndex                                           = 0;
4520 
4521         if (unresolveStencilWithShaderExport)
4522         {
4523             inputImageInfo[inputBindingIndex].imageView = stencilSrcView->getHandle();
4524             inputImageInfo[inputBindingIndex].imageLayout =
4525                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4526             ++inputBindingIndex;
4527         }
4528         if (params.unresolveDepth)
4529         {
4530             inputImageInfo[inputBindingIndex].imageView = depthSrcView->getHandle();
4531             inputImageInfo[inputBindingIndex].imageLayout =
4532                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4533             ++inputBindingIndex;
4534         }
4535 
4536         for (uint32_t attachmentIndex = 0; attachmentIndex < colorAttachmentCount;
4537              ++attachmentIndex)
4538         {
4539             inputImageInfo[inputBindingIndex].imageView =
4540                 colorSrcView[attachmentIndex]->getHandle();
4541             inputImageInfo[inputBindingIndex].imageLayout =
4542                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4543             ++inputBindingIndex;
4544         }
4545 
4546         VkWriteDescriptorSet writeInfo = {};
4547         writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4548         writeInfo.dstSet               = descriptorSet;
4549         writeInfo.dstBinding           = 0;
4550         writeInfo.descriptorCount      = totalBindingCount;
4551         writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
4552         writeInfo.pImageInfo           = inputImageInfo.data();
4553 
4554         vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
4555 
4556         gl::DrawBuffersArray<UnresolveColorAttachmentType> colorAttachmentTypes;
4557         uint32_t flags = GetUnresolveFlags(colorAttachmentCount, colorSrc, params.unresolveDepth,
4558                                            unresolveStencilWithShaderExport, &colorAttachmentTypes);
4559 
4560         vk::ShaderModulePtr &fragmentShader = mUnresolveFragShaders[flags];
4561         ANGLE_TRY(GetUnresolveFrag(contextVk, colorAttachmentCount, colorAttachmentTypes,
4562                                    params.unresolveDepth, params.unresolveStencil,
4563                                    &fragmentShader));
4564 
4565         ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
4566                                        &mUnresolve[flags], &pipelineDesc, descriptorSet, nullptr, 0,
4567                                        commandBuffer));
4568 
4569         if (params.unresolveDepth)
4570         {
4571             SetDepthDynamicStateForWrite(renderer, commandBuffer);
4572         }
4573         else
4574         {
4575             SetDepthDynamicStateForUnused(renderer, commandBuffer);
4576         }
4577 
4578         if (unresolveStencilWithShaderExport)
4579         {
4580             constexpr uint8_t kCompleteMask    = 0xFF;
4581             constexpr uint8_t kUnusedReference = 0x00;
4582 
4583             commandBuffer->setStencilCompareMask(kCompleteMask, kCompleteMask);
4584             commandBuffer->setStencilWriteMask(kCompleteMask, kCompleteMask);
4585             commandBuffer->setStencilReference(kUnusedReference, kUnusedReference);
4586 
4587             SetStencilDynamicStateForWrite(renderer, commandBuffer);
4588         }
4589         else
4590         {
4591             SetStencilDynamicStateForUnused(renderer, commandBuffer);
4592         }
4593 
4594         // This draw call is made before ContextVk gets a chance to start the occlusion query.  As
4595         // such, occlusion queries are not enabled.
4596         commandBuffer->draw(3, 0);
4597     }
4598 
4599     // If stencil needs to be unresolved, but stencil export is not supported, set each bit of
4600     // stencil by adjusting the mask and controlling the output with `discard;` in the shader.  This
4601     // requires that the stencil is cleared to 0 beforehand.
4602     if (params.unresolveStencil && !unresolveStencilWithShaderExport)
4603     {
4604         ANGLE_TRY(ensureExportStencilResourcesInitialized(contextVk));
4605 
4606         // Disable color and depth output, and only let stencil through.
4607         pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
4608 
4609         SetDepthStateForUnused(renderer, &pipelineDesc);
4610         SetStencilStateForWrite(renderer, &pipelineDesc);
4611 
4612         vk::ShaderModulePtr exportStencilShader;
4613         ANGLE_TRY(shaderLibrary.getExportStencil_frag(contextVk, 0, &exportStencilShader));
4614 
4615         // A new descriptor set is needed to match the layout of the ExportStencil program.
4616         VkDescriptorSet exportStencilDescriptorSet;
4617         ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
4618                                         Function::ExportStencil, &exportStencilDescriptorSet));
4619 
4620         VkDescriptorImageInfo stencilImageInfo = {};
4621         stencilImageInfo.imageView             = stencilSrcView->getHandle();
4622         stencilImageInfo.imageLayout           = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4623 
4624         VkWriteDescriptorSet stencilWriteInfo = {};
4625         stencilWriteInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4626         stencilWriteInfo.dstSet               = exportStencilDescriptorSet;
4627         stencilWriteInfo.dstBinding           = 0;
4628         stencilWriteInfo.descriptorCount      = 1;
4629         stencilWriteInfo.descriptorType       = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
4630         stencilWriteInfo.pImageInfo           = &stencilImageInfo;
4631 
4632         vkUpdateDescriptorSets(contextVk->getDevice(), 1, &stencilWriteInfo, 0, nullptr);
4633 
4634         ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ExportStencil, vertexShader,
4635                                        exportStencilShader, &mExportStencil, &pipelineDesc,
4636                                        exportStencilDescriptorSet, nullptr, 0, commandBuffer));
4637 
4638         SetDepthDynamicStateForUnused(renderer, commandBuffer);
4639         SetStencilDynamicStateForWrite(renderer, commandBuffer);
4640 
4641         constexpr uint8_t kCompareMask = 0xFF;
4642         constexpr uint8_t kReference   = 0xFF;
4643         commandBuffer->setStencilCompareMask(kCompareMask, kCompareMask);
4644         commandBuffer->setStencilReference(kReference, kReference);
4645 
4646         // Set each bit in a different draw call.  This is not terribly efficient, but manages to
4647         // keep the transient multisampled stencil data on tile and avoids having to write it back
4648         // to memory / allocate memory for it.
4649         for (uint32_t bit = 0; bit < 8; ++bit)
4650         {
4651             const uint32_t writeMask = 1u << bit;
4652             commandBuffer->setStencilWriteMask(writeMask, writeMask);
4653 
4654             ExportStencilShaderParams shaderParams;
4655             shaderParams.bit = bit;
4656 
4657             commandBuffer->pushConstants(
4658                 *mPipelineLayouts[Function::ExportStencil], VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4659                 /*static_cast<uint32_t>*/ (sizeof(shaderParams)), &shaderParams);
4660 
4661             commandBuffer->draw(3, 0);
4662         }
4663     }
4664 
4665     return angle::Result::Continue;
4666 }
4667 
drawOverlay(ContextVk * contextVk,vk::BufferHelper * textWidgetsBuffer,vk::BufferHelper * graphWidgetsBuffer,vk::ImageHelper * font,const vk::ImageView * fontView,vk::ImageHelper * dst,const vk::ImageView * destView,const OverlayDrawParameters & params)4668 angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
4669                                    vk::BufferHelper *textWidgetsBuffer,
4670                                    vk::BufferHelper *graphWidgetsBuffer,
4671                                    vk::ImageHelper *font,
4672                                    const vk::ImageView *fontView,
4673                                    vk::ImageHelper *dst,
4674                                    const vk::ImageView *destView,
4675                                    const OverlayDrawParameters &params)
4676 {
4677     vk::Renderer *renderer = contextVk->getRenderer();
4678 
4679     ANGLE_TRY(ensureOverlayDrawResourcesInitialized(contextVk));
4680 
4681     OverlayDrawShaderParams shaderParams;
4682     shaderParams.viewportSize[0] = dst->getExtents().width;
4683     shaderParams.viewportSize[1] = dst->getExtents().height;
4684     shaderParams.isText          = false;
4685     shaderParams.rotateXY        = params.rotateXY;
4686     if (params.rotateXY)
4687     {
4688         std::swap(shaderParams.viewportSize[0], shaderParams.viewportSize[1]);
4689     }
4690 
4691     ASSERT(dst->getLevelCount() == 1 && dst->getLayerCount() == 1 &&
4692            dst->getFirstAllocatedLevel() == gl::LevelIndex(0));
4693 
4694     vk::RenderPassDesc renderPassDesc;
4695     renderPassDesc.setSamples(1);
4696     renderPassDesc.packColorAttachment(0, dst->getActualFormatID());
4697 
4698     vk::GraphicsPipelineDesc pipelineDesc;
4699     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
4700                               contextVk->pipelineRobustness(),
4701                               contextVk->pipelineProtectedAccess());
4702     pipelineDesc.setRenderPassDesc(renderPassDesc);
4703     pipelineDesc.setTopology(gl::PrimitiveMode::TriangleStrip);
4704     pipelineDesc.setSingleBlend(0, true, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_SRC_ALPHA,
4705                                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
4706 
4707     gl::Rectangle renderArea;
4708     renderArea.x      = 0;
4709     renderArea.y      = 0;
4710     renderArea.width  = shaderParams.viewportSize[0];
4711     renderArea.height = shaderParams.viewportSize[1];
4712 
4713     // A potential optimization is to reuse the already open render pass if it belongs to the
4714     // swapchain.
4715     vk::RenderPassCommandBuffer *commandBuffer;
4716     ANGLE_TRY(startRenderPass(contextVk, dst, destView, renderPassDesc, renderArea,
4717                               VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
4718                               vk::RenderPassSource::DefaultFramebuffer, &commandBuffer));
4719 
4720     vk::RenderPassCommandBufferHelper *commandBufferHelper =
4721         &contextVk->getStartedRenderPassCommands();
4722 
4723     VkDescriptorSet descriptorSet;
4724     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::OverlayDraw,
4725                                     &descriptorSet));
4726 
4727     UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
4728 
4729     commandBufferHelper->retainResource(textWidgetsBuffer);
4730     commandBufferHelper->retainResource(graphWidgetsBuffer);
4731     contextVk->onImageRenderPassRead(VK_IMAGE_ASPECT_COLOR_BIT,
4732                                      vk::ImageLayout::FragmentShaderReadOnly, font);
4733     contextVk->onImageRenderPassWrite(gl::LevelIndex(0), 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
4734                                       vk::ImageLayout::ColorWrite, dst);
4735 
4736     VkDescriptorImageInfo imageInfo = {};
4737     imageInfo.imageView             = fontView->getHandle();
4738     imageInfo.imageLayout           = font->getCurrentLayout();
4739 
4740     VkDescriptorBufferInfo bufferInfos[2] = {};
4741     bufferInfos[0].buffer                 = textWidgetsBuffer->getBuffer().getHandle();
4742     bufferInfos[0].offset                 = textWidgetsBuffer->getOffset();
4743     bufferInfos[0].range                  = textWidgetsBuffer->getSize();
4744 
4745     bufferInfos[1].buffer = graphWidgetsBuffer->getBuffer().getHandle();
4746     bufferInfos[1].offset = graphWidgetsBuffer->getOffset();
4747     bufferInfos[1].range  = graphWidgetsBuffer->getSize();
4748 
4749     VkWriteDescriptorSet writeInfos[3] = {};
4750     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4751     writeInfos[0].dstSet               = descriptorSet;
4752     writeInfos[0].dstBinding           = kOverlayDrawTextWidgetsBinding;
4753     writeInfos[0].descriptorCount      = 1;
4754     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
4755     writeInfos[0].pBufferInfo          = &bufferInfos[0];
4756 
4757     writeInfos[1]             = writeInfos[0];
4758     writeInfos[1].dstBinding  = kOverlayDrawGraphWidgetsBinding;
4759     writeInfos[1].pBufferInfo = &bufferInfos[1];
4760 
4761     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4762     writeInfos[2].dstSet          = descriptorSet;
4763     writeInfos[2].dstBinding      = kOverlayDrawFontBinding;
4764     writeInfos[2].descriptorCount = 1;
4765     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
4766     writeInfos[2].pImageInfo      = &imageInfo;
4767 
4768     vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
4769 
4770     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
4771     vk::ShaderModulePtr vertexShader;
4772     vk::ShaderModulePtr fragmentShader;
4773     ANGLE_TRY(shaderLibrary.getOverlayDraw_vert(contextVk, 0, &vertexShader));
4774     ANGLE_TRY(shaderLibrary.getOverlayDraw_frag(contextVk, 0, &fragmentShader));
4775 
4776     ANGLE_TRY(setupGraphicsProgram(contextVk, Function::OverlayDraw, vertexShader, fragmentShader,
4777                                    &mOverlayDraw, &pipelineDesc, descriptorSet, nullptr, 0,
4778                                    commandBuffer));
4779 
4780     // Set dynamic state
4781     VkViewport viewport;
4782     gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dst->getExtents().height, &viewport);
4783     commandBuffer->setViewport(0, 1, &viewport);
4784 
4785     VkRect2D scissor = gl_vk::GetRect(renderArea);
4786     commandBuffer->setScissor(0, 1, &scissor);
4787 
4788     SetDepthDynamicStateForUnused(renderer, commandBuffer);
4789     SetStencilDynamicStateForUnused(renderer, commandBuffer);
4790 
4791     // Draw all the graph widgets.
4792     if (params.graphWidgetCount > 0)
4793     {
4794         shaderParams.isText = false;
4795         commandBuffer->pushConstants(*mPipelineLayouts[Function::OverlayDraw],
4796                                      VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4797                                      sizeof(shaderParams), &shaderParams);
4798         commandBuffer->drawInstanced(4, params.graphWidgetCount, 0);
4799     }
4800     // Draw all the text widgets.
4801     if (params.textWidgetCount > 0)
4802     {
4803         shaderParams.isText = true;
4804         commandBuffer->pushConstants(*mPipelineLayouts[Function::OverlayDraw],
4805                                      VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4806                                      sizeof(shaderParams), &shaderParams);
4807         commandBuffer->drawInstanced(4, params.textWidgetCount, 0);
4808     }
4809 
4810     // Overlay is always drawn as the last render pass before present.  Automatically move the
4811     // layout to PresentSrc.
4812     contextVk->onColorDraw(gl::LevelIndex(0), 0, 1, dst, nullptr, {}, vk::PackedAttachmentIndex(0));
4813     if (contextVk->getFeatures().supportsPresentation.enabled &&
4814         !contextVk->getFeatures().preferDynamicRendering.enabled)
4815     {
4816         contextVk->getStartedRenderPassCommands().setImageOptimizeForPresent(dst);
4817         contextVk->finalizeImageLayout(dst, {});
4818     }
4819 
4820     // Close the render pass for this temporary framebuffer.
4821     return contextVk->flushCommandsAndEndRenderPass(
4822         RenderPassClosureReason::TemporaryForOverlayDraw);
4823 }
4824 
generateFragmentShadingRate(ContextVk * contextVk,vk::ImageHelper * shadingRateAttachmentImageHelper,vk::ImageViewHelper * shadingRateAttachmentImageViewHelper,const GenerateFragmentShadingRateParameters & shadingRateParameters)4825 angle::Result UtilsVk::generateFragmentShadingRate(
4826     ContextVk *contextVk,
4827     vk::ImageHelper *shadingRateAttachmentImageHelper,
4828     vk::ImageViewHelper *shadingRateAttachmentImageViewHelper,
4829     const GenerateFragmentShadingRateParameters &shadingRateParameters)
4830 {
4831     ANGLE_TRY(ensureGenerateFragmentShadingRateResourcesInitialized(contextVk));
4832 
4833     // Each workgroup processes an 8x8 tile of the image.
4834     constexpr uint32_t kPixelWorkgroupSize = 8;
4835     const uint32_t workGroupX =
4836         UnsignedCeilDivide(shadingRateParameters.attachmentWidth, kPixelWorkgroupSize);
4837     const uint32_t workGroupY =
4838         UnsignedCeilDivide(shadingRateParameters.attachmentHeight, kPixelWorkgroupSize);
4839 
4840     // Setup compute shader
4841     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
4842     vk::CommandBufferAccess access = {};
4843 
4844     // Fragment shading rate image will always have 1 layer.
4845     access.onImageComputeShaderWrite(shadingRateAttachmentImageHelper->getFirstAllocatedLevel(),
4846                                      shadingRateAttachmentImageHelper->getLevelCount(), 0,
4847                                      shadingRateAttachmentImageHelper->getLayerCount(),
4848                                      shadingRateAttachmentImageHelper->getAspectFlags(),
4849                                      shadingRateAttachmentImageHelper);
4850     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
4851     VkDescriptorSet descriptorSet;
4852     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
4853                                     Function::GenerateFragmentShadingRate, &descriptorSet));
4854     VkDescriptorImageInfo destShadingRateImage = {};
4855     destShadingRateImage.imageView =
4856         shadingRateAttachmentImageViewHelper->getFragmentShadingRateImageView().getHandle();
4857     destShadingRateImage.imageLayout   = shadingRateAttachmentImageHelper->getCurrentLayout();
4858     destShadingRateImage.sampler       = mPointSampler.getHandle();
4859     VkWriteDescriptorSet writeInfos[1] = {};
4860     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4861     writeInfos[0].dstSet               = descriptorSet;
4862     writeInfos[0].dstBinding           = kGenerateFragmentShadingRateAttachmentBinding;
4863     writeInfos[0].descriptorCount      = 1;
4864     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4865     writeInfos[0].pImageInfo           = &destShadingRateImage;
4866 
4867     vkUpdateDescriptorSets(contextVk->getDevice(), 1, writeInfos, 0, nullptr);
4868 
4869     vk::ShaderModulePtr computeShader;
4870     ANGLE_TRY(contextVk->getShaderLibrary().getGenerateFragmentShadingRate_comp(contextVk, 0,
4871                                                                                 &computeShader));
4872 
4873     // Record the command
4874     vk::OutsideRenderPassCommandBuffer *commandBuffer;
4875     commandBuffer = &commandBufferHelper->getCommandBuffer();
4876     ANGLE_TRY(setupComputeProgram(contextVk, Function::GenerateFragmentShadingRate, computeShader,
4877                                   &mGenerateFragmentShadingRateAttachment, descriptorSet,
4878                                   &shadingRateParameters, sizeof(shadingRateParameters),
4879                                   commandBufferHelper));
4880     commandBuffer->dispatch(workGroupX, workGroupY, 1);
4881     return angle::Result::Continue;
4882 }
4883 
allocateDescriptorSetWithLayout(ContextVk * contextVk,vk::CommandBufferHelperCommon * commandBufferHelper,vk::DynamicDescriptorPool & descriptorPool,const vk::DescriptorSetLayout & descriptorSetLayout,VkDescriptorSet * descriptorSetOut)4884 angle::Result UtilsVk::allocateDescriptorSetWithLayout(
4885     ContextVk *contextVk,
4886     vk::CommandBufferHelperCommon *commandBufferHelper,
4887     vk::DynamicDescriptorPool &descriptorPool,
4888     const vk::DescriptorSetLayout &descriptorSetLayout,
4889     VkDescriptorSet *descriptorSetOut)
4890 {
4891     vk::DescriptorSetPointer descriptorSet;
4892 
4893     ANGLE_TRY(descriptorPool.allocateDescriptorSet(contextVk, descriptorSetLayout, &descriptorSet));
4894 
4895     // Retain the individual descriptorSet to the command buffer.
4896     commandBufferHelper->retainResource(descriptorSet.get());
4897 
4898     *descriptorSetOut = descriptorSet->getDescriptorSet();
4899 
4900     return angle::Result::Continue;
4901 }
4902 
allocateDescriptorSet(ContextVk * contextVk,vk::CommandBufferHelperCommon * commandBufferHelper,Function function,VkDescriptorSet * descriptorSetOut)4903 angle::Result UtilsVk::allocateDescriptorSet(ContextVk *contextVk,
4904                                              vk::CommandBufferHelperCommon *commandBufferHelper,
4905                                              Function function,
4906                                              VkDescriptorSet *descriptorSetOut)
4907 {
4908     return allocateDescriptorSetWithLayout(
4909         contextVk, commandBufferHelper, mDescriptorPools[function],
4910         *mDescriptorSetLayouts[function][DescriptorSetIndex::Internal], descriptorSetOut);
4911 }
4912 
allocateDescriptorSetForImageCopyWithSampler(ContextVk * contextVk,vk::CommandBufferHelperCommon * commandBufferHelper,const vk::SamplerDesc & samplerDesc,VkDescriptorSet * descriptorSetOut)4913 angle::Result UtilsVk::allocateDescriptorSetForImageCopyWithSampler(
4914     ContextVk *contextVk,
4915     vk::CommandBufferHelperCommon *commandBufferHelper,
4916     const vk::SamplerDesc &samplerDesc,
4917     VkDescriptorSet *descriptorSetOut)
4918 {
4919     return allocateDescriptorSetWithLayout(
4920         contextVk, commandBufferHelper, mImageCopyWithSamplerDescriptorPools[samplerDesc],
4921         *mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc][DescriptorSetIndex::Internal],
4922         descriptorSetOut);
4923 }
4924 
ClearFramebufferParameters()4925 UtilsVk::ClearFramebufferParameters::ClearFramebufferParameters()
4926     : clearColor(false),
4927       clearDepth(false),
4928       clearStencil(false),
4929       stencilMask(0),
4930       colorMaskFlags(0),
4931       colorAttachmentIndexGL(0),
4932       colorFormat(nullptr),
4933       colorClearValue{},
4934       depthStencilClearValue{}
4935 {}
4936 
4937 // LineLoopHelper implementation.
LineLoopHelper(vk::Renderer * renderer)4938 LineLoopHelper::LineLoopHelper(vk::Renderer *renderer) {}
4939 LineLoopHelper::~LineLoopHelper() = default;
4940 
getIndexBufferForDrawArrays(ContextVk * contextVk,uint32_t clampedVertexCount,GLint firstVertex,vk::BufferHelper ** bufferOut)4941 angle::Result LineLoopHelper::getIndexBufferForDrawArrays(ContextVk *contextVk,
4942                                                           uint32_t clampedVertexCount,
4943                                                           GLint firstVertex,
4944                                                           vk::BufferHelper **bufferOut)
4945 {
4946     size_t allocateBytes = sizeof(uint32_t) * (static_cast<size_t>(clampedVertexCount) + 1);
4947     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
4948                                                        vk::MemoryHostVisibility::Visible));
4949     vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer();
4950     uint32_t *indices             = reinterpret_cast<uint32_t *>(indexBuffer->getMappedMemory());
4951 
4952     // Note: there could be an overflow in this addition.
4953     uint32_t unsignedFirstVertex = static_cast<uint32_t>(firstVertex);
4954     uint32_t vertexCount         = (clampedVertexCount + unsignedFirstVertex);
4955     for (uint32_t vertexIndex = unsignedFirstVertex; vertexIndex < vertexCount; vertexIndex++)
4956     {
4957         *indices++ = vertexIndex;
4958     }
4959     *indices = unsignedFirstVertex;
4960 
4961     // Since we are not using the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT flag when creating the
4962     // device memory in the StreamingBuffer, we always need to make sure we flush it after
4963     // writing.
4964     ANGLE_TRY(indexBuffer->flush(contextVk->getRenderer()));
4965 
4966     *bufferOut = indexBuffer;
4967 
4968     return angle::Result::Continue;
4969 }
4970 
getIndexBufferForElementArrayBuffer(ContextVk * contextVk,BufferVk * elementArrayBufferVk,gl::DrawElementsType glIndexType,int indexCount,intptr_t elementArrayOffset,vk::BufferHelper ** bufferOut,uint32_t * indexCountOut)4971 angle::Result LineLoopHelper::getIndexBufferForElementArrayBuffer(ContextVk *contextVk,
4972                                                                   BufferVk *elementArrayBufferVk,
4973                                                                   gl::DrawElementsType glIndexType,
4974                                                                   int indexCount,
4975                                                                   intptr_t elementArrayOffset,
4976                                                                   vk::BufferHelper **bufferOut,
4977                                                                   uint32_t *indexCountOut)
4978 {
4979     if (glIndexType == gl::DrawElementsType::UnsignedByte ||
4980         contextVk->getState().isPrimitiveRestartEnabled())
4981     {
4982         ANGLE_TRACE_EVENT0("gpu.angle", "LineLoopHelper::getIndexBufferForElementArrayBuffer");
4983 
4984         void *srcDataMapping = nullptr;
4985         ANGLE_TRY(elementArrayBufferVk->mapImpl(contextVk, GL_MAP_READ_BIT, &srcDataMapping));
4986         ANGLE_TRY(streamIndices(contextVk, glIndexType, indexCount,
4987                                 static_cast<const uint8_t *>(srcDataMapping) + elementArrayOffset,
4988                                 bufferOut, indexCountOut));
4989         ANGLE_TRY(elementArrayBufferVk->unmapImpl(contextVk));
4990         return angle::Result::Continue;
4991     }
4992 
4993     *indexCountOut = indexCount + 1;
4994 
4995     size_t unitSize = contextVk->getVkIndexTypeSize(glIndexType);
4996 
4997     size_t allocateBytes = unitSize * (indexCount + 1) + 1;
4998     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
4999                                                        vk::MemoryHostVisibility::Visible));
5000     vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer();
5001 
5002     vk::BufferHelper *sourceBuffer = &elementArrayBufferVk->getBuffer();
5003     VkDeviceSize sourceOffset =
5004         static_cast<VkDeviceSize>(elementArrayOffset) + sourceBuffer->getOffset();
5005     uint64_t unitCount                         = static_cast<VkDeviceSize>(indexCount);
5006     angle::FixedVector<VkBufferCopy, 2> copies = {
5007         {sourceOffset, indexBuffer->getOffset(), unitCount * unitSize},
5008         {sourceOffset, indexBuffer->getOffset() + unitCount * unitSize, unitSize},
5009     };
5010 
5011     vk::CommandBufferAccess access;
5012     access.onBufferTransferWrite(indexBuffer);
5013     access.onBufferTransferRead(sourceBuffer);
5014 
5015     vk::OutsideRenderPassCommandBuffer *commandBuffer;
5016     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
5017 
5018     commandBuffer->copyBuffer(sourceBuffer->getBuffer(), indexBuffer->getBuffer(),
5019                               static_cast<uint32_t>(copies.size()), copies.data());
5020 
5021     ANGLE_TRY(indexBuffer->flush(contextVk->getRenderer()));
5022 
5023     *bufferOut = indexBuffer;
5024 
5025     return angle::Result::Continue;
5026 }
5027 
streamIndices(ContextVk * contextVk,gl::DrawElementsType glIndexType,GLsizei indexCount,const uint8_t * srcPtr,vk::BufferHelper ** bufferOut,uint32_t * indexCountOut)5028 angle::Result LineLoopHelper::streamIndices(ContextVk *contextVk,
5029                                             gl::DrawElementsType glIndexType,
5030                                             GLsizei indexCount,
5031                                             const uint8_t *srcPtr,
5032                                             vk::BufferHelper **bufferOut,
5033                                             uint32_t *indexCountOut)
5034 {
5035     size_t unitSize = contextVk->getVkIndexTypeSize(glIndexType);
5036 
5037     uint32_t numOutIndices = indexCount + 1;
5038     if (contextVk->getState().isPrimitiveRestartEnabled())
5039     {
5040         numOutIndices = GetLineLoopWithRestartIndexCount(glIndexType, indexCount, srcPtr);
5041     }
5042     *indexCountOut = numOutIndices;
5043 
5044     ANGLE_TRY(contextVk->initBufferForVertexConversion(
5045         &mDynamicIndexBuffer, unitSize * numOutIndices, vk::MemoryHostVisibility::Visible));
5046     vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer();
5047     uint8_t *indices              = indexBuffer->getMappedMemory();
5048 
5049     if (contextVk->getState().isPrimitiveRestartEnabled())
5050     {
5051         HandlePrimitiveRestart(contextVk, glIndexType, indexCount, srcPtr, indices);
5052     }
5053     else
5054     {
5055         if (contextVk->shouldConvertUint8VkIndexType(glIndexType))
5056         {
5057             // If vulkan doesn't support uint8 index types, we need to emulate it.
5058             VkIndexType indexType = contextVk->getVkIndexType(glIndexType);
5059             ASSERT(indexType == VK_INDEX_TYPE_UINT16);
5060             uint16_t *indicesDst = reinterpret_cast<uint16_t *>(indices);
5061             for (int i = 0; i < indexCount; i++)
5062             {
5063                 indicesDst[i] = srcPtr[i];
5064             }
5065 
5066             indicesDst[indexCount] = srcPtr[0];
5067         }
5068         else
5069         {
5070             memcpy(indices, srcPtr, unitSize * indexCount);
5071             memcpy(indices + unitSize * indexCount, srcPtr, unitSize);
5072         }
5073     }
5074 
5075     ANGLE_TRY(indexBuffer->flush(contextVk->getRenderer()));
5076 
5077     *bufferOut = indexBuffer;
5078 
5079     return angle::Result::Continue;
5080 }
5081 
streamIndicesIndirect(ContextVk * contextVk,gl::DrawElementsType glIndexType,vk::BufferHelper * srcIndexBuffer,vk::BufferHelper * srcIndirectBuffer,VkDeviceSize indirectBufferOffset,vk::BufferHelper ** dstIndexBufferOut,vk::BufferHelper ** dstIndirectBufferOut)5082 angle::Result LineLoopHelper::streamIndicesIndirect(ContextVk *contextVk,
5083                                                     gl::DrawElementsType glIndexType,
5084                                                     vk::BufferHelper *srcIndexBuffer,
5085                                                     vk::BufferHelper *srcIndirectBuffer,
5086                                                     VkDeviceSize indirectBufferOffset,
5087                                                     vk::BufferHelper **dstIndexBufferOut,
5088                                                     vk::BufferHelper **dstIndirectBufferOut)
5089 {
5090     size_t unitSize      = contextVk->getVkIndexTypeSize(glIndexType);
5091     size_t allocateBytes = static_cast<size_t>(srcIndexBuffer->getSize() + unitSize);
5092 
5093     if (contextVk->getState().isPrimitiveRestartEnabled())
5094     {
5095         // If primitive restart, new index buffer is 135% the size of the original index buffer. The
5096         // smallest lineloop with primitive restart is 3 indices (point 1, point 2 and restart
5097         // value) when converted to linelist becomes 4 vertices. Expansion of 4/3. Any larger
5098         // lineloops would have less overhead and require less extra space. Any incomplete
5099         // primitives can be dropped or left incomplete and thus not increase the size of the
5100         // destination index buffer. Since we don't know the number of indices being used we'll use
5101         // the size of the index buffer as allocated as the index count.
5102         size_t numInputIndices    = static_cast<size_t>(srcIndexBuffer->getSize() / unitSize);
5103         size_t numNewInputIndices = ((numInputIndices * 4) / 3) + 1;
5104         allocateBytes             = static_cast<size_t>(numNewInputIndices * unitSize);
5105     }
5106 
5107     // Allocate buffer for results
5108     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
5109                                                        vk::MemoryHostVisibility::Visible));
5110     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndirectBuffer,
5111                                                        sizeof(VkDrawIndexedIndirectCommand),
5112                                                        vk::MemoryHostVisibility::Visible));
5113 
5114     vk::BufferHelper *dstIndexBuffer    = mDynamicIndexBuffer.getBuffer();
5115     vk::BufferHelper *dstIndirectBuffer = mDynamicIndirectBuffer.getBuffer();
5116 
5117     // Copy relevant section of the source into destination at allocated offset.  Note that the
5118     // offset returned by allocate() above is in bytes. As is the indices offset pointer.
5119     UtilsVk::ConvertLineLoopIndexIndirectParameters params = {};
5120     params.indirectBufferOffset    = static_cast<uint32_t>(indirectBufferOffset);
5121     params.dstIndirectBufferOffset = 0;
5122     params.srcIndexBufferOffset    = 0;
5123     params.dstIndexBufferOffset    = 0;
5124     params.indicesBitsWidth        = static_cast<uint32_t>(unitSize * 8);
5125 
5126     ANGLE_TRY(contextVk->getUtils().convertLineLoopIndexIndirectBuffer(
5127         contextVk, srcIndirectBuffer, srcIndexBuffer, dstIndirectBuffer, dstIndexBuffer, params));
5128 
5129     mDynamicIndexBuffer.clearDirty();
5130     mDynamicIndirectBuffer.clearDirty();
5131 
5132     *dstIndexBufferOut    = dstIndexBuffer;
5133     *dstIndirectBufferOut = dstIndirectBuffer;
5134 
5135     return angle::Result::Continue;
5136 }
5137 
streamArrayIndirect(ContextVk * contextVk,size_t vertexCount,vk::BufferHelper * arrayIndirectBuffer,VkDeviceSize arrayIndirectBufferOffset,vk::BufferHelper ** dstIndexBufferOut,vk::BufferHelper ** dstIndexIndirectBufferOut)5138 angle::Result LineLoopHelper::streamArrayIndirect(ContextVk *contextVk,
5139                                                   size_t vertexCount,
5140                                                   vk::BufferHelper *arrayIndirectBuffer,
5141                                                   VkDeviceSize arrayIndirectBufferOffset,
5142                                                   vk::BufferHelper **dstIndexBufferOut,
5143                                                   vk::BufferHelper **dstIndexIndirectBufferOut)
5144 {
5145     auto unitSize        = sizeof(uint32_t);
5146     size_t allocateBytes = static_cast<size_t>((vertexCount + 1) * unitSize);
5147 
5148     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
5149                                                        vk::MemoryHostVisibility::Visible));
5150     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndirectBuffer,
5151                                                        sizeof(VkDrawIndexedIndirectCommand),
5152                                                        vk::MemoryHostVisibility::Visible));
5153 
5154     vk::BufferHelper *dstIndexBuffer    = mDynamicIndexBuffer.getBuffer();
5155     vk::BufferHelper *dstIndirectBuffer = mDynamicIndirectBuffer.getBuffer();
5156 
5157     // Copy relevant section of the source into destination at allocated offset.  Note that the
5158     // offset returned by allocate() above is in bytes. As is the indices offset pointer.
5159     UtilsVk::ConvertLineLoopArrayIndirectParameters params = {};
5160     params.indirectBufferOffset    = static_cast<uint32_t>(arrayIndirectBufferOffset);
5161     params.dstIndirectBufferOffset = 0;
5162     params.dstIndexBufferOffset    = 0;
5163 
5164     ANGLE_TRY(contextVk->getUtils().convertLineLoopArrayIndirectBuffer(
5165         contextVk, arrayIndirectBuffer, dstIndirectBuffer, dstIndexBuffer, params));
5166 
5167     mDynamicIndexBuffer.clearDirty();
5168     mDynamicIndirectBuffer.clearDirty();
5169 
5170     *dstIndexBufferOut         = dstIndexBuffer;
5171     *dstIndexIndirectBufferOut = dstIndirectBuffer;
5172 
5173     return angle::Result::Continue;
5174 }
5175 
release(ContextVk * contextVk)5176 void LineLoopHelper::release(ContextVk *contextVk)
5177 {
5178     mDynamicIndexBuffer.release(contextVk);
5179     mDynamicIndirectBuffer.release(contextVk);
5180 }
5181 
destroy(vk::Renderer * renderer)5182 void LineLoopHelper::destroy(vk::Renderer *renderer)
5183 {
5184     mDynamicIndexBuffer.destroy(renderer);
5185     mDynamicIndirectBuffer.destroy(renderer);
5186 }
5187 }  // namespace rx
5188