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