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