xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/UtilsVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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::Context * context,uint32_t colorAttachmentCount,gl::DrawBuffersArray<UnresolveColorAttachmentType> & colorAttachmentTypes,bool unresolveDepth,bool unresolveStencil,vk::ShaderModulePtr * shader)1143 angle::Result GetUnresolveFrag(
1144     vk::Context *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         for (vk::PipelineHelper &pipeline : programAndPipelines.pipelines)
1347         {
1348             pipeline.destroy(device);
1349         }
1350     }
1351     for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertIndirectLineLoop)
1352     {
1353         programAndPipelines.program.destroy(renderer);
1354         for (vk::PipelineHelper &pipeline : programAndPipelines.pipelines)
1355         {
1356             pipeline.destroy(device);
1357         }
1358     }
1359     for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertIndexIndirectLineLoop)
1360     {
1361         programAndPipelines.program.destroy(renderer);
1362         for (vk::PipelineHelper &pipeline : programAndPipelines.pipelines)
1363         {
1364             pipeline.destroy(device);
1365         }
1366     }
1367     for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertVertex)
1368     {
1369         programAndPipelines.program.destroy(renderer);
1370         for (vk::PipelineHelper &pipeline : programAndPipelines.pipelines)
1371         {
1372             pipeline.destroy(device);
1373         }
1374     }
1375     mImageClearVSOnly.program.destroy(renderer);
1376     mImageClearVSOnly.pipelines.destroy(contextVk);
1377     for (GraphicsShaderProgramAndPipelines &programAndPipelines : mImageClear)
1378     {
1379         programAndPipelines.program.destroy(renderer);
1380         programAndPipelines.pipelines.destroy(contextVk);
1381     }
1382     for (GraphicsShaderProgramAndPipelines &programAndPipelines : mImageCopy)
1383     {
1384         programAndPipelines.program.destroy(renderer);
1385         programAndPipelines.pipelines.destroy(contextVk);
1386     }
1387     mImageCopyFloat.program.destroy(renderer);
1388     mImageCopyFloat.pipelines.destroy(contextVk);
1389     for (auto &iter : mImageCopyWithSampler)
1390     {
1391         GraphicsShaderProgramAndPipelines &programAndPipelines = iter.second;
1392         programAndPipelines.program.destroy(renderer);
1393         programAndPipelines.pipelines.destroy(contextVk);
1394     }
1395     for (ComputeShaderProgramAndPipelines &programAndPipelines : mCopyImageToBuffer)
1396     {
1397         programAndPipelines.program.destroy(renderer);
1398         for (vk::PipelineHelper &pipeline : programAndPipelines.pipelines)
1399         {
1400             pipeline.destroy(device);
1401         }
1402     }
1403     for (GraphicsShaderProgramAndPipelines &programAndPipelines : mBlitResolve)
1404     {
1405         programAndPipelines.program.destroy(renderer);
1406         programAndPipelines.pipelines.destroy(contextVk);
1407     }
1408     for (GraphicsShaderProgramAndPipelines &programAndPipelines : mBlit3DSrc)
1409     {
1410         programAndPipelines.program.destroy(renderer);
1411         programAndPipelines.pipelines.destroy(contextVk);
1412     }
1413     for (ComputeShaderProgramAndPipelines &programAndPipelines : mBlitResolveStencilNoExport)
1414     {
1415         programAndPipelines.program.destroy(renderer);
1416         for (vk::PipelineHelper &pipeline : programAndPipelines.pipelines)
1417         {
1418             pipeline.destroy(device);
1419         }
1420     }
1421     mExportStencil.program.destroy(renderer);
1422     mExportStencil.pipelines.destroy(contextVk);
1423     mOverlayDraw.program.destroy(renderer);
1424     mOverlayDraw.pipelines.destroy(contextVk);
1425     for (ComputeShaderProgramAndPipelines &programAndPipelines : mGenerateMipmap)
1426     {
1427         programAndPipelines.program.destroy(renderer);
1428         for (vk::PipelineHelper &pipeline : programAndPipelines.pipelines)
1429         {
1430             pipeline.destroy(device);
1431         }
1432     }
1433     for (ComputeShaderProgramAndPipelines &programAndPipelines : mEtcToBc)
1434     {
1435         programAndPipelines.program.destroy(renderer);
1436         for (vk::PipelineHelper &pipeline : programAndPipelines.pipelines)
1437         {
1438             pipeline.destroy(device);
1439         }
1440     }
1441     for (auto &programIter : mUnresolve)
1442     {
1443         GraphicsShaderProgramAndPipelines &programAndPipelines = programIter.second;
1444         programAndPipelines.program.destroy(renderer);
1445         programAndPipelines.pipelines.destroy(contextVk);
1446     }
1447     mUnresolve.clear();
1448 
1449     mUnresolveFragShaders.clear();
1450 
1451     mPointSampler.destroy(device);
1452     mLinearSampler.destroy(device);
1453 
1454     mGenerateFragmentShadingRateAttachment.program.destroy(renderer);
1455     for (vk::PipelineHelper &pipeline : mGenerateFragmentShadingRateAttachment.pipelines)
1456     {
1457         pipeline.destroy(device);
1458     }
1459 }
1460 
ensureResourcesInitialized(ContextVk * contextVk,Function function,VkDescriptorPoolSize * setSizes,size_t setSizesCount,size_t pushConstantsSize)1461 angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
1462                                                   Function function,
1463                                                   VkDescriptorPoolSize *setSizes,
1464                                                   size_t setSizesCount,
1465                                                   size_t pushConstantsSize)
1466 {
1467     vk::DescriptorSetLayoutDesc descriptorSetDesc;
1468     bool isCompute = function >= Function::ComputeStartIndex;
1469     VkShaderStageFlags descStages =
1470         isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
1471     if (function == Function::OverlayDraw)
1472     {
1473         descStages |= VK_SHADER_STAGE_VERTEX_BIT;
1474     }
1475 
1476     uint32_t currentBinding = 0;
1477     for (size_t i = 0; i < setSizesCount; ++i)
1478     {
1479         descriptorSetDesc.addBinding(currentBinding, setSizes[i].type, setSizes[i].descriptorCount,
1480                                      descStages, nullptr);
1481         ++currentBinding;
1482     }
1483 
1484     ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1485         contextVk, descriptorSetDesc,
1486         &mDescriptorSetLayouts[function][DescriptorSetIndex::Internal]));
1487 
1488     vk::DescriptorSetLayoutBindingVector bindingVector;
1489     descriptorSetDesc.unpackBindings(&bindingVector);
1490     std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
1491 
1492     for (const VkDescriptorSetLayoutBinding &binding : bindingVector)
1493     {
1494         if (binding.descriptorCount > 0)
1495         {
1496             VkDescriptorPoolSize poolSize = {};
1497 
1498             poolSize.type            = binding.descriptorType;
1499             poolSize.descriptorCount = binding.descriptorCount;
1500             descriptorPoolSizes.emplace_back(poolSize);
1501         }
1502     }
1503     if (!descriptorPoolSizes.empty())
1504     {
1505         ANGLE_TRY(mDescriptorPools[function].init(
1506             contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
1507             *mDescriptorSetLayouts[function][DescriptorSetIndex::Internal]));
1508     }
1509 
1510     // Corresponding pipeline layouts:
1511     vk::PipelineLayoutDesc pipelineLayoutDesc;
1512 
1513     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Internal, descriptorSetDesc);
1514     if (pushConstantsSize)
1515     {
1516         pipelineLayoutDesc.updatePushConstantRange(descStages, 0,
1517                                                    static_cast<uint32_t>(pushConstantsSize));
1518     }
1519 
1520     ANGLE_TRY(contextVk->getPipelineLayoutCache().getPipelineLayout(contextVk, pipelineLayoutDesc,
1521                                                                     mDescriptorSetLayouts[function],
1522                                                                     &mPipelineLayouts[function]));
1523 
1524     return angle::Result::Continue;
1525 }
1526 
ensureConvertIndexResourcesInitialized(ContextVk * contextVk)1527 angle::Result UtilsVk::ensureConvertIndexResourcesInitialized(ContextVk *contextVk)
1528 {
1529     if (mPipelineLayouts[Function::ConvertIndexBuffer])
1530     {
1531         return angle::Result::Continue;
1532     }
1533 
1534     VkDescriptorPoolSize setSizes[2] = {
1535         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1536         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1537     };
1538 
1539     return ensureResourcesInitialized(contextVk, Function::ConvertIndexBuffer, setSizes,
1540                                       ArraySize(setSizes), sizeof(ConvertIndexShaderParams));
1541 }
1542 
ensureConvertIndexIndirectResourcesInitialized(ContextVk * contextVk)1543 angle::Result UtilsVk::ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk)
1544 {
1545     if (mPipelineLayouts[Function::ConvertIndexIndirectBuffer])
1546     {
1547         return angle::Result::Continue;
1548     }
1549 
1550     VkDescriptorPoolSize setSizes[4] = {
1551         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst index buffer
1552         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // source index buffer
1553         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // src indirect buffer
1554         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst indirect buffer
1555     };
1556 
1557     return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectBuffer, setSizes,
1558                                       ArraySize(setSizes),
1559                                       sizeof(ConvertIndexIndirectShaderParams));
1560 }
1561 
ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk * contextVk)1562 angle::Result UtilsVk::ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
1563 {
1564     if (mPipelineLayouts[Function::ConvertIndexIndirectLineLoopBuffer])
1565     {
1566         return angle::Result::Continue;
1567     }
1568 
1569     VkDescriptorPoolSize setSizes[4] = {
1570         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // cmd buffer
1571         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst cmd buffer
1572         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // source index buffer
1573         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst index buffer
1574     };
1575 
1576     return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
1577                                       setSizes, ArraySize(setSizes),
1578                                       sizeof(ConvertIndexIndirectLineLoopShaderParams));
1579 }
1580 
ensureConvertIndirectLineLoopResourcesInitialized(ContextVk * contextVk)1581 angle::Result UtilsVk::ensureConvertIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
1582 {
1583     if (mPipelineLayouts[Function::ConvertIndirectLineLoopBuffer])
1584     {
1585         return angle::Result::Continue;
1586     }
1587 
1588     VkDescriptorPoolSize setSizes[3] = {
1589         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // cmd buffer
1590         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst cmd buffer
1591         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dst index buffer
1592     };
1593 
1594     return ensureResourcesInitialized(contextVk, Function::ConvertIndirectLineLoopBuffer, setSizes,
1595                                       ArraySize(setSizes),
1596                                       sizeof(ConvertIndirectLineLoopShaderParams));
1597 }
1598 
ensureConvertVertexResourcesInitialized(ContextVk * contextVk)1599 angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk)
1600 {
1601     if (mPipelineLayouts[Function::ConvertVertexBuffer])
1602     {
1603         return angle::Result::Continue;
1604     }
1605 
1606     VkDescriptorPoolSize setSizes[2] = {
1607         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1608         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1609     };
1610 
1611     return ensureResourcesInitialized(contextVk, Function::ConvertVertexBuffer, setSizes,
1612                                       ArraySize(setSizes), sizeof(ConvertVertexShaderParams));
1613 }
1614 
ensureImageClearResourcesInitialized(ContextVk * contextVk)1615 angle::Result UtilsVk::ensureImageClearResourcesInitialized(ContextVk *contextVk)
1616 {
1617     if (mPipelineLayouts[Function::ImageClear])
1618     {
1619         return angle::Result::Continue;
1620     }
1621 
1622     // The shader does not use any descriptor sets.
1623     return ensureResourcesInitialized(contextVk, Function::ImageClear, nullptr, 0,
1624                                       sizeof(ImageClearShaderParams));
1625 }
1626 
ensureImageCopyResourcesInitialized(ContextVk * contextVk)1627 angle::Result UtilsVk::ensureImageCopyResourcesInitialized(ContextVk *contextVk)
1628 {
1629     if (mPipelineLayouts[Function::ImageCopy])
1630     {
1631         return angle::Result::Continue;
1632     }
1633 
1634     VkDescriptorPoolSize setSizes[1] = {
1635         {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1636     };
1637 
1638     return ensureResourcesInitialized(contextVk, Function::ImageCopy, setSizes, ArraySize(setSizes),
1639                                       sizeof(ImageCopyShaderParams));
1640 }
1641 
ensureImageCopyResourcesInitializedWithSampler(ContextVk * contextVk,const vk::SamplerDesc & samplerDesc)1642 angle::Result UtilsVk::ensureImageCopyResourcesInitializedWithSampler(
1643     ContextVk *contextVk,
1644     const vk::SamplerDesc &samplerDesc)
1645 {
1646     if (mImageCopyWithSamplerPipelineLayouts[samplerDesc])
1647     {
1648         return angle::Result::Continue;
1649     }
1650 
1651     vk::SharedSamplerPtr sampler;
1652     ANGLE_TRY(
1653         contextVk->getRenderer()->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler));
1654 
1655     vk::DescriptorSetLayoutDesc descriptorSetDesc;
1656     descriptorSetDesc.addBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1,
1657                                  VK_SHADER_STAGE_FRAGMENT_BIT, &sampler->get());
1658 
1659     ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1660         contextVk, descriptorSetDesc,
1661         &mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc][DescriptorSetIndex::Internal]));
1662 
1663     VkDescriptorPoolSize setSizes[1] = {
1664         // A single YCbCr sampler may consume up to 3 descriptors.
1665         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3},
1666     };
1667     ANGLE_TRY(mImageCopyWithSamplerDescriptorPools[samplerDesc].init(
1668         contextVk, setSizes, 1,
1669         *mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc][DescriptorSetIndex::Internal]));
1670 
1671     vk::PipelineLayoutDesc pipelineLayoutDesc;
1672     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Internal, descriptorSetDesc);
1673     pipelineLayoutDesc.updatePushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0,
1674                                                sizeof(ImageCopyShaderParams));
1675 
1676     ANGLE_TRY(contextVk->getPipelineLayoutCache().getPipelineLayout(
1677         contextVk, pipelineLayoutDesc, mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc],
1678         &mImageCopyWithSamplerPipelineLayouts[samplerDesc]));
1679 
1680     return angle::Result::Continue;
1681 }
1682 
ensureCopyImageToBufferResourcesInitialized(ContextVk * contextVk)1683 angle::Result UtilsVk::ensureCopyImageToBufferResourcesInitialized(ContextVk *contextVk)
1684 {
1685     if (mPipelineLayouts[Function::CopyImageToBuffer])
1686     {
1687         return angle::Result::Continue;
1688     }
1689 
1690     VkDescriptorPoolSize setSizes[2] = {
1691         {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1692         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1693     };
1694 
1695     return ensureResourcesInitialized(contextVk, Function::CopyImageToBuffer, setSizes,
1696                                       ArraySize(setSizes), sizeof(CopyImageToBufferShaderParams));
1697 }
1698 
ensureBlitResolveResourcesInitialized(ContextVk * contextVk)1699 angle::Result UtilsVk::ensureBlitResolveResourcesInitialized(ContextVk *contextVk)
1700 {
1701     if (!mPipelineLayouts[Function::BlitResolve])
1702     {
1703         VkDescriptorPoolSize setSizes[3] = {
1704             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1705             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1706             {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
1707         };
1708 
1709         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolve, setSizes,
1710                                              ArraySize(setSizes), sizeof(BlitResolveShaderParams)));
1711     }
1712 
1713     return ensureSamplersInitialized(contextVk);
1714 }
1715 
ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk * contextVk)1716 angle::Result UtilsVk::ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk *contextVk)
1717 {
1718     if (!mPipelineLayouts[Function::BlitResolveStencilNoExport])
1719     {
1720         VkDescriptorPoolSize setSizes[3] = {
1721             {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1722             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1723             {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
1724         };
1725 
1726         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolveStencilNoExport,
1727                                              setSizes, ArraySize(setSizes),
1728                                              sizeof(BlitResolveStencilNoExportShaderParams)));
1729     }
1730 
1731     return ensureSamplersInitialized(contextVk);
1732 }
1733 
ensureExportStencilResourcesInitialized(ContextVk * contextVk)1734 angle::Result UtilsVk::ensureExportStencilResourcesInitialized(ContextVk *contextVk)
1735 {
1736     if (mPipelineLayouts[Function::ExportStencil])
1737     {
1738         return angle::Result::Continue;
1739     }
1740 
1741     VkDescriptorPoolSize setSizes[1] = {
1742         {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1},
1743     };
1744 
1745     return ensureResourcesInitialized(contextVk, Function::ExportStencil, setSizes,
1746                                       ArraySize(setSizes), sizeof(ExportStencilShaderParams));
1747 }
1748 
ensureOverlayDrawResourcesInitialized(ContextVk * contextVk)1749 angle::Result UtilsVk::ensureOverlayDrawResourcesInitialized(ContextVk *contextVk)
1750 {
1751     if (!mPipelineLayouts[Function::OverlayDraw])
1752     {
1753         VkDescriptorPoolSize setSizes[3] = {
1754             {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
1755             {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
1756             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1757         };
1758 
1759         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::OverlayDraw, setSizes,
1760                                              ArraySize(setSizes), sizeof(OverlayDrawShaderParams)));
1761     }
1762 
1763     return ensureSamplersInitialized(contextVk);
1764 }
1765 
ensureGenerateMipmapResourcesInitialized(ContextVk * contextVk)1766 angle::Result UtilsVk::ensureGenerateMipmapResourcesInitialized(ContextVk *contextVk)
1767 {
1768     if (mPipelineLayouts[Function::GenerateMipmap])
1769     {
1770         return angle::Result::Continue;
1771     }
1772 
1773     VkDescriptorPoolSize setSizes[2] = {
1774         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, GetGenerateMipmapMaxLevels(contextVk)},
1775         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1},
1776     };
1777 
1778     return ensureResourcesInitialized(contextVk, Function::GenerateMipmap, setSizes,
1779                                       ArraySize(setSizes), sizeof(GenerateMipmapShaderParams));
1780 }
1781 
ensureTransCodeEtcToBcResourcesInitialized(ContextVk * contextVk)1782 angle::Result UtilsVk::ensureTransCodeEtcToBcResourcesInitialized(ContextVk *contextVk)
1783 {
1784     if (mPipelineLayouts[Function::TransCodeEtcToBc])
1785     {
1786         return angle::Result::Continue;
1787     }
1788     VkDescriptorPoolSize setSizes[2] = {
1789         {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1},
1790         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
1791     };
1792 
1793     return ensureResourcesInitialized(contextVk, Function::TransCodeEtcToBc, setSizes,
1794                                       ArraySize(setSizes), sizeof(EtcToBcShaderParams));
1795 }
1796 
ensureUnresolveResourcesInitialized(ContextVk * contextVk,Function function,uint32_t attachmentCount)1797 angle::Result UtilsVk::ensureUnresolveResourcesInitialized(ContextVk *contextVk,
1798                                                            Function function,
1799                                                            uint32_t attachmentCount)
1800 {
1801     ASSERT(static_cast<uint32_t>(function) -
1802                static_cast<uint32_t>(Function::Unresolve1Attachment) ==
1803            attachmentCount - 1);
1804 
1805     if (mPipelineLayouts[function])
1806     {
1807         return angle::Result::Continue;
1808     }
1809 
1810     vk::FramebufferAttachmentArray<VkDescriptorPoolSize> setSizes;
1811     std::fill(setSizes.begin(), setSizes.end(),
1812               VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1});
1813 
1814     return ensureResourcesInitialized(contextVk, function, setSizes.data(), attachmentCount, 0);
1815 }
1816 
ensureSamplersInitialized(ContextVk * contextVk)1817 angle::Result UtilsVk::ensureSamplersInitialized(ContextVk *contextVk)
1818 {
1819     VkSamplerCreateInfo samplerInfo     = {};
1820     samplerInfo.sType                   = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
1821     samplerInfo.flags                   = 0;
1822     samplerInfo.magFilter               = VK_FILTER_NEAREST;
1823     samplerInfo.minFilter               = VK_FILTER_NEAREST;
1824     samplerInfo.mipmapMode              = VK_SAMPLER_MIPMAP_MODE_NEAREST;
1825     samplerInfo.addressModeU            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1826     samplerInfo.addressModeV            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1827     samplerInfo.addressModeW            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1828     samplerInfo.mipLodBias              = 0.0f;
1829     samplerInfo.anisotropyEnable        = VK_FALSE;
1830     samplerInfo.maxAnisotropy           = 1;
1831     samplerInfo.compareEnable           = VK_FALSE;
1832     samplerInfo.compareOp               = VK_COMPARE_OP_ALWAYS;
1833     samplerInfo.minLod                  = 0;
1834     samplerInfo.maxLod                  = 0;
1835     samplerInfo.borderColor             = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
1836     samplerInfo.unnormalizedCoordinates = VK_FALSE;
1837 
1838     if (!mPointSampler.valid())
1839     {
1840         ANGLE_VK_TRY(contextVk, mPointSampler.init(contextVk->getDevice(), samplerInfo));
1841     }
1842 
1843     samplerInfo.magFilter = VK_FILTER_LINEAR;
1844     samplerInfo.minFilter = VK_FILTER_LINEAR;
1845 
1846     if (!mLinearSampler.valid())
1847     {
1848         ANGLE_VK_TRY(contextVk, mLinearSampler.init(contextVk->getDevice(), samplerInfo));
1849     }
1850 
1851     return angle::Result::Continue;
1852 }
1853 
ensureGenerateFragmentShadingRateResourcesInitialized(ContextVk * contextVk)1854 angle::Result UtilsVk::ensureGenerateFragmentShadingRateResourcesInitialized(ContextVk *contextVk)
1855 {
1856     if (mGenerateFragmentShadingRateAttachment.program.valid(gl::ShaderType::Compute))
1857     {
1858         return angle::Result::Continue;
1859     }
1860 
1861     VkDescriptorPoolSize setSizes[1] = {
1862         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
1863     };
1864 
1865     return ensureResourcesInitialized(contextVk, Function::GenerateFragmentShadingRate, setSizes,
1866                                       ArraySize(setSizes),
1867                                       sizeof(GenerateFragmentShadingRateParameters));
1868 }
1869 
setupComputeProgram(ContextVk * contextVk,Function function,const vk::ShaderModulePtr & csShader,ComputeShaderProgramAndPipelines * programAndPipelines,const VkDescriptorSet descriptorSet,const void * pushConstants,size_t pushConstantsSize,vk::OutsideRenderPassCommandBufferHelper * commandBufferHelper)1870 angle::Result UtilsVk::setupComputeProgram(
1871     ContextVk *contextVk,
1872     Function function,
1873     const vk::ShaderModulePtr &csShader,
1874     ComputeShaderProgramAndPipelines *programAndPipelines,
1875     const VkDescriptorSet descriptorSet,
1876     const void *pushConstants,
1877     size_t pushConstantsSize,
1878     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper)
1879 {
1880     vk::Renderer *renderer = contextVk->getRenderer();
1881 
1882     ASSERT(function >= Function::ComputeStartIndex);
1883 
1884     const vk::PipelineLayoutPtr &pipelineLayout = mPipelineLayouts[function];
1885 
1886     if (!programAndPipelines->program.valid(gl::ShaderType::Compute))
1887     {
1888         programAndPipelines->program.setShader(gl::ShaderType::Compute, csShader);
1889     }
1890 
1891     vk::PipelineHelper *pipeline;
1892     vk::PipelineCacheAccess pipelineCache;
1893     ANGLE_TRY(renderer->getPipelineCache(contextVk, &pipelineCache));
1894     ANGLE_TRY(programAndPipelines->program.getOrCreateComputePipeline(
1895         contextVk, &programAndPipelines->pipelines, &pipelineCache, *pipelineLayout,
1896         vk::GetComputePipelineOptions(contextVk->pipelineRobustness(),
1897                                       contextVk->pipelineProtectedAccess()),
1898         PipelineSource::Utils, &pipeline, nullptr, nullptr));
1899     commandBufferHelper->retainResource(pipeline);
1900 
1901     vk::OutsideRenderPassCommandBuffer *commandBuffer = &commandBufferHelper->getCommandBuffer();
1902     commandBuffer->bindComputePipeline(pipeline->getPipeline());
1903 
1904     contextVk->invalidateComputePipelineBinding();
1905 
1906     if (descriptorSet != VK_NULL_HANDLE)
1907     {
1908         commandBuffer->bindDescriptorSets(*pipelineLayout, VK_PIPELINE_BIND_POINT_COMPUTE,
1909                                           DescriptorSetIndex::Internal, 1, &descriptorSet, 0,
1910                                           nullptr);
1911         contextVk->invalidateComputeDescriptorSet(DescriptorSetIndex::Internal);
1912     }
1913 
1914     if (pushConstants)
1915     {
1916         commandBuffer->pushConstants(*pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
1917                                      static_cast<uint32_t>(pushConstantsSize), pushConstants);
1918     }
1919 
1920     return angle::Result::Continue;
1921 }
1922 
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)1923 angle::Result UtilsVk::setupGraphicsProgramWithLayout(
1924     ContextVk *contextVk,
1925     const vk::PipelineLayout &pipelineLayout,
1926     const vk::ShaderModulePtr &vsShader,
1927     const vk::ShaderModulePtr &fsShader,
1928     GraphicsShaderProgramAndPipelines *programAndPipelines,
1929     const vk::GraphicsPipelineDesc *pipelineDesc,
1930     const VkDescriptorSet descriptorSet,
1931     const void *pushConstants,
1932     size_t pushConstantsSize,
1933     vk::RenderPassCommandBuffer *commandBuffer)
1934 {
1935     vk::Renderer *renderer = contextVk->getRenderer();
1936 
1937     if (!programAndPipelines->program.valid(gl::ShaderType::Vertex))
1938     {
1939         programAndPipelines->program.setShader(gl::ShaderType::Vertex, vsShader);
1940         if (fsShader)
1941         {
1942             programAndPipelines->program.setShader(gl::ShaderType::Fragment, fsShader);
1943         }
1944     }
1945 
1946     // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
1947     vk::PipelineCacheAccess pipelineCache;
1948     ANGLE_TRY(renderer->getPipelineCache(contextVk, &pipelineCache));
1949 
1950     // Pull in a compatible RenderPass.
1951     const vk::RenderPass *compatibleRenderPass = nullptr;
1952     ANGLE_TRY(contextVk->getCompatibleRenderPass(pipelineDesc->getRenderPassDesc(),
1953                                                  &compatibleRenderPass));
1954 
1955     const vk::GraphicsPipelineDesc *descPtr;
1956     vk::PipelineHelper *helper;
1957 
1958     if (!programAndPipelines->pipelines.getPipeline(*pipelineDesc, &descPtr, &helper))
1959     {
1960         ANGLE_TRY(programAndPipelines->program.createGraphicsPipeline(
1961             contextVk, &programAndPipelines->pipelines, &pipelineCache, *compatibleRenderPass,
1962             pipelineLayout, PipelineSource::Utils, *pipelineDesc, {}, &descPtr, &helper));
1963     }
1964 
1965     contextVk->getStartedRenderPassCommands().retainResource(helper);
1966     commandBuffer->bindGraphicsPipeline(helper->getPipeline());
1967 
1968     contextVk->invalidateGraphicsPipelineBinding();
1969 
1970     if (descriptorSet != VK_NULL_HANDLE)
1971     {
1972         commandBuffer->bindDescriptorSets(pipelineLayout, VK_PIPELINE_BIND_POINT_GRAPHICS,
1973                                           DescriptorSetIndex::Internal, 1, &descriptorSet, 0,
1974                                           nullptr);
1975         contextVk->invalidateGraphicsDescriptorSet(DescriptorSetIndex::Internal);
1976     }
1977 
1978     if (pushConstants)
1979     {
1980         commandBuffer->pushConstants(pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0,
1981                                      static_cast<uint32_t>(pushConstantsSize), pushConstants);
1982     }
1983 
1984     ResetDynamicState(contextVk, commandBuffer);
1985 
1986     return angle::Result::Continue;
1987 }
1988 
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)1989 angle::Result UtilsVk::setupGraphicsProgram(ContextVk *contextVk,
1990                                             Function function,
1991                                             const vk::ShaderModulePtr &vsShader,
1992                                             const vk::ShaderModulePtr &fsShader,
1993                                             GraphicsShaderProgramAndPipelines *programAndPipelines,
1994                                             const vk::GraphicsPipelineDesc *pipelineDesc,
1995                                             const VkDescriptorSet descriptorSet,
1996                                             const void *pushConstants,
1997                                             size_t pushConstantsSize,
1998                                             vk::RenderPassCommandBuffer *commandBuffer)
1999 {
2000     ASSERT(function < Function::ComputeStartIndex);
2001 
2002     return setupGraphicsProgramWithLayout(
2003         contextVk, *mPipelineLayouts[function], vsShader, fsShader, programAndPipelines,
2004         pipelineDesc, descriptorSet, pushConstants, pushConstantsSize, commandBuffer);
2005 }
2006 
convertIndexBuffer(ContextVk * contextVk,vk::BufferHelper * dst,vk::BufferHelper * src,const ConvertIndexParameters & params)2007 angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
2008                                           vk::BufferHelper *dst,
2009                                           vk::BufferHelper *src,
2010                                           const ConvertIndexParameters &params)
2011 {
2012     ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk));
2013 
2014     vk::CommandBufferAccess access;
2015     access.onBufferComputeShaderRead(src);
2016     access.onBufferComputeShaderWrite(dst);
2017 
2018     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2019     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2020     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2021     commandBuffer = &commandBufferHelper->getCommandBuffer();
2022 
2023     VkDescriptorSet descriptorSet;
2024     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::ConvertIndexBuffer,
2025                                     &descriptorSet));
2026 
2027     std::array<VkDescriptorBufferInfo, 2> buffers = {{
2028         {dst->getBuffer().getHandle(), dst->getOffset(), dst->getSize()},
2029         {src->getBuffer().getHandle(), src->getOffset(), src->getSize()},
2030     }};
2031 
2032     VkWriteDescriptorSet writeInfo = {};
2033     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2034     writeInfo.dstSet               = descriptorSet;
2035     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
2036     writeInfo.descriptorCount      = 2;
2037     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2038     writeInfo.pBufferInfo          = buffers.data();
2039 
2040     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2041 
2042     ConvertIndexShaderParams shaderParams = {params.srcOffset, params.dstOffset >> 2,
2043                                              params.maxIndex, 0};
2044 
2045     uint32_t flags = 0;
2046     if (contextVk->getState().isPrimitiveRestartEnabled())
2047     {
2048         flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
2049     }
2050 
2051     vk::ShaderModulePtr shader;
2052     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
2053 
2054     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexBuffer, shader,
2055                                   &mConvertIndex[flags], descriptorSet, &shaderParams,
2056                                   sizeof(ConvertIndexShaderParams), commandBufferHelper));
2057 
2058     constexpr uint32_t kInvocationsPerGroup = 64;
2059     constexpr uint32_t kInvocationsPerIndex = 2;
2060     const uint32_t kIndexCount              = params.maxIndex;
2061     const uint32_t kGroupCount =
2062         UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
2063     commandBuffer->dispatch(kGroupCount, 1, 1);
2064 
2065     return angle::Result::Continue;
2066 }
2067 
convertIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuf,vk::BufferHelper * srcIndexBuf,vk::BufferHelper * dstIndirectBuf,vk::BufferHelper * dstIndexBuf,const ConvertIndexIndirectParameters & params)2068 angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
2069                                                   vk::BufferHelper *srcIndirectBuf,
2070                                                   vk::BufferHelper *srcIndexBuf,
2071                                                   vk::BufferHelper *dstIndirectBuf,
2072                                                   vk::BufferHelper *dstIndexBuf,
2073                                                   const ConvertIndexIndirectParameters &params)
2074 {
2075     ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk));
2076 
2077     vk::CommandBufferAccess access;
2078     access.onBufferComputeShaderRead(srcIndirectBuf);
2079     access.onBufferComputeShaderRead(srcIndexBuf);
2080     access.onBufferComputeShaderWrite(dstIndirectBuf);
2081     access.onBufferComputeShaderWrite(dstIndexBuf);
2082 
2083     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2084     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2085     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2086     commandBuffer = &commandBufferHelper->getCommandBuffer();
2087 
2088     VkDescriptorSet descriptorSet;
2089     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
2090                                     Function::ConvertIndexIndirectBuffer, &descriptorSet));
2091 
2092     std::array<VkDescriptorBufferInfo, 4> buffers = {{
2093         {dstIndexBuf->getBuffer().getHandle(), dstIndexBuf->getOffset(), dstIndexBuf->getSize()},
2094         {srcIndexBuf->getBuffer().getHandle(), srcIndexBuf->getOffset(), srcIndexBuf->getSize()},
2095         {srcIndirectBuf->getBuffer().getHandle(), srcIndirectBuf->getOffset(),
2096          srcIndirectBuf->getSize()},
2097         {dstIndirectBuf->getBuffer().getHandle(), dstIndirectBuf->getOffset(),
2098          dstIndirectBuf->getSize()},
2099     }};
2100 
2101     VkWriteDescriptorSet writeInfo = {};
2102     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2103     writeInfo.dstSet               = descriptorSet;
2104     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
2105     writeInfo.descriptorCount      = 4;
2106     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2107     writeInfo.pBufferInfo          = buffers.data();
2108 
2109     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2110 
2111     ConvertIndexIndirectShaderParams shaderParams = {
2112         params.srcIndirectBufOffset >> 2, params.srcIndexBufOffset, params.dstIndexBufOffset >> 2,
2113         params.maxIndex, params.dstIndirectBufOffset >> 2};
2114 
2115     uint32_t flags = vk::InternalShader::ConvertIndex_comp::kIsIndirect;
2116     if (contextVk->getState().isPrimitiveRestartEnabled())
2117     {
2118         flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
2119     }
2120 
2121     vk::ShaderModulePtr shader;
2122     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
2123 
2124     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader,
2125                                   &mConvertIndex[flags], descriptorSet, &shaderParams,
2126                                   sizeof(ConvertIndexIndirectShaderParams), commandBufferHelper));
2127 
2128     constexpr uint32_t kInvocationsPerGroup = 64;
2129     constexpr uint32_t kInvocationsPerIndex = 2;
2130     const uint32_t kIndexCount              = params.maxIndex;
2131     const uint32_t kGroupCount =
2132         UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
2133     commandBuffer->dispatch(kGroupCount, 1, 1);
2134 
2135     return angle::Result::Continue;
2136 }
2137 
convertLineLoopIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * srcIndexBuffer,vk::BufferHelper * dstIndirectBuffer,vk::BufferHelper * dstIndexBuffer,const ConvertLineLoopIndexIndirectParameters & params)2138 angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
2139     ContextVk *contextVk,
2140     vk::BufferHelper *srcIndirectBuffer,
2141     vk::BufferHelper *srcIndexBuffer,
2142     vk::BufferHelper *dstIndirectBuffer,
2143     vk::BufferHelper *dstIndexBuffer,
2144     const ConvertLineLoopIndexIndirectParameters &params)
2145 {
2146     ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk));
2147 
2148     vk::CommandBufferAccess access;
2149     access.onBufferComputeShaderRead(srcIndirectBuffer);
2150     access.onBufferComputeShaderRead(srcIndexBuffer);
2151     access.onBufferComputeShaderWrite(dstIndirectBuffer);
2152     access.onBufferComputeShaderWrite(dstIndexBuffer);
2153 
2154     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2155     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2156     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2157     commandBuffer = &commandBufferHelper->getCommandBuffer();
2158 
2159     VkDescriptorSet descriptorSet;
2160     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
2161                                     Function::ConvertIndexIndirectLineLoopBuffer, &descriptorSet));
2162 
2163     std::array<VkDescriptorBufferInfo, 4> buffers = {{
2164         {dstIndexBuffer->getBuffer().getHandle(), dstIndexBuffer->getOffset(),
2165          dstIndexBuffer->getSize()},
2166         {srcIndexBuffer->getBuffer().getHandle(), srcIndexBuffer->getOffset(),
2167          srcIndexBuffer->getSize()},
2168         {srcIndirectBuffer->getBuffer().getHandle(), srcIndirectBuffer->getOffset(),
2169          srcIndirectBuffer->getSize()},
2170         {dstIndirectBuffer->getBuffer().getHandle(), dstIndirectBuffer->getOffset(),
2171          dstIndirectBuffer->getSize()},
2172     }};
2173 
2174     VkWriteDescriptorSet writeInfo = {};
2175     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2176     writeInfo.dstSet               = descriptorSet;
2177     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
2178     writeInfo.descriptorCount      = 4;
2179     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2180     writeInfo.pBufferInfo          = buffers.data();
2181 
2182     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2183 
2184     ConvertIndexIndirectLineLoopShaderParams shaderParams = {
2185         params.indirectBufferOffset >> 2, params.dstIndirectBufferOffset >> 2,
2186         params.srcIndexBufferOffset, params.dstIndexBufferOffset >> 2,
2187         contextVk->getState().isPrimitiveRestartEnabled()};
2188 
2189     uint32_t flags = GetConvertIndexIndirectLineLoopFlag(params.indicesBitsWidth);
2190 
2191     vk::ShaderModulePtr shader;
2192     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndexIndirectLineLoop_comp(contextVk, flags,
2193                                                                                  &shader));
2194 
2195     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader,
2196                                   &mConvertIndexIndirectLineLoop[flags], descriptorSet,
2197                                   &shaderParams, sizeof(ConvertIndexIndirectLineLoopShaderParams),
2198                                   commandBufferHelper));
2199 
2200     commandBuffer->dispatch(1, 1, 1);
2201 
2202     return angle::Result::Continue;
2203 }
2204 
convertLineLoopArrayIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * dstIndirectBuffer,vk::BufferHelper * dstIndexBuffer,const ConvertLineLoopArrayIndirectParameters & params)2205 angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer(
2206     ContextVk *contextVk,
2207     vk::BufferHelper *srcIndirectBuffer,
2208     vk::BufferHelper *dstIndirectBuffer,
2209     vk::BufferHelper *dstIndexBuffer,
2210     const ConvertLineLoopArrayIndirectParameters &params)
2211 {
2212     ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk));
2213 
2214     vk::CommandBufferAccess access;
2215     access.onBufferComputeShaderRead(srcIndirectBuffer);
2216     access.onBufferComputeShaderWrite(dstIndirectBuffer);
2217     access.onBufferComputeShaderWrite(dstIndexBuffer);
2218 
2219     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2220     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2221     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2222     commandBuffer = &commandBufferHelper->getCommandBuffer();
2223 
2224     VkDescriptorSet descriptorSet;
2225     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
2226                                     Function::ConvertIndirectLineLoopBuffer, &descriptorSet));
2227 
2228     std::array<VkDescriptorBufferInfo, 3> buffers = {{
2229         {srcIndirectBuffer->getBuffer().getHandle(), srcIndirectBuffer->getOffset(),
2230          srcIndirectBuffer->getSize()},
2231         {dstIndirectBuffer->getBuffer().getHandle(), dstIndirectBuffer->getOffset(),
2232          dstIndirectBuffer->getSize()},
2233         {dstIndexBuffer->getBuffer().getHandle(), dstIndexBuffer->getOffset(),
2234          dstIndexBuffer->getSize()},
2235     }};
2236 
2237     VkWriteDescriptorSet writeInfo = {};
2238     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2239     writeInfo.dstSet               = descriptorSet;
2240     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
2241     writeInfo.descriptorCount      = 3;
2242     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2243     writeInfo.pBufferInfo          = buffers.data();
2244 
2245     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2246 
2247     ConvertIndirectLineLoopShaderParams shaderParams = {params.indirectBufferOffset >> 2,
2248                                                         params.dstIndirectBufferOffset >> 2,
2249                                                         params.dstIndexBufferOffset >> 2};
2250 
2251     uint32_t flags = 0;
2252 
2253     vk::ShaderModulePtr shader;
2254     ANGLE_TRY(
2255         contextVk->getShaderLibrary().getConvertIndirectLineLoop_comp(contextVk, flags, &shader));
2256 
2257     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndirectLineLoopBuffer, shader,
2258                                   &mConvertIndirectLineLoop[flags], descriptorSet, &shaderParams,
2259                                   sizeof(ConvertIndirectLineLoopShaderParams),
2260                                   commandBufferHelper));
2261 
2262     commandBuffer->dispatch(1, 1, 1);
2263 
2264     return angle::Result::Continue;
2265 }
2266 
2267 // Used to clear a layer of a renderable texture in part or whole (EXT_clear_texture).
clearTexture(ContextVk * contextVk,vk::ImageHelper * dst,ClearTextureParameters & params)2268 angle::Result UtilsVk::clearTexture(ContextVk *contextVk,
2269                                     vk::ImageHelper *dst,
2270                                     ClearTextureParameters &params)
2271 {
2272     const angle::Format &dstActualFormat = dst->getActualFormat();
2273     bool isDepthOrStencil                = dstActualFormat.hasDepthOrStencilBits();
2274     bool isFormatDS                      = dstActualFormat.hasDepthAndStencilBits();
2275 
2276     vk::DeviceScoped<vk::ImageView> destView(contextVk->getDevice());
2277     const gl::TextureType destViewType = vk::Get2DTextureType(1, dst->getSamples());
2278 
2279     ANGLE_TRY(dst->initLayerImageView(contextVk, destViewType, params.aspectFlags,
2280                                       gl::SwizzleState(), &destView.get(), params.level, 1,
2281                                       params.layer, 1));
2282 
2283     gl::Rectangle renderArea = {};
2284     renderArea.x             = params.clearArea.x;
2285     renderArea.y             = params.clearArea.y;
2286     renderArea.width         = params.clearArea.width;
2287     renderArea.height        = params.clearArea.height;
2288 
2289     vk::RenderPassDesc renderPassDesc;
2290     renderPassDesc.setSamples(dst->getSamples());
2291 
2292     if (!isDepthOrStencil)
2293     {
2294         renderPassDesc.packColorAttachment(0, dstActualFormat.id);
2295     }
2296     else
2297     {
2298         renderPassDesc.packDepthStencilAttachment(dstActualFormat.id);
2299     }
2300     vk::RenderPassCommandBuffer *commandBuffer;
2301     vk::ImageLayout imageLayout =
2302         isDepthOrStencil ? vk::ImageLayout::DepthWriteStencilWrite : vk::ImageLayout::ColorWrite;
2303 
2304     ANGLE_TRY(startRenderPass(contextVk, dst, &destView.get(), renderPassDesc, renderArea,
2305                               params.aspectFlags, &params.clearValue,
2306                               vk::RenderPassSource::InternalUtils, &commandBuffer));
2307 
2308     // If the format contains both depth and stencil, the barrier aspect mask for the image should
2309     // include both bits.
2310     contextVk->onImageRenderPassWrite(
2311         dst->toGLLevel(params.level), params.layer, 1,
2312         isFormatDS ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : params.aspectFlags,
2313         imageLayout, dst);
2314 
2315     vk::ImageView destViewObject = destView.release();
2316     contextVk->addGarbage(&destViewObject);
2317 
2318     // Close the render pass for this temporary framebuffer. If the render pass is not immediately
2319     // closed and the render area grows due to scissor change, the clear area unexpectedly changes.
2320     // This can be avoided if the scissor code takes LOAD_OP_CLEAR into account before deciding to
2321     // grow the render pass's render area.
2322     return contextVk->flushCommandsAndEndRenderPass(
2323         RenderPassClosureReason::TemporaryForClearTexture);
2324 }
2325 
convertVertexBuffer(ContextVk * contextVk,vk::BufferHelper * dst,vk::BufferHelper * src,const ConvertVertexParameters & params,const OffsetAndVertexCounts & additionalOffsetVertexCounts)2326 angle::Result UtilsVk::convertVertexBuffer(
2327     ContextVk *contextVk,
2328     vk::BufferHelper *dst,
2329     vk::BufferHelper *src,
2330     const ConvertVertexParameters &params,
2331     const OffsetAndVertexCounts &additionalOffsetVertexCounts)
2332 {
2333     vk::CommandBufferAccess access;
2334     access.onBufferComputeShaderRead(src);
2335     access.onBufferComputeShaderWrite(dst);
2336 
2337     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2338     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2339 
2340     ConvertVertexShaderParams shaderParams;
2341     shaderParams.Ns = params.srcFormat->channelCount;
2342     shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount;
2343     shaderParams.Ss = static_cast<uint32_t>(params.srcStride);
2344     shaderParams.Nd = params.dstFormat->channelCount;
2345     shaderParams.Bd = params.dstFormat->pixelBytes / params.dstFormat->channelCount;
2346     shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
2347     // The component size is expected to either be 1, 2 or 4 bytes.
2348     ASSERT(4 % shaderParams.Bs == 0);
2349     ASSERT(4 % shaderParams.Bd == 0);
2350     shaderParams.Es = 4 / shaderParams.Bs;
2351     shaderParams.Ed = 4 / shaderParams.Bd;
2352     // Total number of output components is simply the number of vertices by number of components in
2353     // each.
2354     shaderParams.componentCount = static_cast<uint32_t>(params.vertexCount * shaderParams.Nd);
2355     // Total number of 4-byte outputs is the number of components divided by how many components can
2356     // fit in a 4-byte value.  Note that this value is also the invocation size of the shader.
2357     shaderParams.outputCount = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
2358     shaderParams.srcOffset   = static_cast<uint32_t>(params.srcOffset);
2359     shaderParams.dstOffset   = static_cast<uint32_t>(params.dstOffset);
2360 
2361     bool isSrcA2BGR10 =
2362         params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt2101010 ||
2363         params.srcFormat->vertexAttribType == gl::VertexAttribType::Int2101010;
2364     bool isSrcRGB10A2 =
2365         params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt1010102 ||
2366         params.srcFormat->vertexAttribType == gl::VertexAttribType::Int1010102;
2367 
2368     shaderParams.isSrcHDR     = isSrcA2BGR10 || isSrcRGB10A2;
2369     shaderParams.isSrcA2BGR10 = isSrcA2BGR10;
2370 
2371     uint32_t flags = GetConvertVertexFlags(params);
2372 
2373     // See GLES3.0 section 2.9.1 Transferring Array Elements
2374     const uint32_t srcValueBits = shaderParams.isSrcHDR ? 2 : shaderParams.Bs * 8;
2375     const uint32_t srcValueMask =
2376         srcValueBits == 32 ? 0xFFFFFFFFu : angle::BitMask<uint32_t>(srcValueBits);
2377     switch (flags)
2378     {
2379         case ConvertVertex_comp::kSintToSint:
2380         case ConvertVertex_comp::kSintToFloat:
2381         case ConvertVertex_comp::kUintToFloat:
2382             // For integers, alpha should take a value of 1.
2383             shaderParams.srcEmulatedAlpha = 1;
2384             break;
2385 
2386         case ConvertVertex_comp::kUintToUint:
2387             // For integers, alpha should take a value of 1.  However, uint->uint is also used to
2388             // add channels to RGB snorm, unorm and half formats.
2389             if (params.dstFormat->isSnorm())
2390             {
2391                 // See case ConvertVertex_comp::kSnormToFloat below.
2392                 shaderParams.srcEmulatedAlpha = srcValueMask >> 1;
2393             }
2394             else if (params.dstFormat->isUnorm())
2395             {
2396                 // See case ConvertVertex_comp::kUnormToFloat below.
2397                 shaderParams.srcEmulatedAlpha = srcValueMask;
2398             }
2399             else if (params.dstFormat->isVertexTypeHalfFloat())
2400             {
2401                 shaderParams.srcEmulatedAlpha = gl::Float16One;
2402             }
2403             else
2404             {
2405                 shaderParams.srcEmulatedAlpha = 1;
2406             }
2407             break;
2408 
2409         case ConvertVertex_comp::kSnormToFloat:
2410             // The largest signed number with as many bits as the alpha channel of the source is
2411             // 0b011...1 which is srcValueMask >> 1
2412             shaderParams.srcEmulatedAlpha = srcValueMask >> 1;
2413             break;
2414 
2415         case ConvertVertex_comp::kUnormToFloat:
2416             // The largest unsigned number with as many bits as the alpha channel of the source is
2417             // 0b11...1 which is srcValueMask
2418             shaderParams.srcEmulatedAlpha = srcValueMask;
2419             break;
2420 
2421         case ConvertVertex_comp::kFixedToFloat:
2422             // 1.0 in fixed point is 0x10000
2423             shaderParams.srcEmulatedAlpha = 0x10000;
2424             break;
2425 
2426         case ConvertVertex_comp::kFloatToFloat:
2427             ASSERT(ValidateFloatOneAsUint());
2428             shaderParams.srcEmulatedAlpha = gl::Float32One;
2429             break;
2430 
2431         default:
2432             UNREACHABLE();
2433     }
2434 
2435     return convertVertexBufferImpl(contextVk, dst, src, flags, commandBufferHelper, shaderParams,
2436                                    additionalOffsetVertexCounts);
2437 }
2438 
convertVertexBufferImpl(ContextVk * contextVk,vk::BufferHelper * dst,vk::BufferHelper * src,uint32_t flags,vk::OutsideRenderPassCommandBufferHelper * commandBufferHelper,const ConvertVertexShaderParams & shaderParams,const OffsetAndVertexCounts & additionalOffsetVertexCounts)2439 angle::Result UtilsVk::convertVertexBufferImpl(
2440     ContextVk *contextVk,
2441     vk::BufferHelper *dst,
2442     vk::BufferHelper *src,
2443     uint32_t flags,
2444     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper,
2445     const ConvertVertexShaderParams &shaderParams,
2446     const OffsetAndVertexCounts &additionalOffsetVertexCounts)
2447 {
2448     ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk));
2449 
2450     vk::OutsideRenderPassCommandBuffer *commandBuffer;
2451     commandBuffer = &commandBufferHelper->getCommandBuffer();
2452 
2453     VkDescriptorSet descriptorSet;
2454     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::ConvertVertexBuffer,
2455                                     &descriptorSet));
2456 
2457     // ConvertVertexBuffer writes whole 4 bytes to dstOffset. Caller must ensure dstOffset is
2458     // aligned on 4 bytes boundary.
2459     ASSERT(dst->getOffset() % 4 == 0);
2460 
2461     VkWriteDescriptorSet writeInfo    = {};
2462     VkDescriptorBufferInfo buffers[2] = {
2463         {dst->getBuffer().getHandle(), dst->getOffset(), dst->getSize()},
2464         {src->getBuffer().getHandle(), src->getOffset(), src->getSize()},
2465     };
2466     static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
2467                   "Update write info");
2468 
2469     writeInfo.sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2470     writeInfo.dstSet          = descriptorSet;
2471     writeInfo.dstBinding      = kConvertVertexDestinationBinding;
2472     writeInfo.descriptorCount = 2;
2473     writeInfo.descriptorType  = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2474     writeInfo.pBufferInfo     = buffers;
2475 
2476     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2477 
2478     vk::ShaderModulePtr shader;
2479     ANGLE_TRY(contextVk->getShaderLibrary().getConvertVertex_comp(contextVk, flags, &shader));
2480 
2481     ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertVertexBuffer, shader,
2482                                   &mConvertVertex[flags], descriptorSet, &shaderParams,
2483                                   sizeof(shaderParams), commandBufferHelper));
2484 
2485     commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
2486 
2487     if (!additionalOffsetVertexCounts.empty())
2488     {
2489         ConvertVertexShaderParams constants = shaderParams;
2490 
2491         for (const OffsetAndVertexCount &offsetAndVertexCount : additionalOffsetVertexCounts)
2492         {
2493             // Total number of output components is simply the number of vertices by number of
2494             // components in each.
2495             constants.componentCount =
2496                 static_cast<uint32_t>(offsetAndVertexCount.vertexCount * shaderParams.Nd);
2497             // Total number of 4-byte outputs is the number of components divided by how many
2498             // components can fit in a 4-byte value.  Note that this value is also the invocation
2499             // size of the shader.
2500             constants.outputCount = UnsignedCeilDivide(constants.componentCount, shaderParams.Ed);
2501             constants.srcOffset   = static_cast<uint32_t>(offsetAndVertexCount.srcOffset);
2502             constants.dstOffset   = static_cast<uint32_t>(offsetAndVertexCount.dstOffset);
2503 
2504             commandBuffer->pushConstants(*mPipelineLayouts[Function::ConvertVertexBuffer],
2505                                          VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(constants),
2506                                          &constants);
2507             // Since multiple compute dispatch all convert from the same srcBuffer and write to the
2508             // same dstBuffer, even if the ranges overlap, they should end up with writing the same
2509             // values, thus no barrier is needed here.
2510             commandBuffer->dispatch(UnsignedCeilDivide(constants.outputCount, 64), 1, 1);
2511         }
2512     }
2513 
2514     return angle::Result::Continue;
2515 }
2516 
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)2517 angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
2518                                        vk::ImageHelper *image,
2519                                        const vk::ImageView *imageView,
2520                                        const vk::RenderPassDesc &renderPassDesc,
2521                                        const gl::Rectangle &renderArea,
2522                                        const VkImageAspectFlags aspectFlags,
2523                                        const VkClearValue *clearValue,
2524                                        vk::RenderPassSource renderPassSource,
2525                                        vk::RenderPassCommandBuffer **commandBufferOut)
2526 {
2527     ASSERT(aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT ||
2528            (aspectFlags & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0);
2529     vk::ImageLayout imageLayout = aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT
2530                                       ? vk::ImageLayout::ColorWrite
2531                                       : vk::ImageLayout::DepthWriteStencilWrite;
2532     vk::Framebuffer framebuffer;
2533     vk::Framebuffer framebufferHandle;
2534     vk::RenderPassFramebuffer renderPassFramebuffer;
2535 
2536     const uint32_t framebufferWidth    = renderArea.x + renderArea.width;
2537     const uint32_t framebufferHeight   = renderArea.y + renderArea.height;
2538     const uint32_t framebufferLayers   = 1;
2539     vk::ImagelessFramebuffer imageless = vk::ImagelessFramebuffer::Yes;
2540 
2541     if (!contextVk->getFeatures().preferDynamicRendering.enabled)
2542     {
2543         imageless = vk::ImagelessFramebuffer::No;
2544 
2545         const vk::RenderPass *compatibleRenderPass = nullptr;
2546         ANGLE_TRY(contextVk->getCompatibleRenderPass(renderPassDesc, &compatibleRenderPass));
2547 
2548         VkFramebufferCreateInfo framebufferInfo = {};
2549 
2550         // Minimize the framebuffer coverage to only cover up to the render area.
2551         framebufferInfo.sType           = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2552         framebufferInfo.flags           = 0;
2553         framebufferInfo.renderPass      = compatibleRenderPass->getHandle();
2554         framebufferInfo.attachmentCount = 1;
2555         framebufferInfo.pAttachments    = imageView->ptr();
2556         framebufferInfo.width           = framebufferWidth;
2557         framebufferInfo.height          = framebufferHeight;
2558         framebufferInfo.layers          = framebufferLayers;
2559 
2560         ANGLE_VK_TRY(contextVk, framebuffer.init(contextVk->getDevice(), framebufferInfo));
2561 
2562         framebufferHandle.setHandle(framebuffer.getHandle());
2563     }
2564 
2565     renderPassFramebuffer.setFramebuffer(
2566         contextVk, std::move(framebufferHandle), {imageView->getHandle()}, framebufferWidth,
2567         framebufferHeight, framebufferLayers, imageless, renderPassSource);
2568 
2569     // If a clear value has been provided, the load op is set to clear.
2570     vk::AttachmentOpsArray renderPassAttachmentOps;
2571     vk::PackedClearValuesArray clearValues;
2572     VkClearValue attachmentClearValue = {};
2573 
2574     if (clearValue == nullptr)
2575     {
2576         renderPassAttachmentOps.initWithLoadStore(vk::kAttachmentIndexZero, imageLayout,
2577                                                   imageLayout);
2578     }
2579     else
2580     {
2581         attachmentClearValue = *clearValue;
2582         renderPassAttachmentOps.setLayouts(vk::kAttachmentIndexZero, imageLayout, imageLayout);
2583         renderPassAttachmentOps.setClearOp(vk::kAttachmentIndexZero);
2584         renderPassAttachmentOps.setClearStencilOp(vk::kAttachmentIndexZero);
2585     }
2586 
2587     if (aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT)
2588     {
2589         clearValues.storeColor(vk::kAttachmentIndexZero, attachmentClearValue);
2590     }
2591     else
2592     {
2593         clearValues.storeDepthStencil(vk::kAttachmentIndexZero, attachmentClearValue);
2594     }
2595 
2596     ANGLE_TRY(contextVk->beginNewRenderPass(
2597         std::move(renderPassFramebuffer), renderArea, renderPassDesc, renderPassAttachmentOps,
2598         vk::PackedAttachmentCount(1), vk::kAttachmentIndexInvalid, clearValues, commandBufferOut));
2599 
2600     contextVk->addGarbage(&framebuffer);
2601 
2602     return angle::Result::Continue;
2603 }
2604 
clearFramebuffer(ContextVk * contextVk,FramebufferVk * framebuffer,const ClearFramebufferParameters & params)2605 angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
2606                                         FramebufferVk *framebuffer,
2607                                         const ClearFramebufferParameters &params)
2608 {
2609     vk::Renderer *renderer = contextVk->getRenderer();
2610 
2611     ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
2612 
2613     const gl::Rectangle &scissoredRenderArea = params.clearArea;
2614     vk::RenderPassCommandBuffer *commandBuffer;
2615 
2616     // Start a new render pass if not already started
2617     if (contextVk->hasActiveRenderPass() &&
2618         contextVk->hasStartedRenderPassWithQueueSerial(framebuffer->getLastRenderPassQueueSerial()))
2619     {
2620         vk::RenderPassCommandBufferHelper *renderPassCommands =
2621             &contextVk->getStartedRenderPassCommands();
2622         renderPassCommands->growRenderArea(contextVk, scissoredRenderArea);
2623 
2624         commandBuffer = &renderPassCommands->getCommandBuffer();
2625     }
2626     else
2627     {
2628         // Deferred clears should be handled already.
2629         ASSERT(!framebuffer->hasDeferredClears());
2630         ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer, nullptr));
2631     }
2632 
2633     UpdateColorAccess(contextVk, framebuffer->getState().getColorAttachmentsMask(),
2634                       MakeColorBufferMask(params.colorAttachmentIndexGL));
2635     UpdateDepthStencilAccess(contextVk, params.clearDepth, params.clearStencil);
2636 
2637     ImageClearShaderParams shaderParams;
2638     shaderParams.clearValue = params.colorClearValue;
2639     shaderParams.clearDepth = params.depthStencilClearValue.depth;
2640 
2641     vk::GraphicsPipelineDesc pipelineDesc;
2642     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
2643                               contextVk->pipelineRobustness(),
2644                               contextVk->pipelineProtectedAccess());
2645     pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
2646     pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags);
2647     pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
2648     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
2649     // Clears can be done on a currently open render pass, so make sure the correct subpass index is
2650     // used.
2651     pipelineDesc.setSubpass(contextVk->getCurrentSubpassIndex());
2652 
2653     // Clear depth by enabling depth clamping and setting the viewport depth range to the clear
2654     // value if possible.  Otherwise use the shader to export depth.
2655     const bool supportsDepthClamp = renderer->getPhysicalDeviceFeatures().depthClamp == VK_TRUE;
2656     if (params.clearDepth)
2657     {
2658         SetDepthStateForWrite(renderer, &pipelineDesc);
2659         if (supportsDepthClamp)
2660         {
2661             // Note: this path requires the depthClamp Vulkan feature.
2662             pipelineDesc.setDepthClampEnabled(true);
2663         }
2664     }
2665 
2666     // Clear stencil by enabling stencil write with the right mask.
2667     if (params.clearStencil)
2668     {
2669         SetStencilStateForWrite(renderer, &pipelineDesc);
2670     }
2671 
2672     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
2673     vk::ShaderModulePtr vertexShader;
2674     vk::ShaderModulePtr fragmentShader;
2675     GraphicsShaderProgramAndPipelines *imageClearProgramAndPipelines = &mImageClearVSOnly;
2676 
2677     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
2678     if (params.clearColor)
2679     {
2680         const uint32_t flags =
2681             GetImageClearFlags(*params.colorFormat, params.colorAttachmentIndexGL,
2682                                params.clearDepth && !supportsDepthClamp);
2683         ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
2684         imageClearProgramAndPipelines = &mImageClear[flags];
2685     }
2686 
2687     // Make sure transform feedback is paused.  Needs to be done before binding the pipeline as
2688     // that's not allowed in Vulkan.
2689     const bool isTransformFeedbackActiveUnpaused =
2690         contextVk->getStartedRenderPassCommands().isTransformFeedbackActiveUnpaused();
2691     contextVk->pauseTransformFeedbackIfActiveUnpaused();
2692 
2693     ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageClear, vertexShader, fragmentShader,
2694                                    imageClearProgramAndPipelines, &pipelineDesc, VK_NULL_HANDLE,
2695                                    &shaderParams, sizeof(shaderParams), commandBuffer));
2696 
2697     // Set dynamic state
2698     VkViewport viewport;
2699     gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
2700     bool invertViewport              = contextVk->isViewportFlipEnabledForDrawFBO();
2701     bool clipSpaceOriginUpperLeft =
2702         contextVk->getState().getClipOrigin() == gl::ClipOrigin::UpperLeft;
2703     // Set depth range to clear value.  If clearing depth, the vertex shader depth output is clamped
2704     // to this value, thus clearing the depth buffer to the desired clear value.
2705     const float clearDepthValue = params.depthStencilClearValue.depth;
2706     gl_vk::GetViewport(completeRenderArea, clearDepthValue, clearDepthValue, invertViewport,
2707                        clipSpaceOriginUpperLeft, completeRenderArea.height, &viewport);
2708     commandBuffer->setViewport(0, 1, &viewport);
2709 
2710     const VkRect2D scissor = gl_vk::GetRect(params.clearArea);
2711     commandBuffer->setScissor(0, 1, &scissor);
2712 
2713     if (params.clearDepth)
2714     {
2715         SetDepthDynamicStateForWrite(renderer, commandBuffer);
2716     }
2717     else
2718     {
2719         SetDepthDynamicStateForUnused(renderer, commandBuffer);
2720     }
2721 
2722     if (params.clearStencil)
2723     {
2724         constexpr uint8_t kCompareMask = 0xFF;
2725         const uint8_t clearStencilValue =
2726             static_cast<uint8_t>(params.depthStencilClearValue.stencil);
2727 
2728         commandBuffer->setStencilCompareMask(kCompareMask, kCompareMask);
2729         commandBuffer->setStencilWriteMask(params.stencilMask, params.stencilMask);
2730         commandBuffer->setStencilReference(clearStencilValue, clearStencilValue);
2731 
2732         SetStencilDynamicStateForWrite(renderer, commandBuffer);
2733     }
2734     else
2735     {
2736         SetStencilDynamicStateForUnused(renderer, commandBuffer);
2737     }
2738 
2739     ASSERT(contextVk->hasStartedRenderPassWithQueueSerial(
2740         framebuffer->getLastRenderPassQueueSerial()));
2741     // Make sure this draw call doesn't count towards occlusion query results.
2742     contextVk->pauseRenderPassQueriesIfActive();
2743     commandBuffer->draw(3, 0);
2744     ANGLE_TRY(contextVk->resumeRenderPassQueriesIfActive());
2745 
2746     // If transform feedback was active, we can't pause and resume it in the same render pass
2747     // because we can't insert a memory barrier for the counter buffers.  In that case, break the
2748     // render pass.
2749     if (isTransformFeedbackActiveUnpaused)
2750     {
2751         ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
2752             RenderPassClosureReason::XfbResumeAfterDrawBasedClear));
2753     }
2754 
2755     return angle::Result::Continue;
2756 }
2757 
clearImage(ContextVk * contextVk,vk::ImageHelper * dst,const ClearImageParameters & params)2758 angle::Result UtilsVk::clearImage(ContextVk *contextVk,
2759                                   vk::ImageHelper *dst,
2760                                   const ClearImageParameters &params)
2761 {
2762     vk::Renderer *renderer = contextVk->getRenderer();
2763 
2764     ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
2765 
2766     const angle::Format &dstActualFormat = dst->getActualFormat();
2767 
2768     // Currently, this function is only used to clear emulated channels of color images.
2769     ASSERT(!dstActualFormat.hasDepthOrStencilBits());
2770 
2771     // TODO: currently this function is only implemented for images that are drawable.  If needed,
2772     // for images that are not drawable, the following algorithm can be used.
2773     //
2774     // - Copy image to temp buffer
2775     // - Use convertVertexBufferImpl to overwrite the alpha channel
2776     // - Copy the result back to the image
2777     //
2778     // Note that the following check is not enough; if the image is AHB-imported, then the draw path
2779     // cannot be taken if AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER hasn't been specified, even if the
2780     // format is renderable.
2781     //
2782     // http://anglebug.com/42264676
2783     if (!vk::FormatHasNecessaryFeature(renderer, dstActualFormat.id, dst->getTilingMode(),
2784                                        VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
2785     {
2786         UNIMPLEMENTED();
2787         return angle::Result::Continue;
2788     }
2789 
2790     vk::DeviceScoped<vk::ImageView> destView(contextVk->getDevice());
2791     const gl::TextureType destViewType = vk::Get2DTextureType(1, dst->getSamples());
2792 
2793     ANGLE_TRY(dst->initLayerImageView(contextVk, destViewType, VK_IMAGE_ASPECT_COLOR_BIT,
2794                                       gl::SwizzleState(), &destView.get(), params.dstMip, 1,
2795                                       params.dstLayer, 1));
2796 
2797     const gl::Rectangle &renderArea = params.clearArea;
2798 
2799     ImageClearShaderParams shaderParams;
2800     shaderParams.clearValue = params.colorClearValue;
2801     shaderParams.clearDepth = 0;
2802 
2803     vk::RenderPassDesc renderPassDesc;
2804     renderPassDesc.setSamples(dst->getSamples());
2805     renderPassDesc.packColorAttachment(0, dstActualFormat.id);
2806 
2807     vk::GraphicsPipelineDesc pipelineDesc;
2808     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
2809                               contextVk->pipelineRobustness(),
2810                               contextVk->pipelineProtectedAccess());
2811     pipelineDesc.setSingleColorWriteMask(0, params.colorMaskFlags);
2812     pipelineDesc.setRasterizationSamples(dst->getSamples());
2813     pipelineDesc.setRenderPassDesc(renderPassDesc);
2814 
2815     vk::RenderPassCommandBuffer *commandBuffer;
2816     ANGLE_TRY(startRenderPass(contextVk, dst, &destView.get(), renderPassDesc, renderArea,
2817                               VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
2818                               vk::RenderPassSource::InternalUtils, &commandBuffer));
2819 
2820     UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
2821 
2822     contextVk->onImageRenderPassWrite(dst->toGLLevel(params.dstMip), params.dstLayer, 1,
2823                                       VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorWrite, dst);
2824 
2825     const uint32_t flags = GetImageClearFlags(dstActualFormat, 0, false);
2826 
2827     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
2828     vk::ShaderModulePtr vertexShader;
2829     vk::ShaderModulePtr fragmentShader;
2830     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
2831     ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
2832 
2833     ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageClear, vertexShader, fragmentShader,
2834                                    &mImageClear[flags], &pipelineDesc, VK_NULL_HANDLE,
2835                                    &shaderParams, sizeof(shaderParams), commandBuffer));
2836 
2837     // Set dynamic state
2838     VkViewport viewport;
2839     gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dst->getExtents().height, &viewport);
2840     commandBuffer->setViewport(0, 1, &viewport);
2841 
2842     VkRect2D scissor = gl_vk::GetRect(renderArea);
2843     commandBuffer->setScissor(0, 1, &scissor);
2844 
2845     SetDepthDynamicStateForUnused(renderer, commandBuffer);
2846     SetStencilDynamicStateForUnused(renderer, commandBuffer);
2847 
2848     // Note: this utility creates its own framebuffer, thus bypassing ContextVk::startRenderPass.
2849     // As such, occlusion queries are not enabled.
2850     commandBuffer->draw(3, 0);
2851 
2852     vk::ImageView destViewObject = destView.release();
2853     contextVk->addGarbage(&destViewObject);
2854 
2855     // Close the render pass for this temporary framebuffer.
2856     return contextVk->flushCommandsAndEndRenderPass(
2857         RenderPassClosureReason::TemporaryForImageClear);
2858 }
2859 
colorBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcView,const BlitResolveParameters & params)2860 angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk,
2861                                         FramebufferVk *framebuffer,
2862                                         vk::ImageHelper *src,
2863                                         const vk::ImageView *srcView,
2864                                         const BlitResolveParameters &params)
2865 {
2866     // The views passed to this function are already retained, so a render pass cannot be already
2867     // open.  Otherwise, this function closes the render pass, which may incur a vkQueueSubmit and
2868     // then the views are used in a new command buffer without having been retained for it.
2869     // http://crbug.com/1272266#c22
2870     //
2871     // Note that depth/stencil views for blit are not derived from a |Resource| class and are
2872     // retained differently.
2873     ASSERT(!contextVk->hasActiveRenderPass());
2874 
2875     return blitResolveImpl(contextVk, framebuffer, src, srcView, nullptr, nullptr, params);
2876 }
2877 
depthStencilBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)2878 angle::Result UtilsVk::depthStencilBlitResolve(ContextVk *contextVk,
2879                                                FramebufferVk *framebuffer,
2880                                                vk::ImageHelper *src,
2881                                                const vk::ImageView *srcDepthView,
2882                                                const vk::ImageView *srcStencilView,
2883                                                const BlitResolveParameters &params)
2884 {
2885     return blitResolveImpl(contextVk, framebuffer, src, nullptr, srcDepthView, srcStencilView,
2886                            params);
2887 }
2888 
blitResolveImpl(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcColorView,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)2889 angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
2890                                        FramebufferVk *framebuffer,
2891                                        vk::ImageHelper *src,
2892                                        const vk::ImageView *srcColorView,
2893                                        const vk::ImageView *srcDepthView,
2894                                        const vk::ImageView *srcStencilView,
2895                                        const BlitResolveParameters &params)
2896 {
2897     // Possible ways to resolve color are:
2898     //
2899     // - vkCmdResolveImage: This is by far the easiest method, but lacks the ability to flip
2900     //   images during resolve.
2901     // - Manual resolve: A shader can read all samples from input, average them and output.
2902     // - Using subpass resolve attachment: A shader can transform the sample colors from source to
2903     //   destination coordinates and the subpass resolve would finish the job.
2904     //
2905     // The first method is unable to handle flipping, so it's not generally applicable.  The last
2906     // method would have been great were we able to modify the last render pass that rendered into
2907     // source, but still wouldn't be able to handle flipping.  The second method is implemented in
2908     // this function for complete control.
2909 
2910     // Possible ways to resolve depth/stencil are:
2911     //
2912     // - Manual resolve: A shader can read a samples from input and choose that for output.
2913     // - Using subpass resolve attachment through VkSubpassDescriptionDepthStencilResolveKHR: This
2914     //   requires an extension that's not very well supported.
2915     //
2916     // The first method is implemented in this function.
2917 
2918     // Possible ways to blit color, depth or stencil are:
2919     //
2920     // - vkCmdBlitImage: This function works if the source and destination formats have the blit
2921     //   feature.
2922     // - Manual blit: A shader can sample from the source image and write it to the destination.
2923     //
2924     // The first method has a serious shortcoming.  GLES allows blit parameters to exceed the
2925     // source or destination boundaries.  The actual blit is clipped to these limits, but the
2926     // scaling applied is determined solely by the input areas.  Vulkan requires the blit parameters
2927     // to be within the source and destination bounds.  This makes it hard to keep the scaling
2928     // constant.
2929     //
2930     // The second method is implemented in this function, which shares code with the resolve method.
2931     vk::Renderer *renderer = contextVk->getRenderer();
2932 
2933     ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
2934 
2935     bool isResolve = src->getSamples() > 1;
2936 
2937     BlitResolveShaderParams shaderParams;
2938     // Note: adjustments made for pre-rotatation in FramebufferVk::blit() affect these
2939     // Calculate*Offset() functions.
2940     if (isResolve)
2941     {
2942         CalculateResolveOffset(params, shaderParams.offset.resolve);
2943     }
2944     else
2945     {
2946         CalculateBlitOffset(params, shaderParams.offset.blit);
2947     }
2948     shaderParams.stretch[0]      = params.stretch[0];
2949     shaderParams.stretch[1]      = params.stretch[1];
2950     shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
2951     shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
2952     shaderParams.srcLayer        = params.srcLayer;
2953     shaderParams.samples         = src->getSamples();
2954     shaderParams.invSamples      = 1.0f / shaderParams.samples;
2955     shaderParams.outputMask      = framebuffer->getState().getEnabledDrawBuffers().bits();
2956     shaderParams.flipX           = params.flipX;
2957     shaderParams.flipY           = params.flipY;
2958     shaderParams.rotateXY        = 0;
2959 
2960     // Potentially make adjustments for pre-rotation.  Depending on the angle some of the
2961     // shaderParams need to be adjusted.
2962     switch (params.rotation)
2963     {
2964         case SurfaceRotation::Identity:
2965         case SurfaceRotation::Rotated90Degrees:
2966             break;
2967         case SurfaceRotation::Rotated180Degrees:
2968         case SurfaceRotation::Rotated270Degrees:
2969             if (isResolve)
2970             {
2971                 // Align the offset with minus 1, or the sample position near the edge will be
2972                 // wrong.
2973                 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0] - 1;
2974                 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1] - 1;
2975             }
2976             else
2977             {
2978                 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0];
2979                 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1];
2980             }
2981             break;
2982         default:
2983             UNREACHABLE();
2984             break;
2985     }
2986 
2987     shaderParams.rotateXY = IsRotatedAspectRatio(params.rotation);
2988 
2989     bool blitColor   = srcColorView != nullptr;
2990     bool blitDepth   = srcDepthView != nullptr;
2991     bool blitStencil = srcStencilView != nullptr;
2992 
2993     // Either color is blitted/resolved or depth/stencil, but not both.
2994     ASSERT(blitColor != (blitDepth || blitStencil));
2995 
2996     // Linear sampling is only valid with color blitting.
2997     ASSERT((blitColor && !isResolve) || !params.linear);
2998 
2999     uint32_t flags =
3000         GetBlitResolveFlags(blitColor, blitDepth, blitStencil, src->getIntendedFormat());
3001     flags |= src->getLayerCount() > 1 ? BlitResolve_frag::kSrcIsArray : 0;
3002     flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
3003     Function function = Function::BlitResolve;
3004 
3005     // Note: a different shader is used for 3D color blits, but otherwise the desc sets, parameters
3006     // etc are identical.
3007     const bool isSrc3D = src->getType() == VK_IMAGE_TYPE_3D;
3008     ASSERT(!isSrc3D || (blitColor && !isResolve));
3009     if (isSrc3D)
3010     {
3011         flags = GetFormatFlags(src->getIntendedFormat(), Blit3DSrc_frag::kBlitInt,
3012                                Blit3DSrc_frag::kBlitUint, Blit3DSrc_frag::kBlitFloat);
3013     }
3014 
3015     vk::GraphicsPipelineDesc pipelineDesc;
3016     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
3017                               contextVk->pipelineRobustness(),
3018                               contextVk->pipelineProtectedAccess());
3019     if (blitColor)
3020     {
3021         constexpr VkColorComponentFlags kAllColorComponents =
3022             VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
3023             VK_COLOR_COMPONENT_A_BIT;
3024 
3025         pipelineDesc.setColorWriteMasks(
3026             gl::BlendStateExt::ColorMaskStorage::GetReplicatedValue(
3027                 kAllColorComponents, gl::BlendStateExt::ColorMaskStorage::GetMask(
3028                                          framebuffer->getRenderPassDesc().colorAttachmentRange())),
3029             framebuffer->getEmulatedAlphaAttachmentMask(), ~gl::DrawBufferMask());
3030     }
3031     else
3032     {
3033         pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
3034     }
3035     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
3036     if (blitDepth)
3037     {
3038         SetDepthStateForWrite(renderer, &pipelineDesc);
3039     }
3040 
3041     if (blitStencil)
3042     {
3043         SetStencilStateForWrite(renderer, &pipelineDesc);
3044     }
3045 
3046     // All deferred clear must have been flushed, otherwise it will conflict with params.blitArea.
3047     ASSERT(!framebuffer->hasDeferredClears());
3048     vk::RenderPassCommandBuffer *commandBuffer;
3049     ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer, nullptr));
3050 
3051     VkDescriptorSet descriptorSet;
3052     ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
3053                                     Function::BlitResolve, &descriptorSet));
3054 
3055     // Pick layout consistent with GetImageReadLayout() to avoid unnecessary layout change.
3056     vk::ImageLayout srcImagelayout = src->isDepthOrStencil()
3057                                          ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead
3058                                          : vk::ImageLayout::FragmentShaderReadOnly;
3059     contextVk->onImageRenderPassRead(src->getAspectFlags(), srcImagelayout, src);
3060 
3061     UpdateColorAccess(contextVk, framebuffer->getState().getColorAttachmentsMask(),
3062                       framebuffer->getState().getEnabledDrawBuffers());
3063     UpdateDepthStencilAccess(contextVk, blitDepth, blitStencil);
3064 
3065     VkDescriptorImageInfo imageInfos[2] = {};
3066 
3067     if (blitColor)
3068     {
3069         imageInfos[0].imageView   = srcColorView->getHandle();
3070         imageInfos[0].imageLayout = src->getCurrentLayout(renderer);
3071     }
3072     if (blitDepth)
3073     {
3074         imageInfos[0].imageView   = srcDepthView->getHandle();
3075         imageInfos[0].imageLayout = src->getCurrentLayout(renderer);
3076     }
3077     if (blitStencil)
3078     {
3079         imageInfos[1].imageView   = srcStencilView->getHandle();
3080         imageInfos[1].imageLayout = src->getCurrentLayout(renderer);
3081     }
3082 
3083     VkDescriptorImageInfo samplerInfo = {};
3084     samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
3085 
3086     VkWriteDescriptorSet writeInfos[3] = {};
3087     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3088     writeInfos[0].dstSet               = descriptorSet;
3089     writeInfos[0].dstBinding           = kBlitResolveColorOrDepthBinding;
3090     writeInfos[0].descriptorCount      = 1;
3091     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3092     writeInfos[0].pImageInfo           = &imageInfos[0];
3093 
3094     writeInfos[1]            = writeInfos[0];
3095     writeInfos[1].dstBinding = kBlitResolveStencilBinding;
3096     writeInfos[1].pImageInfo = &imageInfos[1];
3097 
3098     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3099     writeInfos[2].dstSet          = descriptorSet;
3100     writeInfos[2].dstBinding      = kBlitResolveSamplerBinding;
3101     writeInfos[2].descriptorCount = 1;
3102     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
3103     writeInfos[2].pImageInfo      = &samplerInfo;
3104 
3105     // If resolving color, there's one write info; index 0
3106     // If resolving depth, write info index 0 must be written
3107     // If resolving stencil, write info index 1 must also be written
3108     //
3109     // Note again that resolving color and depth/stencil are mutually exclusive here.
3110     uint32_t writeInfoOffset = blitDepth || blitColor ? 0 : 1;
3111     uint32_t writeInfoCount  = blitColor + blitDepth + blitStencil;
3112 
3113     vkUpdateDescriptorSets(contextVk->getDevice(), writeInfoCount, writeInfos + writeInfoOffset, 0,
3114                            nullptr);
3115     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfos[2], 0, nullptr);
3116 
3117     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
3118     vk::ShaderModulePtr vertexShader;
3119     vk::ShaderModulePtr fragmentShader;
3120     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
3121     if (isSrc3D)
3122     {
3123         ANGLE_TRY(shaderLibrary.getBlit3DSrc_frag(contextVk, flags, &fragmentShader));
3124     }
3125     else
3126     {
3127         ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
3128     }
3129 
3130     ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
3131                                    isSrc3D ? &mBlit3DSrc[flags] : &mBlitResolve[flags],
3132                                    &pipelineDesc, descriptorSet, &shaderParams,
3133                                    sizeof(shaderParams), commandBuffer));
3134 
3135     // Set dynamic state
3136     VkViewport viewport;
3137     gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
3138     gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, false, completeRenderArea.height,
3139                        &viewport);
3140     commandBuffer->setViewport(0, 1, &viewport);
3141 
3142     VkRect2D scissor = gl_vk::GetRect(params.blitArea);
3143     commandBuffer->setScissor(0, 1, &scissor);
3144 
3145     if (blitDepth)
3146     {
3147         SetDepthDynamicStateForWrite(renderer, commandBuffer);
3148     }
3149     else
3150     {
3151         SetDepthDynamicStateForUnused(renderer, commandBuffer);
3152     }
3153 
3154     if (blitStencil)
3155     {
3156         constexpr uint8_t kCompleteMask    = 0xFF;
3157         constexpr uint8_t kUnusedReference = 0x00;
3158 
3159         commandBuffer->setStencilCompareMask(kCompleteMask, kCompleteMask);
3160         commandBuffer->setStencilWriteMask(kCompleteMask, kCompleteMask);
3161         commandBuffer->setStencilReference(kUnusedReference, kUnusedReference);
3162 
3163         SetStencilDynamicStateForWrite(renderer, commandBuffer);
3164     }
3165     else
3166     {
3167         SetStencilDynamicStateForUnused(renderer, commandBuffer);
3168     }
3169 
3170     // Note: this utility starts the render pass directly, thus bypassing
3171     // ContextVk::startRenderPass. As such, occlusion queries are not enabled.
3172     commandBuffer->draw(3, 0);
3173 
3174     // Don't allow this render pass to be reactivated by the user's draw call due to test flakiness
3175     // on win/intel bot.
3176     contextVk->disableRenderPassReactivation();
3177 
3178     return angle::Result::Continue;
3179 }
3180 
stencilBlitResolveNoShaderExport(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)3181 angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
3182                                                         FramebufferVk *framebuffer,
3183                                                         vk::ImageHelper *src,
3184                                                         const vk::ImageView *srcStencilView,
3185                                                         const BlitResolveParameters &params)
3186 {
3187     vk::Renderer *renderer = contextVk->getRenderer();
3188 
3189     // When VK_EXT_shader_stencil_export is not available, stencil is blitted/resolved into a
3190     // temporary buffer which is then copied into the stencil aspect of the image.
3191     ANGLE_TRY(ensureBlitResolveStencilNoExportResourcesInitialized(contextVk));
3192 
3193     bool isResolve = src->getSamples() > 1;
3194 
3195     // Create a temporary buffer to blit/resolve stencil into.
3196     vk::RendererScoped<vk::BufferHelper> blitBuffer(renderer);
3197 
3198     uint32_t bufferRowLengthInUints = UnsignedCeilDivide(params.blitArea.width, sizeof(uint32_t));
3199     VkDeviceSize bufferSize = bufferRowLengthInUints * sizeof(uint32_t) * params.blitArea.height;
3200 
3201     ANGLE_TRY(contextVk->initBufferAllocation(
3202         &blitBuffer.get(), renderer->getDeviceLocalMemoryTypeIndex(),
3203         static_cast<size_t>(bufferSize), renderer->getDefaultBufferAlignment(),
3204         BufferUsageType::Static));
3205 
3206     BlitResolveStencilNoExportShaderParams shaderParams;
3207     // Note: adjustments made for pre-rotatation in FramebufferVk::blit() affect these
3208     // Calculate*Offset() functions.
3209     if (isResolve)
3210     {
3211         CalculateResolveOffset(params, shaderParams.offset.resolve);
3212     }
3213     else
3214     {
3215         CalculateBlitOffset(params, shaderParams.offset.blit);
3216     }
3217     shaderParams.stretch[0]      = params.stretch[0];
3218     shaderParams.stretch[1]      = params.stretch[1];
3219     shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
3220     shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
3221     shaderParams.srcLayer        = params.srcLayer;
3222     shaderParams.srcWidth        = params.srcExtents[0];
3223     shaderParams.dstPitch        = bufferRowLengthInUints;
3224     shaderParams.blitArea[0]     = params.blitArea.x;
3225     shaderParams.blitArea[1]     = params.blitArea.y;
3226     shaderParams.blitArea[2]     = params.blitArea.width;
3227     shaderParams.blitArea[3]     = params.blitArea.height;
3228     shaderParams.flipX           = params.flipX;
3229     shaderParams.flipY           = params.flipY;
3230     shaderParams.rotateXY        = 0;
3231 
3232     // Potentially make adjustments for pre-rotatation.  Depending on the angle some of the
3233     // shaderParams need to be adjusted.
3234     switch (params.rotation)
3235     {
3236         case SurfaceRotation::Identity:
3237         case SurfaceRotation::Rotated90Degrees:
3238             break;
3239         case SurfaceRotation::Rotated180Degrees:
3240         case SurfaceRotation::Rotated270Degrees:
3241             if (isResolve)
3242             {
3243                 // Align the offset with minus 1, or the sample position near the edge will be
3244                 // wrong.
3245                 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0] - 1;
3246                 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1] - 1;
3247             }
3248             else
3249             {
3250                 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0];
3251                 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1];
3252             }
3253             break;
3254         default:
3255             UNREACHABLE();
3256             break;
3257     }
3258 
3259     shaderParams.rotateXY = IsRotatedAspectRatio(params.rotation);
3260 
3261     // Linear sampling is only valid with color blitting.
3262     ASSERT(!params.linear);
3263 
3264     uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0;
3265     flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
3266 
3267     RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
3268     ASSERT(depthStencilRenderTarget != nullptr);
3269     vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImageForWrite();
3270 
3271     // Change layouts prior to computation.
3272     vk::CommandBufferAccess access;
3273     access.onImageComputeShaderRead(src->getAspectFlags(), src);
3274     access.onImageTransferWrite(depthStencilRenderTarget->getLevelIndex(), 1,
3275                                 depthStencilRenderTarget->getLayerIndex(), 1,
3276                                 depthStencilImage->getAspectFlags(), depthStencilImage);
3277     access.onBufferComputeShaderWrite(&blitBuffer.get());
3278 
3279     VkDescriptorSet descriptorSet;
3280     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3281     vk::OutsideRenderPassCommandBuffer *commandBuffer;
3282     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3283     commandBuffer = &commandBufferHelper->getCommandBuffer();
3284     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
3285                                     Function::BlitResolveStencilNoExport, &descriptorSet));
3286 
3287     // Blit/resolve stencil into the buffer.
3288     VkDescriptorImageInfo imageInfo = {};
3289     imageInfo.imageView             = srcStencilView->getHandle();
3290     imageInfo.imageLayout           = src->getCurrentLayout(renderer);
3291 
3292     VkDescriptorBufferInfo bufferInfo = {};
3293     bufferInfo.buffer                 = blitBuffer.get().getBuffer().getHandle();
3294     bufferInfo.offset                 = blitBuffer.get().getOffset();
3295     bufferInfo.range                  = blitBuffer.get().getSize();
3296 
3297     VkDescriptorImageInfo samplerInfo = {};
3298     samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
3299 
3300     VkWriteDescriptorSet writeInfos[3] = {};
3301     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3302     writeInfos[0].dstSet               = descriptorSet;
3303     writeInfos[0].dstBinding           = kBlitResolveStencilNoExportDestBinding;
3304     writeInfos[0].descriptorCount      = 1;
3305     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3306     writeInfos[0].pBufferInfo          = &bufferInfo;
3307 
3308     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3309     writeInfos[1].dstSet          = descriptorSet;
3310     writeInfos[1].dstBinding      = kBlitResolveStencilNoExportSrcBinding;
3311     writeInfos[1].descriptorCount = 1;
3312     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3313     writeInfos[1].pImageInfo      = &imageInfo;
3314 
3315     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3316     writeInfos[2].dstSet          = descriptorSet;
3317     writeInfos[2].dstBinding      = kBlitResolveStencilNoExportSamplerBinding;
3318     writeInfos[2].descriptorCount = 1;
3319     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
3320     writeInfos[2].pImageInfo      = &samplerInfo;
3321 
3322     vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
3323 
3324     vk::ShaderModulePtr shader;
3325     ANGLE_TRY(contextVk->getShaderLibrary().getBlitResolveStencilNoExport_comp(contextVk, flags,
3326                                                                                &shader));
3327 
3328     ANGLE_TRY(setupComputeProgram(contextVk, Function::BlitResolveStencilNoExport, shader,
3329                                   &mBlitResolveStencilNoExport[flags], descriptorSet, &shaderParams,
3330                                   sizeof(shaderParams), commandBufferHelper));
3331     commandBuffer->dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
3332                             UnsignedCeilDivide(params.blitArea.height, 8), 1);
3333 
3334     // Add a barrier prior to copy.
3335     VkMemoryBarrier memoryBarrier = {};
3336     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
3337     memoryBarrier.srcAccessMask   = VK_ACCESS_SHADER_WRITE_BIT;
3338     memoryBarrier.dstAccessMask   = VK_ACCESS_TRANSFER_READ_BIT;
3339 
3340     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3341                                  VK_PIPELINE_STAGE_TRANSFER_BIT, memoryBarrier);
3342 
3343     // Copy the resulting buffer into dst.
3344     VkBufferImageCopy region           = {};
3345     region.bufferOffset                = blitBuffer.get().getOffset();
3346     region.bufferRowLength             = bufferRowLengthInUints * sizeof(uint32_t);
3347     region.bufferImageHeight           = params.blitArea.height;
3348     region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
3349     region.imageSubresource.mipLevel =
3350         depthStencilImage->toVkLevel(depthStencilRenderTarget->getLevelIndex()).get();
3351     region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex();
3352     region.imageSubresource.layerCount     = 1;
3353     region.imageOffset.x                   = params.blitArea.x;
3354     region.imageOffset.y                   = params.blitArea.y;
3355     region.imageOffset.z                   = 0;
3356     region.imageExtent.width               = params.blitArea.width;
3357     region.imageExtent.height              = params.blitArea.height;
3358     region.imageExtent.depth               = 1;
3359 
3360     commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(),
3361                                      depthStencilImage->getImage(),
3362                                      depthStencilImage->getCurrentLayout(renderer), 1, &region);
3363 
3364     return angle::Result::Continue;
3365 }
3366 
copyImage(ContextVk * contextVk,vk::ImageHelper * dst,const vk::ImageView * destView,vk::ImageHelper * src,const vk::ImageView * srcView,const CopyImageParameters & params)3367 angle::Result UtilsVk::copyImage(ContextVk *contextVk,
3368                                  vk::ImageHelper *dst,
3369                                  const vk::ImageView *destView,
3370                                  vk::ImageHelper *src,
3371                                  const vk::ImageView *srcView,
3372                                  const CopyImageParameters &params)
3373 {
3374     vk::Renderer *renderer = contextVk->getRenderer();
3375 
3376     // The views passed to this function are already retained, so a render pass cannot be already
3377     // open.  Otherwise, this function closes the render pass, which may incur a vkQueueSubmit and
3378     // then the views are used in a new command buffer without having been retained for it.
3379     // http://crbug.com/1272266#c22
3380     ASSERT(!contextVk->hasActiveRenderPass());
3381 
3382     const angle::Format &srcIntendedFormat = src->getIntendedFormat();
3383     const angle::Format &dstIntendedFormat = dst->getIntendedFormat();
3384 
3385     const bool isYUV             = src->getYcbcrConversionDesc().valid();
3386     const bool isSrcMultisampled = params.srcSampleCount > 1;
3387 
3388     vk::SamplerDesc samplerDesc;
3389     if (isYUV)
3390     {
3391         samplerDesc = vk::SamplerDesc(contextVk, gl::SamplerState(), false,
3392                                       &src->getYcbcrConversionDesc(), srcIntendedFormat.id);
3393 
3394         ANGLE_TRY(ensureImageCopyResourcesInitializedWithSampler(contextVk, samplerDesc));
3395     }
3396     else
3397     {
3398         ANGLE_TRY(ensureImageCopyResourcesInitialized(contextVk));
3399     }
3400 
3401     ImageCopyShaderParams shaderParams;
3402     shaderParams.flipX            = 0;
3403     shaderParams.flipY            = params.srcFlipY || params.dstFlipY;
3404     shaderParams.premultiplyAlpha = params.srcPremultiplyAlpha;
3405     shaderParams.unmultiplyAlpha  = params.srcUnmultiplyAlpha;
3406     shaderParams.dstHasLuminance  = dstIntendedFormat.luminanceBits > 0;
3407     shaderParams.dstIsAlpha       = dstIntendedFormat.isLUMA() && dstIntendedFormat.alphaBits > 0;
3408     shaderParams.dstDefaultChannelsMask =
3409         GetFormatDefaultChannelMask(dst->getIntendedFormat(), dst->getActualFormat());
3410     shaderParams.srcMip       = params.srcMip;
3411     shaderParams.srcLayer     = params.srcLayer;
3412     shaderParams.srcSampleCount = params.srcSampleCount;
3413     shaderParams.srcOffset[0] = params.srcOffset[0];
3414     shaderParams.srcOffset[1] = params.srcOffset[1];
3415     shaderParams.dstOffset[0] = params.dstOffset[0];
3416     shaderParams.dstOffset[1] = params.dstOffset[1];
3417     shaderParams.rotateXY     = 0;
3418 
3419     shaderParams.srcIsSRGB = params.srcColorEncoding == GL_SRGB;
3420     shaderParams.dstIsSRGB = params.dstColorEncoding == GL_SRGB;
3421 
3422     // If both src and dst are sRGB, and there is no alpha multiplication/division necessary, then
3423     // the shader can work with sRGB data and pretend they are linear.
3424     if (shaderParams.srcIsSRGB && shaderParams.dstIsSRGB && !shaderParams.premultiplyAlpha &&
3425         !shaderParams.unmultiplyAlpha)
3426     {
3427         shaderParams.srcIsSRGB = false;
3428         shaderParams.dstIsSRGB = false;
3429     }
3430 
3431     ASSERT(!(params.srcFlipY && params.dstFlipY));
3432     if (params.srcFlipY)
3433     {
3434         // If viewport is flipped, the shader expects srcOffset[1] to have the
3435         // last row's index instead of the first's.
3436         shaderParams.srcOffset[1] = params.srcHeight - params.srcOffset[1] - 1;
3437     }
3438     else if (params.dstFlipY)
3439     {
3440         // If image is flipped during copy, the shader uses the same code path as above,
3441         // with srcOffset being set to the last row's index instead of the first's.
3442         shaderParams.srcOffset[1] = params.srcOffset[1] + params.srcExtents[1] - 1;
3443     }
3444 
3445     switch (params.srcRotation)
3446     {
3447         case SurfaceRotation::Identity:
3448             break;
3449         case SurfaceRotation::Rotated90Degrees:
3450             shaderParams.rotateXY = 1;
3451             break;
3452         case SurfaceRotation::Rotated180Degrees:
3453             shaderParams.flipX = true;
3454             ASSERT(shaderParams.flipY);
3455             shaderParams.flipY = false;
3456             shaderParams.srcOffset[0] += params.srcExtents[0];
3457             shaderParams.srcOffset[1] -= params.srcExtents[1];
3458             break;
3459         case SurfaceRotation::Rotated270Degrees:
3460             shaderParams.flipX = true;
3461             ASSERT(!shaderParams.flipY);
3462             shaderParams.flipY = true;
3463             shaderParams.srcOffset[0] += params.srcExtents[0];
3464             shaderParams.srcOffset[1] += params.srcExtents[1];
3465             shaderParams.rotateXY = 1;
3466             break;
3467         default:
3468             UNREACHABLE();
3469             break;
3470     }
3471 
3472     vk::RenderPassDesc renderPassDesc;
3473     renderPassDesc.setSamples(dst->getSamples());
3474     renderPassDesc.packColorAttachment(0, dst->getActualFormatID());
3475 
3476     vk::GraphicsPipelineDesc pipelineDesc;
3477     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
3478                               contextVk->pipelineRobustness(),
3479                               contextVk->pipelineProtectedAccess());
3480     pipelineDesc.setRenderPassDesc(renderPassDesc);
3481     pipelineDesc.setRasterizationSamples(dst->getSamples());
3482 
3483     gl::Rectangle renderArea;
3484     renderArea.x      = params.dstOffset[0];
3485     renderArea.y      = params.dstOffset[1];
3486     renderArea.width  = params.srcExtents[0];
3487     renderArea.height = params.srcExtents[1];
3488     if ((params.srcRotation == SurfaceRotation::Rotated90Degrees) ||
3489         (params.srcRotation == SurfaceRotation::Rotated270Degrees))
3490     {
3491         // The surface is rotated 90/270 degrees.  This changes the aspect ratio of the surface.
3492         std::swap(renderArea.width, renderArea.height);
3493     }
3494 
3495     vk::RenderPassCommandBuffer *commandBuffer;
3496     ANGLE_TRY(startRenderPass(contextVk, dst, destView, renderPassDesc, renderArea,
3497                               VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
3498                               vk::RenderPassSource::InternalUtils, &commandBuffer));
3499 
3500     VkDescriptorSet descriptorSet;
3501     if (isYUV)
3502     {
3503         ANGLE_TRY(allocateDescriptorSetForImageCopyWithSampler(
3504             contextVk, &contextVk->getStartedRenderPassCommands(), samplerDesc, &descriptorSet));
3505     }
3506     else
3507     {
3508         ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
3509                                         Function::ImageCopy, &descriptorSet));
3510     }
3511 
3512     UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
3513 
3514     // Change source layout inside render pass.
3515     contextVk->onImageRenderPassRead(VK_IMAGE_ASPECT_COLOR_BIT,
3516                                      vk::ImageLayout::FragmentShaderReadOnly, src);
3517     contextVk->onImageRenderPassWrite(params.dstMip, params.dstLayer, 1, VK_IMAGE_ASPECT_COLOR_BIT,
3518                                       vk::ImageLayout::ColorWrite, dst);
3519 
3520     VkDescriptorImageInfo imageInfo = {};
3521     imageInfo.imageView             = srcView->getHandle();
3522     imageInfo.imageLayout           = src->getCurrentLayout(renderer);
3523 
3524     VkWriteDescriptorSet writeInfo = {};
3525     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3526     writeInfo.dstSet               = descriptorSet;
3527     writeInfo.dstBinding           = kImageCopySourceBinding;
3528     writeInfo.descriptorCount      = 1;
3529     writeInfo.descriptorType =
3530         isYUV ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3531     writeInfo.pImageInfo = &imageInfo;
3532 
3533     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
3534 
3535     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
3536     vk::ShaderModulePtr vertexShader;
3537     vk::ShaderModulePtr fragmentShader;
3538     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
3539 
3540     if (isYUV)
3541     {
3542         ASSERT(src->getType() == VK_IMAGE_TYPE_2D);
3543         ANGLE_TRY(shaderLibrary.getImageCopyFloat_frag(contextVk, ImageCopyFloat_frag::kSrcIsYUV,
3544                                                        &fragmentShader));
3545         ANGLE_TRY(setupGraphicsProgramWithLayout(
3546             contextVk, *mImageCopyWithSamplerPipelineLayouts[samplerDesc], vertexShader,
3547             fragmentShader, &mImageCopyWithSampler[samplerDesc], &pipelineDesc, descriptorSet,
3548             &shaderParams, sizeof(shaderParams), commandBuffer));
3549     }
3550     else if (isSrcMultisampled)
3551     {
3552         ANGLE_TRY(shaderLibrary.getImageCopyFloat_frag(contextVk, ImageCopyFloat_frag::kSrcIs2DMS,
3553                                                        &fragmentShader));
3554         ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageCopy, vertexShader, fragmentShader,
3555                                        &mImageCopyFloat, &pipelineDesc, descriptorSet,
3556                                        &shaderParams, sizeof(shaderParams), commandBuffer));
3557     }
3558     else
3559     {
3560         uint32_t flags = GetImageCopyFlags(srcIntendedFormat, dstIntendedFormat);
3561         if (src->getType() == VK_IMAGE_TYPE_3D)
3562         {
3563             flags |= ImageCopy_frag::kSrcIs3D;
3564         }
3565         else if (src->getLayerCount() > 1)
3566         {
3567             flags |= ImageCopy_frag::kSrcIs2DArray;
3568         }
3569         else
3570         {
3571             ASSERT(src->getType() == VK_IMAGE_TYPE_2D);
3572             flags |= ImageCopy_frag::kSrcIs2D;
3573         }
3574 
3575         ANGLE_TRY(shaderLibrary.getImageCopy_frag(contextVk, flags, &fragmentShader));
3576         ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageCopy, vertexShader, fragmentShader,
3577                                        &mImageCopy[flags], &pipelineDesc, descriptorSet,
3578                                        &shaderParams, sizeof(shaderParams), commandBuffer));
3579     }
3580 
3581     // Set dynamic state
3582     VkViewport viewport;
3583     gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dst->getExtents().height, &viewport);
3584     commandBuffer->setViewport(0, 1, &viewport);
3585 
3586     VkRect2D scissor = gl_vk::GetRect(renderArea);
3587     commandBuffer->setScissor(0, 1, &scissor);
3588 
3589     SetDepthDynamicStateForUnused(renderer, commandBuffer);
3590     SetStencilDynamicStateForUnused(renderer, commandBuffer);
3591 
3592     // Note: this utility creates its own framebuffer, thus bypassing ContextVk::startRenderPass.
3593     // As such, occlusion queries are not enabled.
3594     commandBuffer->draw(3, 0);
3595 
3596     // Close the render pass for this temporary framebuffer.
3597     return contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::TemporaryForImageCopy);
3598 }
3599 
copyImageBits(ContextVk * contextVk,vk::ImageHelper * dst,vk::ImageHelper * src,const CopyImageBitsParameters & params)3600 angle::Result UtilsVk::copyImageBits(ContextVk *contextVk,
3601                                      vk::ImageHelper *dst,
3602                                      vk::ImageHelper *src,
3603                                      const CopyImageBitsParameters &params)
3604 {
3605     vk::Renderer *renderer = contextVk->getRenderer();
3606 
3607     // This function is used to copy the bit representation of an image to another, and is used to
3608     // support EXT_copy_image when a format is emulated.  Currently, only RGB->RGBA emulation is
3609     // possible, and so this function is tailored to this specific kind of emulation.
3610     //
3611     // The copy can be done with various degrees of efficiency:
3612     //
3613     // - If the UINT reinterpretation format for src supports SAMPLED usage, texels can be read
3614     //   directly from that.  Otherwise vkCmdCopyImageToBuffer can be used and data then read from
3615     //   the buffer.
3616     // - If the UINT reinterpretation format for dst supports STORAGE usage, texels can be written
3617     //   directly to that.  Otherwise conversion can be done to a buffer and then
3618     //   vkCmdCopyBufferToImage used.
3619     //
3620     // This requires four different shaders.  For simplicity, this function unconditionally copies
3621     // src to a temp buffer, transforms to another temp buffer and copies to the dst.  No known
3622     // applications use EXT_copy_image on RGB formats, so no further optimization is currently
3623     // necessary.
3624     //
3625     // The conversion between buffers can be done with ConvertVertex.comp in UintToUint mode, so no
3626     // new shader is necessary.  The srcEmulatedAlpha parameter is used to make sure the destination
3627     // alpha value is correct, if dst is RGBA.
3628 
3629     // This path should only be necessary for when RGBA is used as fallback for RGB.  No other
3630     // format which can be used with EXT_copy_image has a fallback.
3631     ASSERT(src->getIntendedFormat().blueBits > 0 && src->getIntendedFormat().alphaBits == 0);
3632     ASSERT(dst->getIntendedFormat().blueBits > 0 && dst->getIntendedFormat().alphaBits == 0);
3633 
3634     const angle::Format &srcImageFormat = src->getActualFormat();
3635     const angle::Format &dstImageFormat = dst->getActualFormat();
3636 
3637     // Create temporary buffers.
3638     vk::RendererScoped<vk::BufferHelper> srcBuffer(renderer);
3639     vk::RendererScoped<vk::BufferHelper> dstBuffer(renderer);
3640 
3641     const uint32_t srcPixelBytes = srcImageFormat.pixelBytes;
3642     const uint32_t dstPixelBytes = dstImageFormat.pixelBytes;
3643 
3644     const uint32_t totalPixelCount =
3645         params.copyExtents[0] * params.copyExtents[1] * params.copyExtents[2];
3646     // Note that buffer sizes are rounded up a multiple of uint size, as that the granularity in
3647     // which the compute shader accesses these buffers.
3648     const VkDeviceSize srcBufferSize =
3649         roundUpPow2<uint32_t>(srcPixelBytes * totalPixelCount, sizeof(uint32_t));
3650     const VkDeviceSize dstBufferSize =
3651         roundUpPow2<uint32_t>(dstPixelBytes * totalPixelCount, sizeof(uint32_t));
3652 
3653     VkBufferCreateInfo bufferInfo = {};
3654     bufferInfo.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
3655     bufferInfo.flags              = 0;
3656     bufferInfo.size               = srcBufferSize;
3657     bufferInfo.usage       = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3658     bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
3659     bufferInfo.queueFamilyIndexCount = 0;
3660     bufferInfo.pQueueFamilyIndices   = nullptr;
3661 
3662     ANGLE_TRY(srcBuffer.get().init(contextVk, bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
3663 
3664     bufferInfo.size  = dstBufferSize;
3665     bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
3666 
3667     ANGLE_TRY(dstBuffer.get().init(contextVk, bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
3668 
3669     bool isSrc3D = src->getType() == VK_IMAGE_TYPE_3D;
3670     bool isDst3D = dst->getType() == VK_IMAGE_TYPE_3D;
3671 
3672     // Change layouts prior to computation.
3673     vk::CommandBufferAccess access;
3674     access.onImageTransferRead(src->getAspectFlags(), src);
3675     access.onImageTransferWrite(params.dstLevel, 1, isDst3D ? 0 : params.dstOffset[2],
3676                                 isDst3D ? 1 : params.copyExtents[2], VK_IMAGE_ASPECT_COLOR_BIT,
3677                                 dst);
3678 
3679     // srcBuffer is the destination of copyImageToBuffer() below.
3680     access.onBufferTransferWrite(&srcBuffer.get());
3681     access.onBufferComputeShaderWrite(&dstBuffer.get());
3682 
3683     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3684     vk::OutsideRenderPassCommandBuffer *commandBuffer;
3685     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3686     commandBuffer = &commandBufferHelper->getCommandBuffer();
3687 
3688     // Copy src into buffer, completely packed.
3689     VkBufferImageCopy srcRegion               = {};
3690     srcRegion.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
3691     srcRegion.imageSubresource.mipLevel       = src->toVkLevel(params.srcLevel).get();
3692     srcRegion.imageSubresource.baseArrayLayer = isSrc3D ? 0 : params.srcOffset[2];
3693     srcRegion.imageSubresource.layerCount     = isSrc3D ? 1 : params.copyExtents[2];
3694     srcRegion.imageOffset.x                   = params.srcOffset[0];
3695     srcRegion.imageOffset.y                   = params.srcOffset[1];
3696     srcRegion.imageOffset.z                   = isSrc3D ? params.srcOffset[2] : 0;
3697     srcRegion.imageExtent.width               = params.copyExtents[0];
3698     srcRegion.imageExtent.height              = params.copyExtents[1];
3699     srcRegion.imageExtent.depth               = isSrc3D ? params.copyExtents[2] : 1;
3700 
3701     commandBuffer->copyImageToBuffer(src->getImage(), src->getCurrentLayout(renderer),
3702                                      srcBuffer.get().getBuffer().getHandle(), 1, &srcRegion);
3703 
3704     // Add a barrier prior to dispatch call.
3705     VkMemoryBarrier memoryBarrier = {};
3706     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
3707     memoryBarrier.srcAccessMask   = VK_ACCESS_TRANSFER_WRITE_BIT;
3708     memoryBarrier.dstAccessMask   = VK_ACCESS_SHADER_READ_BIT;
3709 
3710     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
3711                                  VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, memoryBarrier);
3712 
3713     // Set up ConvertVertex shader to convert between the formats.  Only the following three cases
3714     // are possible:
3715     //
3716     // - RGB -> RGBA: Ns = 3, Ss = src.pixelBytes,
3717     //                Nd = 4, Sd = dst.pixelBytes, use srcEmulatedAlpha
3718     //
3719     // - RGBA -> RGBA: Ns = 3, Ss = src.pixelBytes,
3720     //                 Nd = 4, Sd = dst.pixelBytes, use srcEmulatedAlpha
3721     //
3722     // - RGBA -> RGB:  Ns = 3, Ss = src.pixelBytes,
3723     //                 Nd = 3, Sd = dst.pixelBytes
3724     //
3725     // The trick here is with RGBA -> RGBA, where Ns is specified as 3, so that the emulated alpha
3726     // from source is not taken (as uint), but rather one is provided such that the destination
3727     // alpha would contain the correct emulated alpha.
3728     //
3729     ConvertVertexShaderParams shaderParams;
3730     shaderParams.Ns = 3;
3731     shaderParams.Bs = srcImageFormat.pixelBytes / srcImageFormat.channelCount;
3732     shaderParams.Ss = srcImageFormat.pixelBytes;
3733     shaderParams.Nd = dstImageFormat.channelCount;
3734     shaderParams.Bd = dstImageFormat.pixelBytes / dstImageFormat.channelCount;
3735     shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
3736     // The component size is expected to either be 1, 2 or 4 bytes.
3737     ASSERT(4 % shaderParams.Bs == 0);
3738     ASSERT(4 % shaderParams.Bd == 0);
3739     shaderParams.Es = 4 / shaderParams.Bs;
3740     shaderParams.Ed = 4 / shaderParams.Bd;
3741     // Total number of output components is simply the number of pixels by number of components in
3742     // each.
3743     shaderParams.componentCount = totalPixelCount * shaderParams.Nd;
3744     // Total number of 4-byte outputs is the number of components divided by how many components can
3745     // fit in a 4-byte value.  Note that this value is also the invocation size of the shader.
3746     shaderParams.outputCount  = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
3747     shaderParams.srcOffset    = 0;
3748     shaderParams.dstOffset    = 0;
3749     shaderParams.isSrcHDR     = 0;
3750     shaderParams.isSrcA2BGR10 = 0;
3751 
3752     // Due to the requirements of EXT_copy_image, the channel size of src and dst must be
3753     // identical.  Usage of srcEmulatedAlpha relies on this as it's used to output an alpha value in
3754     // dst through the source.
3755     ASSERT(shaderParams.Bs == shaderParams.Bd);
3756 
3757     // The following RGB formats are allowed in EXT_copy_image:
3758     //
3759     // - RGB32F, RGB32UI, RGB32I
3760     // - RGB16F, RGB16UI, RGB16I
3761     // - RGB8, RGB8_SNORM, SRGB8, RGB8UI, RGB8I
3762     //
3763     // The value of emulated alpha is:
3764     //
3765     // - 1 for all RGB*I and RGB*UI formats
3766     // - bit representation of 1.0f for RGB32F
3767     // - bit representation of half-float 1.0f for RGB16F
3768     // - 0xFF for RGB8 and SRGB8
3769     // - 0x7F for RGB8_SNORM
3770     if (dstImageFormat.isInt())
3771     {
3772         shaderParams.srcEmulatedAlpha = 1;
3773     }
3774     else if (dstImageFormat.isUnorm())
3775     {
3776         ASSERT(shaderParams.Bd == 1);
3777         shaderParams.srcEmulatedAlpha = 0xFF;
3778     }
3779     else if (dstImageFormat.isSnorm())
3780     {
3781         ASSERT(shaderParams.Bd == 1);
3782         shaderParams.srcEmulatedAlpha = 0x7F;
3783     }
3784     else if (shaderParams.Bd == 2)
3785     {
3786         ASSERT(dstImageFormat.isFloat());
3787         shaderParams.srcEmulatedAlpha = gl::Float16One;
3788     }
3789     else if (shaderParams.Bd == 4)
3790     {
3791         ASSERT(dstImageFormat.isFloat());
3792         ASSERT(ValidateFloatOneAsUint());
3793         shaderParams.srcEmulatedAlpha = gl::Float32One;
3794     }
3795     else
3796     {
3797         UNREACHABLE();
3798     }
3799 
3800     // Use UintToUint conversion to preserve the bit pattern during transfer.
3801     const uint32_t flags = ConvertVertex_comp::kUintToUint;
3802     ANGLE_TRY(convertVertexBufferImpl(contextVk, &dstBuffer.get(), &srcBuffer.get(), flags,
3803                                       commandBufferHelper, shaderParams, {}));
3804 
3805     // Add a barrier prior to copy.
3806     memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
3807     memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
3808 
3809     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3810                                  VK_PIPELINE_STAGE_TRANSFER_BIT, memoryBarrier);
3811 
3812     // Copy buffer into dst.  It's completely packed.
3813     VkBufferImageCopy dstRegion               = {};
3814     dstRegion.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
3815     dstRegion.imageSubresource.mipLevel       = dst->toVkLevel(params.dstLevel).get();
3816     dstRegion.imageSubresource.baseArrayLayer = isDst3D ? 0 : params.dstOffset[2];
3817     dstRegion.imageSubresource.layerCount     = isDst3D ? 1 : params.copyExtents[2];
3818     dstRegion.imageOffset.x                   = params.dstOffset[0];
3819     dstRegion.imageOffset.y                   = params.dstOffset[1];
3820     dstRegion.imageOffset.z                   = isDst3D ? params.dstOffset[2] : 0;
3821     dstRegion.imageExtent.width               = params.copyExtents[0];
3822     dstRegion.imageExtent.height              = params.copyExtents[1];
3823     dstRegion.imageExtent.depth               = isDst3D ? params.copyExtents[2] : 1;
3824 
3825     commandBuffer->copyBufferToImage(dstBuffer.get().getBuffer().getHandle(), dst->getImage(),
3826                                      dst->getCurrentLayout(renderer), 1, &dstRegion);
3827 
3828     return angle::Result::Continue;
3829 }
3830 
copyImageToBuffer(ContextVk * contextVk,vk::BufferHelper * dst,vk::ImageHelper * src,const CopyImageToBufferParameters & params)3831 angle::Result UtilsVk::copyImageToBuffer(ContextVk *contextVk,
3832                                          vk::BufferHelper *dst,
3833                                          vk::ImageHelper *src,
3834                                          const CopyImageToBufferParameters &params)
3835 {
3836     vk::Renderer *renderer = contextVk->getRenderer();
3837     ANGLE_TRY(ensureCopyImageToBufferResourcesInitialized(contextVk));
3838 
3839     const angle::Format &srcFormat = src->getActualFormat();
3840 
3841     ASSERT(params.outputOffset % sizeof(uint32_t) == 0);
3842     ASSERT(params.outputPitch % sizeof(uint32_t) == 0);
3843 
3844     CopyImageToBufferShaderParams shaderParams;
3845     shaderParams.srcOffset[0]    = params.srcOffset[0];
3846     shaderParams.srcOffset[1]    = params.srcOffset[1];
3847     shaderParams.srcDepth        = params.srcLayer;
3848     shaderParams.reverseRowOrder = params.reverseRowOrder;
3849     shaderParams.size[0]         = params.size[0];
3850     shaderParams.size[1]         = params.size[1];
3851     shaderParams.outputOffset    = static_cast<uint32_t>(params.outputOffset / sizeof(uint32_t));
3852     shaderParams.outputPitch     = params.outputPitch / sizeof(uint32_t);
3853     shaderParams.isDstSnorm      = params.outputFormat->isSnorm();
3854 
3855     gl::SwizzleState swizzle;
3856     if (params.outputFormat->isBGRA())
3857     {
3858         swizzle.swizzleRed  = GL_BLUE;
3859         swizzle.swizzleBlue = GL_RED;
3860     }
3861 
3862     uint32_t flags = GetCopyImageToBufferFlags(srcFormat);
3863     gl::TextureType textureType;
3864     if (src->getType() == VK_IMAGE_TYPE_3D)
3865     {
3866         flags |= CopyImageToBuffer_comp::kSrcIs3D;
3867         textureType = gl::TextureType::_3D;
3868     }
3869     else
3870     {
3871         flags |= CopyImageToBuffer_comp::kSrcIs2D;
3872         textureType = gl::TextureType::_2D;
3873     }
3874 
3875     // Don't decode to linear colorspace when copying an image
3876     angle::FormatID imageFormat = src->getActualFormatID();
3877     angle::FormatID linearFormat =
3878         src->getActualFormat().isSRGB ? ConvertToLinear(imageFormat) : imageFormat;
3879     ASSERT(linearFormat != angle::FormatID::NONE);
3880 
3881     vk::DeviceScoped<vk::ImageView> srcView(contextVk->getDevice());
3882     ANGLE_TRY(src->initReinterpretedLayerImageView(
3883         contextVk, textureType, src->getAspectFlags(), swizzle, &srcView.get(), params.srcMip, 1,
3884         textureType == gl::TextureType::_2D ? params.srcLayer : 0, 1, VK_IMAGE_USAGE_SAMPLED_BIT,
3885         linearFormat));
3886 
3887     vk::CommandBufferAccess access;
3888     access.onImageComputeShaderRead(src->getAspectFlags(), src);
3889     access.onBufferComputeShaderWrite(dst);
3890 
3891     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3892     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3893 
3894     vk::OutsideRenderPassCommandBuffer *commandBuffer;
3895     commandBuffer = &commandBufferHelper->getCommandBuffer();
3896 
3897     VkDescriptorSet descriptorSet;
3898     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::CopyImageToBuffer,
3899                                     &descriptorSet));
3900 
3901     VkDescriptorImageInfo imageInfo = {};
3902     imageInfo.imageView             = srcView.get().getHandle();
3903     imageInfo.imageLayout           = src->getCurrentLayout(renderer);
3904 
3905     VkDescriptorBufferInfo bufferInfo = {};
3906     bufferInfo.buffer                 = dst->getBuffer().getHandle();
3907     bufferInfo.offset                 = dst->getOffset();
3908     bufferInfo.range                  = dst->getSize();
3909 
3910     VkWriteDescriptorSet writeInfo[2] = {};
3911 
3912     writeInfo[0].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3913     writeInfo[0].dstSet          = descriptorSet;
3914     writeInfo[0].dstBinding      = kCopyImageToBufferSourceBinding;
3915     writeInfo[0].descriptorCount = 1;
3916     writeInfo[0].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3917     writeInfo[0].pImageInfo      = &imageInfo;
3918 
3919     writeInfo[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3920     writeInfo[1].dstSet          = descriptorSet;
3921     writeInfo[1].dstBinding      = kCopyImageToBufferDestinationBinding;
3922     writeInfo[1].descriptorCount = 1;
3923     writeInfo[1].descriptorType  = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3924     writeInfo[1].pBufferInfo     = &bufferInfo;
3925 
3926     vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfo, 0, nullptr);
3927 
3928     vk::ShaderModulePtr shader;
3929     ANGLE_TRY(contextVk->getShaderLibrary().getCopyImageToBuffer_comp(contextVk, flags, &shader));
3930 
3931     ANGLE_TRY(setupComputeProgram(contextVk, Function::CopyImageToBuffer, shader,
3932                                   &mCopyImageToBuffer[flags], descriptorSet, &shaderParams,
3933                                   sizeof(shaderParams), commandBufferHelper));
3934 
3935     commandBuffer->dispatch(UnsignedCeilDivide(params.size[0], 8),
3936                             UnsignedCeilDivide(params.size[1], 8), 1);
3937 
3938     vk::ImageView srcViewObject = srcView.release();
3939     contextVk->addGarbage(&srcViewObject);
3940 
3941     return angle::Result::Continue;
3942 }
3943 
copyRgbToRgba(ContextVk * contextVk,const angle::Format & srcFormat,vk::BufferHelper * srcBuffer,uint32_t srcOffset,uint32_t pixelCount,vk::BufferHelper * dstBuffer)3944 angle::Result UtilsVk::copyRgbToRgba(ContextVk *contextVk,
3945                                      const angle::Format &srcFormat,
3946                                      vk::BufferHelper *srcBuffer,
3947                                      uint32_t srcOffset,
3948                                      uint32_t pixelCount,
3949                                      vk::BufferHelper *dstBuffer)
3950 {
3951     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3952 
3953     vk::CommandBufferAccess access;
3954     access.onBufferComputeShaderRead(srcBuffer);
3955     access.onBufferComputeShaderWrite(dstBuffer);
3956 
3957     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3958 
3959     rx::UtilsVk::ConvertVertexShaderParams shaderParams;
3960     shaderParams.Ns = 3;   // src channels
3961     shaderParams.Bs = 4;   // src bytes per channel
3962     shaderParams.Ss = 12;  // src stride
3963     shaderParams.Nd = 4;   // dest channels
3964     shaderParams.Bd = 4;   // dest bytes per channel
3965     shaderParams.Sd = 16;  // dest stride
3966     shaderParams.Es = 4 / shaderParams.Bs;
3967     shaderParams.Ed = 4 / shaderParams.Bd;
3968     // Total number of output components is simply the number of pixels by number of components in
3969     // each.
3970     shaderParams.componentCount = pixelCount * shaderParams.Nd;
3971     // Total number of 4-byte outputs is the number of components divided by how many components can
3972     // fit in a 4-byte value.  Note that this value is also the invocation size of the shader.
3973     shaderParams.outputCount  = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
3974     shaderParams.srcOffset    = srcOffset;
3975     shaderParams.dstOffset    = 0;
3976     shaderParams.isSrcHDR     = 0;
3977     shaderParams.isSrcA2BGR10 = 0;
3978 
3979     uint32_t flags = 0;
3980     switch (srcFormat.id)
3981     {
3982         case angle::FormatID::R32G32B32_UINT:
3983             flags                         = ConvertVertex_comp::kUintToUint;
3984             shaderParams.srcEmulatedAlpha = 1;
3985             break;
3986         case angle::FormatID::R32G32B32_SINT:
3987             flags                         = ConvertVertex_comp::kSintToSint;
3988             shaderParams.srcEmulatedAlpha = 1;
3989             break;
3990         case angle::FormatID::R32G32B32_FLOAT:
3991             flags                         = ConvertVertex_comp::kFloatToFloat;
3992             shaderParams.srcEmulatedAlpha = gl::Float32One;
3993             break;
3994         default:
3995             UNREACHABLE();
3996     }
3997 
3998     return convertVertexBufferImpl(contextVk, dstBuffer, srcBuffer, flags, commandBufferHelper,
3999                                    shaderParams, {});
4000 }
4001 
GetEtcToBcFlags(const angle::Format & format)4002 uint32_t GetEtcToBcFlags(const angle::Format &format)
4003 {
4004     switch (format.id)
4005     {
4006         case angle::FormatID::ETC1_R8G8B8_UNORM_BLOCK:
4007         case angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK:
4008         case angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK:
4009         case angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK:
4010         case angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK:
4011         case angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK:
4012         case angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK:
4013         case angle::FormatID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK:
4014             return EtcToBc_comp::kEtcRgba8ToBC3;
4015         case angle::FormatID::EAC_R11_SNORM_BLOCK:
4016         case angle::FormatID::EAC_R11_UNORM_BLOCK:
4017         case angle::FormatID::EAC_R11G11_SNORM_BLOCK:
4018         case angle::FormatID::EAC_R11G11_UNORM_BLOCK:
4019             return EtcToBc_comp::kEtcRg11ToBC5;
4020         default:
4021             UNREACHABLE();
4022             return EtcToBc_comp::kEtcRgba8ToBC3;
4023     }
4024 }
4025 
GetCompactibleUINTFormat(const angle::Format & format)4026 angle::FormatID GetCompactibleUINTFormat(const angle::Format &format)
4027 {
4028     ASSERT(format.pixelBytes == 8 || format.pixelBytes == 16);
4029     return format.pixelBytes != 8 ? angle::FormatID::R32G32B32A32_UINT
4030                                   : angle::FormatID::R32G32_UINT;
4031 }
4032 
transCodeEtcToBc(ContextVk * contextVk,vk::BufferHelper * srcBuffer,vk::ImageHelper * dstImage,const VkBufferImageCopy * copyRegion)4033 angle::Result UtilsVk::transCodeEtcToBc(ContextVk *contextVk,
4034                                         vk::BufferHelper *srcBuffer,
4035                                         vk::ImageHelper *dstImage,
4036                                         const VkBufferImageCopy *copyRegion)
4037 {
4038     ANGLE_TRY(ensureTransCodeEtcToBcResourcesInitialized(contextVk));
4039     vk::Renderer *renderer              = contextVk->getRenderer();
4040     const angle::Format &intendedFormat = dstImage->getIntendedFormat();
4041     vk::ContextScoped<vk::BufferViewHelper> bufferViewHelper(contextVk);
4042     const gl::InternalFormat &info =
4043         gl::GetSizedInternalFormatInfo(intendedFormat.glInternalFormat);
4044 
4045     // According to GLES spec. Etc texture don't support 3D texture type.
4046     ASSERT(copyRegion->bufferRowLength % info.compressedBlockWidth == 0 &&
4047            copyRegion->bufferImageHeight % info.compressedBlockHeight == 0 &&
4048            copyRegion->imageExtent.depth == 1);
4049 
4050     ASSERT(dstImage->getType() != VK_IMAGE_TYPE_1D && dstImage->getType() != VK_IMAGE_TYPE_3D);
4051 
4052     GLuint sliceTexels = (copyRegion->bufferRowLength / info.compressedBlockWidth) *
4053                          (copyRegion->bufferImageHeight / info.compressedBlockHeight);
4054     GLuint sliceSize     = sliceTexels * intendedFormat.pixelBytes;
4055     GLuint texBufferSize = sliceSize * copyRegion->imageSubresource.layerCount;
4056 
4057     // Make sure the texture buffer size not out of limit.
4058     // Usually the limit is more than 128M.
4059     ASSERT(
4060         texBufferSize <
4061         static_cast<GLuint>(renderer->getPhysicalDeviceProperties().limits.maxTexelBufferElements));
4062     const vk::BufferView *srcBufferView = nullptr;
4063     bufferViewHelper.get().init(renderer, 0, texBufferSize);
4064     ANGLE_TRY(bufferViewHelper.get().getView(
4065         contextVk, *srcBuffer, copyRegion->bufferOffset,
4066         renderer->getFormat(GetCompactibleUINTFormat(intendedFormat)), &srcBufferView));
4067 
4068     vk::LevelIndex dstLevel =
4069         gl::LevelIndexWrapper<uint32_t>(copyRegion->imageSubresource.mipLevel);
4070 
4071     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
4072     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper({}, &commandBufferHelper));
4073     const angle::Format &format              = dstImage->getIntendedFormat();
4074     uint32_t flags                           = GetEtcToBcFlags(format);
4075     vk::ShaderModulePtr shader;
4076     ANGLE_TRY(contextVk->getShaderLibrary().getEtcToBc_comp(contextVk, flags, &shader));
4077 
4078     vk::OutsideRenderPassCommandBuffer *commandBuffer;
4079     commandBuffer = &commandBufferHelper->getCommandBuffer();
4080 
4081     // For BC format, shader need width and height to be multiple of four.
4082     uint32_t width  = rx::roundUpPow2(copyRegion->imageExtent.width, 4u);
4083     uint32_t height = rx::roundUpPow2(copyRegion->imageExtent.height, 4u);
4084 
4085     // push constants data
4086     EtcToBcShaderParams shaderParams = {};
4087     shaderParams.offsetX             = static_cast<uint32_t>(copyRegion->imageOffset.x);
4088     shaderParams.offsetY             = static_cast<uint32_t>(copyRegion->imageOffset.y);
4089     shaderParams.texelOffset         = 0;
4090     shaderParams.width               = width;
4091     shaderParams.height              = height;
4092     shaderParams.alphaBits           = format.alphaBits;
4093     shaderParams.isSigned            = format.isSnorm();
4094     shaderParams.isEacRg             = format.channelCount == 2;  // EAC_RG11
4095 
4096     VkBufferView bufferView                    = srcBufferView->getHandle();
4097     VkWriteDescriptorSet writeDescriptorSet[2] = {};
4098     writeDescriptorSet[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4099     writeDescriptorSet[0].descriptorType       = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
4100     writeDescriptorSet[0].dstBinding           = 0;
4101     writeDescriptorSet[0].pBufferInfo          = nullptr;
4102     writeDescriptorSet[0].descriptorCount      = 1;
4103     writeDescriptorSet[0].pTexelBufferView     = &bufferView;
4104 
4105     VkDescriptorImageInfo imageInfo       = {};
4106     imageInfo.imageLayout                 = VK_IMAGE_LAYOUT_GENERAL;
4107     writeDescriptorSet[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4108     writeDescriptorSet[1].descriptorType  = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4109     writeDescriptorSet[1].dstBinding      = 1;
4110     writeDescriptorSet[1].pImageInfo      = &imageInfo;
4111     writeDescriptorSet[1].descriptorCount = 1;
4112     // Due to limitation VUID-VkImageViewCreateInfo-image-07072, we have to copy layer by layer.
4113     for (uint32_t i = 0; i < copyRegion->imageSubresource.layerCount; ++i)
4114     {
4115         vk::DeviceScoped<vk::ImageView> scopedImageView(contextVk->getDevice());
4116         ANGLE_TRY(dstImage->initReinterpretedLayerImageView(
4117             contextVk, gl::TextureType::_2D, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
4118             &scopedImageView.get(), dstLevel, 1, copyRegion->imageSubresource.baseArrayLayer + i, 1,
4119             VK_IMAGE_USAGE_STORAGE_BIT, GetCompactibleUINTFormat(intendedFormat)));
4120         imageInfo.imageView = scopedImageView.get().getHandle();
4121 
4122         VkDescriptorSet descriptorSet;
4123         ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::TransCodeEtcToBc,
4124                                         &descriptorSet));
4125         writeDescriptorSet[0].dstSet = descriptorSet;
4126         writeDescriptorSet[1].dstSet = descriptorSet;
4127         vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeDescriptorSet, 0, nullptr);
4128 
4129         ANGLE_TRY(setupComputeProgram(contextVk, Function::TransCodeEtcToBc, shader,
4130                                       &mEtcToBc[flags], descriptorSet, &shaderParams,
4131                                       sizeof(shaderParams), commandBufferHelper));
4132 
4133         // Work group size is 8 x 8 x 1
4134         commandBuffer->dispatch(UnsignedCeilDivide(width, 8), UnsignedCeilDivide(height, 8), 1);
4135         // Release temporary views
4136         vk::ImageView imageView = scopedImageView.release();
4137         contextVk->addGarbage(&imageView);
4138 
4139         shaderParams.texelOffset += sliceTexels;
4140     }
4141     // Retain buffer view
4142     commandBufferHelper->retainResource(&bufferViewHelper.get());
4143     return angle::Result::Continue;
4144 }
4145 
generateMipmap(ContextVk * contextVk,vk::ImageHelper * src,const vk::ImageView * srcLevelZeroView,vk::ImageHelper * dst,const GenerateMipmapDestLevelViews & destLevelViews,const vk::Sampler & sampler,const GenerateMipmapParameters & params)4146 angle::Result UtilsVk::generateMipmap(ContextVk *contextVk,
4147                                       vk::ImageHelper *src,
4148                                       const vk::ImageView *srcLevelZeroView,
4149                                       vk::ImageHelper *dst,
4150                                       const GenerateMipmapDestLevelViews &destLevelViews,
4151                                       const vk::Sampler &sampler,
4152                                       const GenerateMipmapParameters &params)
4153 {
4154     vk::Renderer *renderer = contextVk->getRenderer();
4155 
4156     ANGLE_TRY(ensureGenerateMipmapResourcesInitialized(contextVk));
4157 
4158     const gl::Extents &srcExtents = src->getLevelExtents(vk::LevelIndex(params.srcLevel));
4159     ASSERT(srcExtents.depth == 1);
4160 
4161     // Each workgroup processes a 64x64 tile of the image.
4162     constexpr uint32_t kPixelWorkgroupRatio = 64;
4163     const uint32_t workGroupX = UnsignedCeilDivide(srcExtents.width, kPixelWorkgroupRatio);
4164     const uint32_t workGroupY = UnsignedCeilDivide(srcExtents.height, kPixelWorkgroupRatio);
4165 
4166     GenerateMipmapShaderParams shaderParams;
4167     shaderParams.invSrcExtent[0] = 1.0f / srcExtents.width;
4168     shaderParams.invSrcExtent[1] = 1.0f / srcExtents.height;
4169     shaderParams.levelCount      = params.dstLevelCount;
4170 
4171     uint32_t flags = GetGenerateMipmapFlags(contextVk, src->getActualFormat());
4172 
4173     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
4174     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper({}, &commandBufferHelper));
4175 
4176     VkDescriptorSet descriptorSet;
4177     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::GenerateMipmap,
4178                                     &descriptorSet));
4179 
4180     VkDescriptorImageInfo destImageInfos[kGenerateMipmapMaxLevels] = {};
4181     for (uint32_t level = 0; level < kGenerateMipmapMaxLevels; ++level)
4182     {
4183         destImageInfos[level].imageView   = destLevelViews[level]->getHandle();
4184         destImageInfos[level].imageLayout = dst->getCurrentLayout(renderer);
4185     }
4186 
4187     VkDescriptorImageInfo srcImageInfo = {};
4188     srcImageInfo.imageView             = srcLevelZeroView->getHandle();
4189     srcImageInfo.imageLayout           = src->getCurrentLayout(renderer);
4190     srcImageInfo.sampler               = sampler.getHandle();
4191 
4192     VkWriteDescriptorSet writeInfos[2] = {};
4193     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4194     writeInfos[0].dstSet               = descriptorSet;
4195     writeInfos[0].dstBinding           = kGenerateMipmapDestinationBinding;
4196     writeInfos[0].descriptorCount      = GetGenerateMipmapMaxLevels(contextVk);
4197     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4198     writeInfos[0].pImageInfo           = destImageInfos;
4199 
4200     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4201     writeInfos[1].dstSet          = descriptorSet;
4202     writeInfos[1].dstBinding      = kGenerateMipmapSourceBinding;
4203     writeInfos[1].descriptorCount = 1;
4204     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
4205     writeInfos[1].pImageInfo      = &srcImageInfo;
4206 
4207     vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
4208 
4209     vk::ShaderModulePtr shader;
4210     ANGLE_TRY(contextVk->getShaderLibrary().getGenerateMipmap_comp(contextVk, flags, &shader));
4211 
4212     // Note: onImageRead/onImageWrite is expected to be called by the caller.  This avoids inserting
4213     // barriers between calls for each layer of the image.
4214     vk::OutsideRenderPassCommandBuffer *commandBuffer;
4215     commandBuffer = &commandBufferHelper->getCommandBuffer();
4216 
4217     ANGLE_TRY(setupComputeProgram(contextVk, Function::GenerateMipmap, shader,
4218                                   &mGenerateMipmap[flags], descriptorSet, &shaderParams,
4219                                   sizeof(shaderParams), commandBufferHelper));
4220 
4221     commandBuffer->dispatch(workGroupX, workGroupY, 1);
4222 
4223     return angle::Result::Continue;
4224 }
4225 
generateMipmapWithDraw(ContextVk * contextVk,vk::ImageHelper * image,const angle::FormatID actualFormatID,const bool isMipmapFiltered)4226 angle::Result UtilsVk::generateMipmapWithDraw(ContextVk *contextVk,
4227                                               vk::ImageHelper *image,
4228                                               const angle::FormatID actualFormatID,
4229                                               const bool isMipmapFiltered)
4230 {
4231     // This function only supports -
4232     // 1. color formats that support color attachment feature
4233     // 2. image is of type VK_IMAGE_TYPE_2D and is not MSAA
4234     ASSERT(image);
4235     ASSERT(image->getType() == VK_IMAGE_TYPE_2D && image->getSamples() == 1);
4236     const angle::Format &actualFormat = angle::Format::Get(actualFormatID);
4237     ASSERT(!actualFormat.hasDepthOrStencilBits());
4238     // TODO: the following check is not enough; if the image is AHB-imported, then the draw path
4239     // cannot be taken if AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER hasn't been specified, even if the
4240     // format is renderable.
4241     vk::Renderer *renderer = contextVk->getRenderer();
4242     ASSERT(vk::FormatHasNecessaryFeature(renderer, actualFormat.id, image->getTilingMode(),
4243                                          VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT));
4244 
4245     // Ensure required resources are initialized
4246     ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
4247 
4248     uint32_t layerCount        = image->getLayerCount();
4249     uint32_t levelCount        = image->getLevelCount();
4250     GLint sampleCount          = image->getSamples();
4251     gl::LevelIndex baseLevelGL = image->getFirstAllocatedLevel();
4252     vk::LevelIndex baseLevelVK = image->toVkLevel(baseLevelGL);
4253     vk::LevelIndex maxLevelVK  = baseLevelVK + (levelCount - 1);
4254 
4255     // Transition entire image to color attachment layout
4256     vk::CommandBufferAccess access;
4257     access.onImageDrawMipmapGenerationWrite(baseLevelGL, levelCount, 0, layerCount,
4258                                             VK_IMAGE_ASPECT_COLOR_BIT, image);
4259     vk::OutsideRenderPassCommandBuffer *outsideCommandBuffer;
4260     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &outsideCommandBuffer));
4261 
4262     gl::TextureType textureType       = vk::Get2DTextureType(layerCount, sampleCount);
4263     gl::SwizzleState swizzle          = {};
4264     VkImageUsageFlags imageUsageFlags = image->getUsage();
4265 
4266     // Setup shaders for draw
4267     uint32_t flags = GetBlitResolveFlags(true, false, false, actualFormat);
4268     flags |= layerCount > 1 ? BlitResolve_frag::kSrcIsArray : 0;
4269     Function function = Function::BlitResolve;
4270 
4271     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
4272     vk::ShaderModulePtr vertexShader;
4273     vk::ShaderModulePtr fragmentShader;
4274     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
4275     ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
4276 
4277     // Setup blit shader parameters
4278     BlitResolveShaderParams shaderParams;
4279     shaderParams.offset.blit[0] = 0.0f;
4280     shaderParams.offset.blit[1] = 0.0f;
4281     shaderParams.stretch[0]     = 1.0f;
4282     shaderParams.stretch[1]     = 1.0f;
4283     shaderParams.samples        = 1;
4284     shaderParams.invSamples     = 1.0f;
4285     shaderParams.outputMask     = 1;
4286     shaderParams.flipX          = 0;
4287     shaderParams.flipY          = 0;
4288     shaderParams.rotateXY       = 0;
4289 
4290     // Setup pipeline for draw
4291     vk::RenderPassDesc renderPassDesc;
4292     renderPassDesc.setSamples(sampleCount);
4293     renderPassDesc.packColorAttachment(0, actualFormatID);
4294 
4295     vk::GraphicsPipelineDesc pipelineDesc;
4296     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
4297                               contextVk->pipelineRobustness(),
4298                               contextVk->pipelineProtectedAccess());
4299     pipelineDesc.setSingleColorWriteMask(0, (VkColorComponentFlagBits::VK_COLOR_COMPONENT_R_BIT |
4300                                              VkColorComponentFlagBits::VK_COLOR_COMPONENT_G_BIT |
4301                                              VkColorComponentFlagBits::VK_COLOR_COMPONENT_B_BIT |
4302                                              VkColorComponentFlagBits::VK_COLOR_COMPONENT_A_BIT));
4303     pipelineDesc.setRasterizationSamples(sampleCount);
4304     pipelineDesc.setRenderPassDesc(renderPassDesc);
4305 
4306     // Setup write descriptors
4307     VkDescriptorImageInfo imageInfos = {};
4308     imageInfos.imageLayout           = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4309 
4310     VkDescriptorImageInfo samplerInfo = {};
4311     samplerInfo.sampler = isMipmapFiltered ? mLinearSampler.getHandle() : mPointSampler.getHandle();
4312 
4313     VkWriteDescriptorSet writeInfos[2] = {};
4314     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4315     writeInfos[0].dstBinding           = kBlitResolveColorOrDepthBinding;
4316     writeInfos[0].descriptorCount      = 1;
4317     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
4318     writeInfos[0].pImageInfo           = &imageInfos;
4319 
4320     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4321     writeInfos[1].dstBinding      = kBlitResolveSamplerBinding;
4322     writeInfos[1].descriptorCount = 1;
4323     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
4324     writeInfos[1].pImageInfo      = &samplerInfo;
4325 
4326     // Setup for read barrier
4327     VkImageMemoryBarrier barrier            = {};
4328     barrier.sType                           = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
4329     barrier.image                           = image->getImage().getHandle();
4330     barrier.srcQueueFamilyIndex             = VK_QUEUE_FAMILY_IGNORED;
4331     barrier.dstQueueFamilyIndex             = VK_QUEUE_FAMILY_IGNORED;
4332     barrier.subresourceRange.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
4333     barrier.subresourceRange.baseArrayLayer = 0;
4334     barrier.subresourceRange.layerCount     = layerCount;
4335     barrier.subresourceRange.baseMipLevel   = baseLevelVK.get();
4336     barrier.subresourceRange.levelCount     = 1;
4337     barrier.oldLayout                       = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4338     barrier.srcAccessMask                   = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
4339     barrier.newLayout                       = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4340     barrier.dstAccessMask                   = VK_ACCESS_SHADER_READ_BIT;
4341 
4342     // Sample from mipLevel N and draw to mipLevel N+1
4343     for (vk::LevelIndex srcLevelVk = baseLevelVK; srcLevelVk < maxLevelVK;)
4344     {
4345         // Transition "srcLevel" of all layers to shader read only optimal layout
4346         outsideCommandBuffer = nullptr;
4347         ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &outsideCommandBuffer));
4348 
4349         barrier.subresourceRange.baseMipLevel = srcLevelVk.get();
4350         outsideCommandBuffer->imageBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
4351                                            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier);
4352 
4353         // Update render area
4354         vk::LevelIndex dstLevelVk = srcLevelVk + 1;
4355         ASSERT(dstLevelVk <= baseLevelVK + levelCount);
4356         gl::Extents extents      = image->getLevelExtents(dstLevelVk);
4357         gl::Rectangle renderArea = gl::Rectangle(0, 0, extents.width, extents.height);
4358         VkViewport viewport;
4359         gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, renderArea.height, &viewport);
4360         VkRect2D scissor = gl_vk::GetRect(renderArea);
4361 
4362         shaderParams.invSrcExtent[0] = 1.0f / renderArea.width;
4363         shaderParams.invSrcExtent[1] = 1.0f / renderArea.height;
4364 
4365         // mipLevel N --> mipLevel N+1 must be done for each layer
4366         for (uint32_t currentLayer = 0; currentLayer < layerCount; currentLayer++)
4367         {
4368             // Create image views for currentLayer's srcLevelVk and dstLevelVk
4369             vk::ImageView srcImageView;
4370             ANGLE_TRY(image->initReinterpretedLayerImageView(
4371                 contextVk, textureType, image->getAspectFlags(), swizzle, &srcImageView, srcLevelVk,
4372                 1, currentLayer, 1, imageUsageFlags, actualFormatID));
4373 
4374             vk::ImageView dstImageView;
4375             ANGLE_TRY(image->initReinterpretedLayerImageView(
4376                 contextVk, textureType, image->getAspectFlags(), swizzle, &dstImageView, dstLevelVk,
4377                 1, currentLayer, 1, imageUsageFlags, actualFormatID));
4378 
4379             vk::RenderPassCommandBuffer *commandBuffer = nullptr;
4380             ANGLE_TRY(startRenderPass(contextVk, image, &dstImageView, renderPassDesc, renderArea,
4381                                       VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
4382                                       vk::RenderPassSource::InternalUtils, &commandBuffer));
4383 
4384             UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
4385 
4386             VkDescriptorSet descriptorSet;
4387             ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
4388                                             Function::BlitResolve, &descriptorSet));
4389 
4390             // Update write descriptor info
4391             writeInfos[0].dstSet = descriptorSet;
4392             writeInfos[1].dstSet = descriptorSet;
4393             imageInfos.imageView = srcImageView.getHandle();
4394             vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
4395 
4396             // Update layer index and create pipeline
4397             shaderParams.srcLayer = currentLayer;
4398             ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
4399                                            &mBlitResolve[flags], &pipelineDesc, descriptorSet,
4400                                            &shaderParams, sizeof(shaderParams), commandBuffer));
4401 
4402             // Set dynamic state
4403             commandBuffer->setViewport(0, 1, &viewport);
4404             commandBuffer->setScissor(0, 1, &scissor);
4405             SetDepthDynamicStateForUnused(renderer, commandBuffer);
4406             SetStencilDynamicStateForUnused(renderer, commandBuffer);
4407 
4408             // Note: this utility creates its own framebuffer, thus bypassing
4409             // ContextVk::startRenderPass. As such, occlusion queries are not enabled.
4410             commandBuffer->draw(3, 0);
4411 
4412             contextVk->addGarbage(&srcImageView);
4413             contextVk->addGarbage(&dstImageView);
4414         }
4415 
4416         // Close the render pass for this temporary framebuffer.
4417         ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
4418             RenderPassClosureReason::GenerateMipmapWithDraw));
4419 
4420         srcLevelVk = dstLevelVk;
4421     }
4422 
4423     // Transition the last mipLevel to shader read only optimal layout
4424     outsideCommandBuffer = nullptr;
4425     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &outsideCommandBuffer));
4426 
4427     barrier.subresourceRange.baseMipLevel = maxLevelVK.get();
4428     outsideCommandBuffer->imageBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
4429                                        VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier);
4430 
4431     // Update image's layout related state to shader read only optimal layout
4432     image->setCurrentImageLayout(renderer, vk::ImageLayout::FragmentShaderReadOnly);
4433 
4434     return angle::Result::Continue;
4435 }
4436 
unresolve(ContextVk * contextVk,const FramebufferVk * framebuffer,const UnresolveParameters & params)4437 angle::Result UtilsVk::unresolve(ContextVk *contextVk,
4438                                  const FramebufferVk *framebuffer,
4439                                  const UnresolveParameters &params)
4440 {
4441     vk::Renderer *renderer = contextVk->getRenderer();
4442 
4443     // Get attachment count and pointers to resolve images and views.
4444     gl::DrawBuffersArray<vk::ImageHelper *> colorSrc         = {};
4445     gl::DrawBuffersArray<const vk::ImageView *> colorSrcView = {};
4446 
4447     const vk::ImageView *depthSrcView   = nullptr;
4448     const vk::ImageView *stencilSrcView = nullptr;
4449 
4450     // The subpass that initializes the multisampled-render-to-texture attachments packs the
4451     // attachments that need to be unresolved, so the attachment indices of this subpass are not the
4452     // same.  See InitializeUnresolveSubpass for details.
4453     vk::PackedAttachmentIndex colorIndexVk(0);
4454     for (size_t colorIndexGL : params.unresolveColorMask)
4455     {
4456         RenderTargetVk *colorRenderTarget = framebuffer->getColorDrawRenderTarget(colorIndexGL);
4457 
4458         ASSERT(colorRenderTarget->hasResolveAttachment());
4459         ASSERT(colorRenderTarget->isImageTransient());
4460 
4461         colorSrc[colorIndexVk.get()] = &colorRenderTarget->getResolveImageForRenderPass();
4462         ANGLE_TRY(
4463             colorRenderTarget->getResolveImageView(contextVk, &colorSrcView[colorIndexVk.get()]));
4464 
4465         ++colorIndexVk;
4466     }
4467 
4468     if (params.unresolveDepth || params.unresolveStencil)
4469     {
4470         RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
4471 
4472         ASSERT(depthStencilRenderTarget->hasResolveAttachment());
4473         ASSERT(depthStencilRenderTarget->isImageTransient());
4474 
4475         if (params.unresolveDepth)
4476         {
4477             ANGLE_TRY(depthStencilRenderTarget->getResolveDepthOrStencilImageView(
4478                 contextVk, VK_IMAGE_ASPECT_DEPTH_BIT, &depthSrcView));
4479         }
4480 
4481         if (params.unresolveStencil)
4482         {
4483             ANGLE_TRY(depthStencilRenderTarget->getResolveDepthOrStencilImageView(
4484                 contextVk, VK_IMAGE_ASPECT_STENCIL_BIT, &stencilSrcView));
4485         }
4486     }
4487 
4488     vk::GraphicsPipelineDesc pipelineDesc;
4489     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
4490                               contextVk->pipelineRobustness(),
4491                               contextVk->pipelineProtectedAccess());
4492     pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
4493     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
4494 
4495     vk::RenderPassCommandBuffer *commandBuffer =
4496         &contextVk->getStartedRenderPassCommands().getCommandBuffer();
4497 
4498     vk::ShaderLibrary &shaderLibrary               = contextVk->getShaderLibrary();
4499     vk::ShaderModulePtr vertexShader;
4500     ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
4501 
4502     // Set dynamic state
4503     VkViewport viewport;
4504     gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
4505     bool invertViewport              = contextVk->isViewportFlipEnabledForDrawFBO();
4506     bool clipSpaceOriginUpperLeft =
4507         contextVk->getState().getClipOrigin() == gl::ClipOrigin::UpperLeft;
4508     gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, clipSpaceOriginUpperLeft,
4509                        completeRenderArea.height, &viewport);
4510     commandBuffer->setViewport(0, 1, &viewport);
4511 
4512     VkRect2D scissor = gl_vk::GetRect(completeRenderArea);
4513     commandBuffer->setScissor(0, 1, &scissor);
4514 
4515     // When VK_EXT_shader_stencil_export is enabled, the draw call can directly read from the
4516     // stencil buffer and export it.  When disabled, a special path is taken after the main
4517     // unresolve draw call.
4518     const bool unresolveStencilWithShaderExport =
4519         params.unresolveStencil && contextVk->getFeatures().supportsShaderStencilExport.enabled;
4520 
4521     const uint32_t colorAttachmentCount = colorIndexVk.get();
4522     const uint32_t depthStencilBindingCount =
4523         (params.unresolveDepth ? 1 : 0) + (unresolveStencilWithShaderExport ? 1 : 0);
4524     const uint32_t totalBindingCount = colorAttachmentCount + depthStencilBindingCount;
4525 
4526     if (totalBindingCount > 0)
4527     {
4528         const Function function = static_cast<Function>(
4529             static_cast<uint32_t>(Function::Unresolve1Attachment) + totalBindingCount - 1);
4530 
4531         ANGLE_TRY(ensureUnresolveResourcesInitialized(contextVk, function, totalBindingCount));
4532 
4533         if (params.unresolveDepth)
4534         {
4535             SetDepthStateForWrite(renderer, &pipelineDesc);
4536         }
4537 
4538         if (unresolveStencilWithShaderExport)
4539         {
4540             SetStencilStateForWrite(renderer, &pipelineDesc);
4541         }
4542 
4543         VkDescriptorSet descriptorSet;
4544         ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
4545                                         function, &descriptorSet));
4546 
4547         vk::FramebufferAttachmentArray<VkDescriptorImageInfo> inputImageInfo = {};
4548         uint32_t inputBindingIndex                                           = 0;
4549 
4550         if (unresolveStencilWithShaderExport)
4551         {
4552             inputImageInfo[inputBindingIndex].imageView = stencilSrcView->getHandle();
4553             inputImageInfo[inputBindingIndex].imageLayout =
4554                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4555             ++inputBindingIndex;
4556         }
4557         if (params.unresolveDepth)
4558         {
4559             inputImageInfo[inputBindingIndex].imageView = depthSrcView->getHandle();
4560             inputImageInfo[inputBindingIndex].imageLayout =
4561                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4562             ++inputBindingIndex;
4563         }
4564 
4565         for (uint32_t attachmentIndex = 0; attachmentIndex < colorAttachmentCount;
4566              ++attachmentIndex)
4567         {
4568             inputImageInfo[inputBindingIndex].imageView =
4569                 colorSrcView[attachmentIndex]->getHandle();
4570             inputImageInfo[inputBindingIndex].imageLayout =
4571                 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4572             ++inputBindingIndex;
4573         }
4574 
4575         VkWriteDescriptorSet writeInfo = {};
4576         writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4577         writeInfo.dstSet               = descriptorSet;
4578         writeInfo.dstBinding           = 0;
4579         writeInfo.descriptorCount      = totalBindingCount;
4580         writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
4581         writeInfo.pImageInfo           = inputImageInfo.data();
4582 
4583         vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
4584 
4585         gl::DrawBuffersArray<UnresolveColorAttachmentType> colorAttachmentTypes;
4586         uint32_t flags = GetUnresolveFlags(colorAttachmentCount, colorSrc, params.unresolveDepth,
4587                                            unresolveStencilWithShaderExport, &colorAttachmentTypes);
4588 
4589         vk::ShaderModulePtr &fragmentShader = mUnresolveFragShaders[flags];
4590         ANGLE_TRY(GetUnresolveFrag(contextVk, colorAttachmentCount, colorAttachmentTypes,
4591                                    params.unresolveDepth, params.unresolveStencil,
4592                                    &fragmentShader));
4593 
4594         ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
4595                                        &mUnresolve[flags], &pipelineDesc, descriptorSet, nullptr, 0,
4596                                        commandBuffer));
4597 
4598         if (params.unresolveDepth)
4599         {
4600             SetDepthDynamicStateForWrite(renderer, commandBuffer);
4601         }
4602         else
4603         {
4604             SetDepthDynamicStateForUnused(renderer, commandBuffer);
4605         }
4606 
4607         if (unresolveStencilWithShaderExport)
4608         {
4609             constexpr uint8_t kCompleteMask    = 0xFF;
4610             constexpr uint8_t kUnusedReference = 0x00;
4611 
4612             commandBuffer->setStencilCompareMask(kCompleteMask, kCompleteMask);
4613             commandBuffer->setStencilWriteMask(kCompleteMask, kCompleteMask);
4614             commandBuffer->setStencilReference(kUnusedReference, kUnusedReference);
4615 
4616             SetStencilDynamicStateForWrite(renderer, commandBuffer);
4617         }
4618         else
4619         {
4620             SetStencilDynamicStateForUnused(renderer, commandBuffer);
4621         }
4622 
4623         // This draw call is made before ContextVk gets a chance to start the occlusion query.  As
4624         // such, occlusion queries are not enabled.
4625         commandBuffer->draw(3, 0);
4626     }
4627 
4628     // If stencil needs to be unresolved, but stencil export is not supported, set each bit of
4629     // stencil by adjusting the mask and controlling the output with `discard;` in the shader.  This
4630     // requires that the stencil is cleared to 0 beforehand.
4631     if (params.unresolveStencil && !unresolveStencilWithShaderExport)
4632     {
4633         ANGLE_TRY(ensureExportStencilResourcesInitialized(contextVk));
4634 
4635         // Disable color and depth output, and only let stencil through.
4636         pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
4637 
4638         SetDepthStateForUnused(renderer, &pipelineDesc);
4639         SetStencilStateForWrite(renderer, &pipelineDesc);
4640 
4641         vk::ShaderModulePtr exportStencilShader;
4642         ANGLE_TRY(shaderLibrary.getExportStencil_frag(contextVk, 0, &exportStencilShader));
4643 
4644         // A new descriptor set is needed to match the layout of the ExportStencil program.
4645         VkDescriptorSet exportStencilDescriptorSet;
4646         ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
4647                                         Function::ExportStencil, &exportStencilDescriptorSet));
4648 
4649         VkDescriptorImageInfo stencilImageInfo = {};
4650         stencilImageInfo.imageView             = stencilSrcView->getHandle();
4651         stencilImageInfo.imageLayout           = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4652 
4653         VkWriteDescriptorSet stencilWriteInfo = {};
4654         stencilWriteInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4655         stencilWriteInfo.dstSet               = exportStencilDescriptorSet;
4656         stencilWriteInfo.dstBinding           = 0;
4657         stencilWriteInfo.descriptorCount      = 1;
4658         stencilWriteInfo.descriptorType       = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
4659         stencilWriteInfo.pImageInfo           = &stencilImageInfo;
4660 
4661         vkUpdateDescriptorSets(contextVk->getDevice(), 1, &stencilWriteInfo, 0, nullptr);
4662 
4663         ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ExportStencil, vertexShader,
4664                                        exportStencilShader, &mExportStencil, &pipelineDesc,
4665                                        exportStencilDescriptorSet, nullptr, 0, commandBuffer));
4666 
4667         SetDepthDynamicStateForUnused(renderer, commandBuffer);
4668         SetStencilDynamicStateForWrite(renderer, commandBuffer);
4669 
4670         constexpr uint8_t kCompareMask = 0xFF;
4671         constexpr uint8_t kReference   = 0xFF;
4672         commandBuffer->setStencilCompareMask(kCompareMask, kCompareMask);
4673         commandBuffer->setStencilReference(kReference, kReference);
4674 
4675         // Set each bit in a different draw call.  This is not terribly efficient, but manages to
4676         // keep the transient multisampled stencil data on tile and avoids having to write it back
4677         // to memory / allocate memory for it.
4678         for (uint32_t bit = 0; bit < 8; ++bit)
4679         {
4680             const uint32_t writeMask = 1u << bit;
4681             commandBuffer->setStencilWriteMask(writeMask, writeMask);
4682 
4683             ExportStencilShaderParams shaderParams;
4684             shaderParams.bit = bit;
4685 
4686             commandBuffer->pushConstants(
4687                 *mPipelineLayouts[Function::ExportStencil], VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4688                 /*static_cast<uint32_t>*/ (sizeof(shaderParams)), &shaderParams);
4689 
4690             commandBuffer->draw(3, 0);
4691         }
4692     }
4693 
4694     return angle::Result::Continue;
4695 }
4696 
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)4697 angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
4698                                    vk::BufferHelper *textWidgetsBuffer,
4699                                    vk::BufferHelper *graphWidgetsBuffer,
4700                                    vk::ImageHelper *font,
4701                                    const vk::ImageView *fontView,
4702                                    vk::ImageHelper *dst,
4703                                    const vk::ImageView *destView,
4704                                    const OverlayDrawParameters &params)
4705 {
4706     vk::Renderer *renderer = contextVk->getRenderer();
4707 
4708     ANGLE_TRY(ensureOverlayDrawResourcesInitialized(contextVk));
4709 
4710     OverlayDrawShaderParams shaderParams;
4711     shaderParams.viewportSize[0] = dst->getExtents().width;
4712     shaderParams.viewportSize[1] = dst->getExtents().height;
4713     shaderParams.isText          = false;
4714     shaderParams.rotateXY        = params.rotateXY;
4715     if (params.rotateXY)
4716     {
4717         std::swap(shaderParams.viewportSize[0], shaderParams.viewportSize[1]);
4718     }
4719 
4720     ASSERT(dst->getLevelCount() == 1 && dst->getLayerCount() == 1 &&
4721            dst->getFirstAllocatedLevel() == gl::LevelIndex(0));
4722 
4723     vk::RenderPassDesc renderPassDesc;
4724     renderPassDesc.setSamples(1);
4725     renderPassDesc.packColorAttachment(0, dst->getActualFormatID());
4726 
4727     vk::GraphicsPipelineDesc pipelineDesc;
4728     pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
4729                               contextVk->pipelineRobustness(),
4730                               contextVk->pipelineProtectedAccess());
4731     pipelineDesc.setRenderPassDesc(renderPassDesc);
4732     pipelineDesc.setTopology(gl::PrimitiveMode::TriangleStrip);
4733     pipelineDesc.setSingleBlend(0, true, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_SRC_ALPHA,
4734                                 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
4735 
4736     gl::Rectangle renderArea;
4737     renderArea.x      = 0;
4738     renderArea.y      = 0;
4739     renderArea.width  = shaderParams.viewportSize[0];
4740     renderArea.height = shaderParams.viewportSize[1];
4741 
4742     // A potential optimization is to reuse the already open render pass if it belongs to the
4743     // swapchain.
4744     vk::RenderPassCommandBuffer *commandBuffer;
4745     ANGLE_TRY(startRenderPass(contextVk, dst, destView, renderPassDesc, renderArea,
4746                               VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
4747                               vk::RenderPassSource::DefaultFramebuffer, &commandBuffer));
4748 
4749     vk::RenderPassCommandBufferHelper *commandBufferHelper =
4750         &contextVk->getStartedRenderPassCommands();
4751 
4752     VkDescriptorSet descriptorSet;
4753     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::OverlayDraw,
4754                                     &descriptorSet));
4755 
4756     UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
4757 
4758     commandBufferHelper->retainResource(textWidgetsBuffer);
4759     commandBufferHelper->retainResource(graphWidgetsBuffer);
4760     contextVk->onImageRenderPassRead(VK_IMAGE_ASPECT_COLOR_BIT,
4761                                      vk::ImageLayout::FragmentShaderReadOnly, font);
4762     contextVk->onImageRenderPassWrite(gl::LevelIndex(0), 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
4763                                       vk::ImageLayout::ColorWrite, dst);
4764 
4765     VkDescriptorImageInfo imageInfo = {};
4766     imageInfo.imageView             = fontView->getHandle();
4767     imageInfo.imageLayout           = font->getCurrentLayout(renderer);
4768 
4769     VkDescriptorBufferInfo bufferInfos[2] = {};
4770     bufferInfos[0].buffer                 = textWidgetsBuffer->getBuffer().getHandle();
4771     bufferInfos[0].offset                 = textWidgetsBuffer->getOffset();
4772     bufferInfos[0].range                  = textWidgetsBuffer->getSize();
4773 
4774     bufferInfos[1].buffer = graphWidgetsBuffer->getBuffer().getHandle();
4775     bufferInfos[1].offset = graphWidgetsBuffer->getOffset();
4776     bufferInfos[1].range  = graphWidgetsBuffer->getSize();
4777 
4778     VkWriteDescriptorSet writeInfos[3] = {};
4779     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4780     writeInfos[0].dstSet               = descriptorSet;
4781     writeInfos[0].dstBinding           = kOverlayDrawTextWidgetsBinding;
4782     writeInfos[0].descriptorCount      = 1;
4783     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
4784     writeInfos[0].pBufferInfo          = &bufferInfos[0];
4785 
4786     writeInfos[1]             = writeInfos[0];
4787     writeInfos[1].dstBinding  = kOverlayDrawGraphWidgetsBinding;
4788     writeInfos[1].pBufferInfo = &bufferInfos[1];
4789 
4790     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4791     writeInfos[2].dstSet          = descriptorSet;
4792     writeInfos[2].dstBinding      = kOverlayDrawFontBinding;
4793     writeInfos[2].descriptorCount = 1;
4794     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
4795     writeInfos[2].pImageInfo      = &imageInfo;
4796 
4797     vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
4798 
4799     vk::ShaderLibrary &shaderLibrary                 = contextVk->getShaderLibrary();
4800     vk::ShaderModulePtr vertexShader;
4801     vk::ShaderModulePtr fragmentShader;
4802     ANGLE_TRY(shaderLibrary.getOverlayDraw_vert(contextVk, 0, &vertexShader));
4803     ANGLE_TRY(shaderLibrary.getOverlayDraw_frag(contextVk, 0, &fragmentShader));
4804 
4805     ANGLE_TRY(setupGraphicsProgram(contextVk, Function::OverlayDraw, vertexShader, fragmentShader,
4806                                    &mOverlayDraw, &pipelineDesc, descriptorSet, nullptr, 0,
4807                                    commandBuffer));
4808 
4809     // Set dynamic state
4810     VkViewport viewport;
4811     gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dst->getExtents().height, &viewport);
4812     commandBuffer->setViewport(0, 1, &viewport);
4813 
4814     VkRect2D scissor = gl_vk::GetRect(renderArea);
4815     commandBuffer->setScissor(0, 1, &scissor);
4816 
4817     SetDepthDynamicStateForUnused(renderer, commandBuffer);
4818     SetStencilDynamicStateForUnused(renderer, commandBuffer);
4819 
4820     // Draw all the graph widgets.
4821     if (params.graphWidgetCount > 0)
4822     {
4823         shaderParams.isText = false;
4824         commandBuffer->pushConstants(*mPipelineLayouts[Function::OverlayDraw],
4825                                      VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4826                                      sizeof(shaderParams), &shaderParams);
4827         commandBuffer->drawInstanced(4, params.graphWidgetCount, 0);
4828     }
4829     // Draw all the text widgets.
4830     if (params.textWidgetCount > 0)
4831     {
4832         shaderParams.isText = true;
4833         commandBuffer->pushConstants(*mPipelineLayouts[Function::OverlayDraw],
4834                                      VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4835                                      sizeof(shaderParams), &shaderParams);
4836         commandBuffer->drawInstanced(4, params.textWidgetCount, 0);
4837     }
4838 
4839     // Overlay is always drawn as the last render pass before present.  Automatically move the
4840     // layout to PresentSrc.
4841     contextVk->onColorDraw(gl::LevelIndex(0), 0, 1, dst, nullptr, {}, vk::PackedAttachmentIndex(0));
4842     if (contextVk->getFeatures().supportsPresentation.enabled &&
4843         !contextVk->getFeatures().preferDynamicRendering.enabled)
4844     {
4845         contextVk->getStartedRenderPassCommands().setImageOptimizeForPresent(dst);
4846         contextVk->finalizeImageLayout(dst, {});
4847     }
4848 
4849     // Close the render pass for this temporary framebuffer.
4850     return contextVk->flushCommandsAndEndRenderPass(
4851         RenderPassClosureReason::TemporaryForOverlayDraw);
4852 }
4853 
generateFragmentShadingRate(ContextVk * contextVk,vk::ImageHelper * shadingRateAttachmentImageHelper,vk::ImageViewHelper * shadingRateAttachmentImageViewHelper,const GenerateFragmentShadingRateParameters & shadingRateParameters)4854 angle::Result UtilsVk::generateFragmentShadingRate(
4855     ContextVk *contextVk,
4856     vk::ImageHelper *shadingRateAttachmentImageHelper,
4857     vk::ImageViewHelper *shadingRateAttachmentImageViewHelper,
4858     const GenerateFragmentShadingRateParameters &shadingRateParameters)
4859 {
4860     ANGLE_TRY(ensureGenerateFragmentShadingRateResourcesInitialized(contextVk));
4861 
4862     // Each workgroup processes an 8x8 tile of the image.
4863     constexpr uint32_t kPixelWorkgroupSize = 8;
4864     const uint32_t workGroupX =
4865         UnsignedCeilDivide(shadingRateParameters.attachmentWidth, kPixelWorkgroupSize);
4866     const uint32_t workGroupY =
4867         UnsignedCeilDivide(shadingRateParameters.attachmentHeight, kPixelWorkgroupSize);
4868 
4869     // Setup compute shader
4870     vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
4871     vk::CommandBufferAccess access = {};
4872 
4873     // Fragment shading rate image will always have 1 layer.
4874     access.onImageComputeShaderWrite(shadingRateAttachmentImageHelper->getFirstAllocatedLevel(),
4875                                      shadingRateAttachmentImageHelper->getLevelCount(), 0,
4876                                      shadingRateAttachmentImageHelper->getLayerCount(),
4877                                      shadingRateAttachmentImageHelper->getAspectFlags(),
4878                                      shadingRateAttachmentImageHelper);
4879     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
4880     VkDescriptorSet descriptorSet;
4881     ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
4882                                     Function::GenerateFragmentShadingRate, &descriptorSet));
4883     VkDescriptorImageInfo destShadingRateImage = {};
4884     destShadingRateImage.imageView =
4885         shadingRateAttachmentImageViewHelper->getFragmentShadingRateImageView().getHandle();
4886     destShadingRateImage.imageLayout =
4887         shadingRateAttachmentImageHelper->getCurrentLayout(contextVk->getRenderer());
4888     destShadingRateImage.sampler       = mPointSampler.getHandle();
4889     VkWriteDescriptorSet writeInfos[1] = {};
4890     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4891     writeInfos[0].dstSet               = descriptorSet;
4892     writeInfos[0].dstBinding           = kGenerateFragmentShadingRateAttachmentBinding;
4893     writeInfos[0].descriptorCount      = 1;
4894     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4895     writeInfos[0].pImageInfo           = &destShadingRateImage;
4896 
4897     vkUpdateDescriptorSets(contextVk->getDevice(), 1, writeInfos, 0, nullptr);
4898 
4899     vk::ShaderModulePtr computeShader;
4900     ANGLE_TRY(contextVk->getShaderLibrary().getGenerateFragmentShadingRate_comp(contextVk, 0,
4901                                                                                 &computeShader));
4902 
4903     // Record the command
4904     vk::OutsideRenderPassCommandBuffer *commandBuffer;
4905     commandBuffer = &commandBufferHelper->getCommandBuffer();
4906     ANGLE_TRY(setupComputeProgram(contextVk, Function::GenerateFragmentShadingRate, computeShader,
4907                                   &mGenerateFragmentShadingRateAttachment, descriptorSet,
4908                                   &shadingRateParameters, sizeof(shadingRateParameters),
4909                                   commandBufferHelper));
4910     commandBuffer->dispatch(workGroupX, workGroupY, 1);
4911     return angle::Result::Continue;
4912 }
4913 
allocateDescriptorSetWithLayout(ContextVk * contextVk,vk::CommandBufferHelperCommon * commandBufferHelper,vk::DynamicDescriptorPool & descriptorPool,const vk::DescriptorSetLayout & descriptorSetLayout,VkDescriptorSet * descriptorSetOut)4914 angle::Result UtilsVk::allocateDescriptorSetWithLayout(
4915     ContextVk *contextVk,
4916     vk::CommandBufferHelperCommon *commandBufferHelper,
4917     vk::DynamicDescriptorPool &descriptorPool,
4918     const vk::DescriptorSetLayout &descriptorSetLayout,
4919     VkDescriptorSet *descriptorSetOut)
4920 {
4921     vk::DescriptorSetPointer descriptorSet;
4922 
4923     ANGLE_TRY(descriptorPool.allocateDescriptorSet(contextVk, descriptorSetLayout, &descriptorSet));
4924 
4925     // Retain the individual descriptorSet to the command buffer.
4926     commandBufferHelper->retainResource(descriptorSet.get());
4927 
4928     *descriptorSetOut = descriptorSet->getDescriptorSet();
4929 
4930     return angle::Result::Continue;
4931 }
4932 
allocateDescriptorSet(ContextVk * contextVk,vk::CommandBufferHelperCommon * commandBufferHelper,Function function,VkDescriptorSet * descriptorSetOut)4933 angle::Result UtilsVk::allocateDescriptorSet(ContextVk *contextVk,
4934                                              vk::CommandBufferHelperCommon *commandBufferHelper,
4935                                              Function function,
4936                                              VkDescriptorSet *descriptorSetOut)
4937 {
4938     return allocateDescriptorSetWithLayout(
4939         contextVk, commandBufferHelper, mDescriptorPools[function],
4940         *mDescriptorSetLayouts[function][DescriptorSetIndex::Internal], descriptorSetOut);
4941 }
4942 
allocateDescriptorSetForImageCopyWithSampler(ContextVk * contextVk,vk::CommandBufferHelperCommon * commandBufferHelper,const vk::SamplerDesc & samplerDesc,VkDescriptorSet * descriptorSetOut)4943 angle::Result UtilsVk::allocateDescriptorSetForImageCopyWithSampler(
4944     ContextVk *contextVk,
4945     vk::CommandBufferHelperCommon *commandBufferHelper,
4946     const vk::SamplerDesc &samplerDesc,
4947     VkDescriptorSet *descriptorSetOut)
4948 {
4949     return allocateDescriptorSetWithLayout(
4950         contextVk, commandBufferHelper, mImageCopyWithSamplerDescriptorPools[samplerDesc],
4951         *mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc][DescriptorSetIndex::Internal],
4952         descriptorSetOut);
4953 }
4954 
ClearFramebufferParameters()4955 UtilsVk::ClearFramebufferParameters::ClearFramebufferParameters()
4956     : clearColor(false),
4957       clearDepth(false),
4958       clearStencil(false),
4959       stencilMask(0),
4960       colorMaskFlags(0),
4961       colorAttachmentIndexGL(0),
4962       colorFormat(nullptr),
4963       colorClearValue{},
4964       depthStencilClearValue{}
4965 {}
4966 
4967 // LineLoopHelper implementation.
LineLoopHelper(vk::Renderer * renderer)4968 LineLoopHelper::LineLoopHelper(vk::Renderer *renderer) {}
4969 LineLoopHelper::~LineLoopHelper() = default;
4970 
getIndexBufferForDrawArrays(ContextVk * contextVk,uint32_t clampedVertexCount,GLint firstVertex,vk::BufferHelper ** bufferOut)4971 angle::Result LineLoopHelper::getIndexBufferForDrawArrays(ContextVk *contextVk,
4972                                                           uint32_t clampedVertexCount,
4973                                                           GLint firstVertex,
4974                                                           vk::BufferHelper **bufferOut)
4975 {
4976     size_t allocateBytes = sizeof(uint32_t) * (static_cast<size_t>(clampedVertexCount) + 1);
4977     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
4978                                                        vk::MemoryHostVisibility::Visible));
4979     vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer();
4980     uint32_t *indices             = reinterpret_cast<uint32_t *>(indexBuffer->getMappedMemory());
4981 
4982     // Note: there could be an overflow in this addition.
4983     uint32_t unsignedFirstVertex = static_cast<uint32_t>(firstVertex);
4984     uint32_t vertexCount         = (clampedVertexCount + unsignedFirstVertex);
4985     for (uint32_t vertexIndex = unsignedFirstVertex; vertexIndex < vertexCount; vertexIndex++)
4986     {
4987         *indices++ = vertexIndex;
4988     }
4989     *indices = unsignedFirstVertex;
4990 
4991     // Since we are not using the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT flag when creating the
4992     // device memory in the StreamingBuffer, we always need to make sure we flush it after
4993     // writing.
4994     ANGLE_TRY(indexBuffer->flush(contextVk->getRenderer()));
4995 
4996     *bufferOut = indexBuffer;
4997 
4998     return angle::Result::Continue;
4999 }
5000 
getIndexBufferForElementArrayBuffer(ContextVk * contextVk,BufferVk * elementArrayBufferVk,gl::DrawElementsType glIndexType,int indexCount,intptr_t elementArrayOffset,vk::BufferHelper ** bufferOut,uint32_t * indexCountOut)5001 angle::Result LineLoopHelper::getIndexBufferForElementArrayBuffer(ContextVk *contextVk,
5002                                                                   BufferVk *elementArrayBufferVk,
5003                                                                   gl::DrawElementsType glIndexType,
5004                                                                   int indexCount,
5005                                                                   intptr_t elementArrayOffset,
5006                                                                   vk::BufferHelper **bufferOut,
5007                                                                   uint32_t *indexCountOut)
5008 {
5009     if (glIndexType == gl::DrawElementsType::UnsignedByte ||
5010         contextVk->getState().isPrimitiveRestartEnabled())
5011     {
5012         ANGLE_TRACE_EVENT0("gpu.angle", "LineLoopHelper::getIndexBufferForElementArrayBuffer");
5013 
5014         void *srcDataMapping = nullptr;
5015         ANGLE_TRY(elementArrayBufferVk->mapImpl(contextVk, GL_MAP_READ_BIT, &srcDataMapping));
5016         ANGLE_TRY(streamIndices(contextVk, glIndexType, indexCount,
5017                                 static_cast<const uint8_t *>(srcDataMapping) + elementArrayOffset,
5018                                 bufferOut, indexCountOut));
5019         ANGLE_TRY(elementArrayBufferVk->unmapImpl(contextVk));
5020         return angle::Result::Continue;
5021     }
5022 
5023     *indexCountOut = indexCount + 1;
5024 
5025     size_t unitSize = contextVk->getVkIndexTypeSize(glIndexType);
5026 
5027     size_t allocateBytes = unitSize * (indexCount + 1) + 1;
5028     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
5029                                                        vk::MemoryHostVisibility::Visible));
5030     vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer();
5031 
5032     vk::BufferHelper *sourceBuffer = &elementArrayBufferVk->getBuffer();
5033     VkDeviceSize sourceOffset =
5034         static_cast<VkDeviceSize>(elementArrayOffset) + sourceBuffer->getOffset();
5035     uint64_t unitCount                         = static_cast<VkDeviceSize>(indexCount);
5036     angle::FixedVector<VkBufferCopy, 2> copies = {
5037         {sourceOffset, indexBuffer->getOffset(), unitCount * unitSize},
5038         {sourceOffset, indexBuffer->getOffset() + unitCount * unitSize, unitSize},
5039     };
5040 
5041     vk::CommandBufferAccess access;
5042     access.onBufferTransferWrite(indexBuffer);
5043     access.onBufferTransferRead(sourceBuffer);
5044 
5045     vk::OutsideRenderPassCommandBuffer *commandBuffer;
5046     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
5047 
5048     commandBuffer->copyBuffer(sourceBuffer->getBuffer(), indexBuffer->getBuffer(),
5049                               static_cast<uint32_t>(copies.size()), copies.data());
5050 
5051     ANGLE_TRY(indexBuffer->flush(contextVk->getRenderer()));
5052 
5053     *bufferOut = indexBuffer;
5054 
5055     return angle::Result::Continue;
5056 }
5057 
streamIndices(ContextVk * contextVk,gl::DrawElementsType glIndexType,GLsizei indexCount,const uint8_t * srcPtr,vk::BufferHelper ** bufferOut,uint32_t * indexCountOut)5058 angle::Result LineLoopHelper::streamIndices(ContextVk *contextVk,
5059                                             gl::DrawElementsType glIndexType,
5060                                             GLsizei indexCount,
5061                                             const uint8_t *srcPtr,
5062                                             vk::BufferHelper **bufferOut,
5063                                             uint32_t *indexCountOut)
5064 {
5065     size_t unitSize = contextVk->getVkIndexTypeSize(glIndexType);
5066 
5067     uint32_t numOutIndices = indexCount + 1;
5068     if (contextVk->getState().isPrimitiveRestartEnabled())
5069     {
5070         numOutIndices = GetLineLoopWithRestartIndexCount(glIndexType, indexCount, srcPtr);
5071     }
5072     *indexCountOut = numOutIndices;
5073 
5074     ANGLE_TRY(contextVk->initBufferForVertexConversion(
5075         &mDynamicIndexBuffer, unitSize * numOutIndices, vk::MemoryHostVisibility::Visible));
5076     vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer();
5077     uint8_t *indices              = indexBuffer->getMappedMemory();
5078 
5079     if (contextVk->getState().isPrimitiveRestartEnabled())
5080     {
5081         HandlePrimitiveRestart(contextVk, glIndexType, indexCount, srcPtr, indices);
5082     }
5083     else
5084     {
5085         if (contextVk->shouldConvertUint8VkIndexType(glIndexType))
5086         {
5087             // If vulkan doesn't support uint8 index types, we need to emulate it.
5088             VkIndexType indexType = contextVk->getVkIndexType(glIndexType);
5089             ASSERT(indexType == VK_INDEX_TYPE_UINT16);
5090             uint16_t *indicesDst = reinterpret_cast<uint16_t *>(indices);
5091             for (int i = 0; i < indexCount; i++)
5092             {
5093                 indicesDst[i] = srcPtr[i];
5094             }
5095 
5096             indicesDst[indexCount] = srcPtr[0];
5097         }
5098         else
5099         {
5100             memcpy(indices, srcPtr, unitSize * indexCount);
5101             memcpy(indices + unitSize * indexCount, srcPtr, unitSize);
5102         }
5103     }
5104 
5105     ANGLE_TRY(indexBuffer->flush(contextVk->getRenderer()));
5106 
5107     *bufferOut = indexBuffer;
5108 
5109     return angle::Result::Continue;
5110 }
5111 
streamIndicesIndirect(ContextVk * contextVk,gl::DrawElementsType glIndexType,vk::BufferHelper * srcIndexBuffer,vk::BufferHelper * srcIndirectBuffer,VkDeviceSize indirectBufferOffset,vk::BufferHelper ** dstIndexBufferOut,vk::BufferHelper ** dstIndirectBufferOut)5112 angle::Result LineLoopHelper::streamIndicesIndirect(ContextVk *contextVk,
5113                                                     gl::DrawElementsType glIndexType,
5114                                                     vk::BufferHelper *srcIndexBuffer,
5115                                                     vk::BufferHelper *srcIndirectBuffer,
5116                                                     VkDeviceSize indirectBufferOffset,
5117                                                     vk::BufferHelper **dstIndexBufferOut,
5118                                                     vk::BufferHelper **dstIndirectBufferOut)
5119 {
5120     size_t unitSize      = contextVk->getVkIndexTypeSize(glIndexType);
5121     size_t allocateBytes = static_cast<size_t>(srcIndexBuffer->getSize() + unitSize);
5122 
5123     if (contextVk->getState().isPrimitiveRestartEnabled())
5124     {
5125         // If primitive restart, new index buffer is 135% the size of the original index buffer. The
5126         // smallest lineloop with primitive restart is 3 indices (point 1, point 2 and restart
5127         // value) when converted to linelist becomes 4 vertices. Expansion of 4/3. Any larger
5128         // lineloops would have less overhead and require less extra space. Any incomplete
5129         // primitives can be dropped or left incomplete and thus not increase the size of the
5130         // destination index buffer. Since we don't know the number of indices being used we'll use
5131         // the size of the index buffer as allocated as the index count.
5132         size_t numInputIndices    = static_cast<size_t>(srcIndexBuffer->getSize() / unitSize);
5133         size_t numNewInputIndices = ((numInputIndices * 4) / 3) + 1;
5134         allocateBytes             = static_cast<size_t>(numNewInputIndices * unitSize);
5135     }
5136 
5137     // Allocate buffer for results
5138     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
5139                                                        vk::MemoryHostVisibility::Visible));
5140     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndirectBuffer,
5141                                                        sizeof(VkDrawIndexedIndirectCommand),
5142                                                        vk::MemoryHostVisibility::Visible));
5143 
5144     vk::BufferHelper *dstIndexBuffer    = mDynamicIndexBuffer.getBuffer();
5145     vk::BufferHelper *dstIndirectBuffer = mDynamicIndirectBuffer.getBuffer();
5146 
5147     // Copy relevant section of the source into destination at allocated offset.  Note that the
5148     // offset returned by allocate() above is in bytes. As is the indices offset pointer.
5149     UtilsVk::ConvertLineLoopIndexIndirectParameters params = {};
5150     params.indirectBufferOffset    = static_cast<uint32_t>(indirectBufferOffset);
5151     params.dstIndirectBufferOffset = 0;
5152     params.srcIndexBufferOffset    = 0;
5153     params.dstIndexBufferOffset    = 0;
5154     params.indicesBitsWidth        = static_cast<uint32_t>(unitSize * 8);
5155 
5156     ANGLE_TRY(contextVk->getUtils().convertLineLoopIndexIndirectBuffer(
5157         contextVk, srcIndirectBuffer, srcIndexBuffer, dstIndirectBuffer, dstIndexBuffer, params));
5158 
5159     mDynamicIndexBuffer.clearDirty();
5160     mDynamicIndirectBuffer.clearDirty();
5161 
5162     *dstIndexBufferOut    = dstIndexBuffer;
5163     *dstIndirectBufferOut = dstIndirectBuffer;
5164 
5165     return angle::Result::Continue;
5166 }
5167 
streamArrayIndirect(ContextVk * contextVk,size_t vertexCount,vk::BufferHelper * arrayIndirectBuffer,VkDeviceSize arrayIndirectBufferOffset,vk::BufferHelper ** dstIndexBufferOut,vk::BufferHelper ** dstIndexIndirectBufferOut)5168 angle::Result LineLoopHelper::streamArrayIndirect(ContextVk *contextVk,
5169                                                   size_t vertexCount,
5170                                                   vk::BufferHelper *arrayIndirectBuffer,
5171                                                   VkDeviceSize arrayIndirectBufferOffset,
5172                                                   vk::BufferHelper **dstIndexBufferOut,
5173                                                   vk::BufferHelper **dstIndexIndirectBufferOut)
5174 {
5175     auto unitSize        = sizeof(uint32_t);
5176     size_t allocateBytes = static_cast<size_t>((vertexCount + 1) * unitSize);
5177 
5178     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
5179                                                        vk::MemoryHostVisibility::Visible));
5180     ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndirectBuffer,
5181                                                        sizeof(VkDrawIndexedIndirectCommand),
5182                                                        vk::MemoryHostVisibility::Visible));
5183 
5184     vk::BufferHelper *dstIndexBuffer    = mDynamicIndexBuffer.getBuffer();
5185     vk::BufferHelper *dstIndirectBuffer = mDynamicIndirectBuffer.getBuffer();
5186 
5187     // Copy relevant section of the source into destination at allocated offset.  Note that the
5188     // offset returned by allocate() above is in bytes. As is the indices offset pointer.
5189     UtilsVk::ConvertLineLoopArrayIndirectParameters params = {};
5190     params.indirectBufferOffset    = static_cast<uint32_t>(arrayIndirectBufferOffset);
5191     params.dstIndirectBufferOffset = 0;
5192     params.dstIndexBufferOffset    = 0;
5193 
5194     ANGLE_TRY(contextVk->getUtils().convertLineLoopArrayIndirectBuffer(
5195         contextVk, arrayIndirectBuffer, dstIndirectBuffer, dstIndexBuffer, params));
5196 
5197     mDynamicIndexBuffer.clearDirty();
5198     mDynamicIndirectBuffer.clearDirty();
5199 
5200     *dstIndexBufferOut         = dstIndexBuffer;
5201     *dstIndexIndirectBufferOut = dstIndirectBuffer;
5202 
5203     return angle::Result::Continue;
5204 }
5205 
release(ContextVk * contextVk)5206 void LineLoopHelper::release(ContextVk *contextVk)
5207 {
5208     mDynamicIndexBuffer.release(contextVk->getRenderer());
5209     mDynamicIndirectBuffer.release(contextVk->getRenderer());
5210 }
5211 
destroy(vk::Renderer * renderer)5212 void LineLoopHelper::destroy(vk::Renderer *renderer)
5213 {
5214     mDynamicIndexBuffer.destroy(renderer);
5215     mDynamicIndirectBuffer.destroy(renderer);
5216 }
5217 }  // namespace rx
5218