• 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/glslang_wrapper_utils.h"
15 #include "libANGLE/renderer/vulkan/ContextVk.h"
16 #include "libANGLE/renderer/vulkan/DisplayVk.h"
17 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
18 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
19 #include "libANGLE/renderer/vulkan/RendererVk.h"
20 #include "libANGLE/renderer/vulkan/vk_utils.h"
21 
22 namespace rx
23 {
24 
25 namespace ConvertVertex_comp                = vk::InternalShader::ConvertVertex_comp;
26 namespace ImageClear_frag                   = vk::InternalShader::ImageClear_frag;
27 namespace ImageCopy_frag                    = vk::InternalShader::ImageCopy_frag;
28 namespace BlitResolve_frag                  = vk::InternalShader::BlitResolve_frag;
29 namespace BlitResolveStencilNoExport_comp   = vk::InternalShader::BlitResolveStencilNoExport_comp;
30 namespace OverlayCull_comp                  = vk::InternalShader::OverlayCull_comp;
31 namespace OverlayDraw_comp                  = vk::InternalShader::OverlayDraw_comp;
32 namespace ConvertIndexIndirectLineLoop_comp = vk::InternalShader::ConvertIndexIndirectLineLoop_comp;
33 namespace GenerateMipmap_comp               = vk::InternalShader::GenerateMipmap_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 kBlitResolveColorOrDepthBinding = 0;
47 constexpr uint32_t kBlitResolveStencilBinding      = 1;
48 constexpr uint32_t kBlitResolveSamplerBinding      = 2;
49 
50 constexpr uint32_t kBlitResolveStencilNoExportDestBinding    = 0;
51 constexpr uint32_t kBlitResolveStencilNoExportSrcBinding     = 1;
52 constexpr uint32_t kBlitResolveStencilNoExportSamplerBinding = 2;
53 
54 constexpr uint32_t kOverlayCullCulledWidgetsBinding = 0;
55 constexpr uint32_t kOverlayCullWidgetCoordsBinding  = 1;
56 
57 constexpr uint32_t kOverlayDrawOutputBinding        = 0;
58 constexpr uint32_t kOverlayDrawTextWidgetsBinding   = 1;
59 constexpr uint32_t kOverlayDrawGraphWidgetsBinding  = 2;
60 constexpr uint32_t kOverlayDrawCulledWidgetsBinding = 3;
61 constexpr uint32_t kOverlayDrawFontBinding          = 4;
62 
63 constexpr uint32_t kGenerateMipmapDestinationBinding = 0;
64 constexpr uint32_t kGenerateMipmapSourceBinding      = 1;
65 
ValidateFloatOneAsUint()66 bool ValidateFloatOneAsUint()
67 {
68     union
69     {
70         uint32_t asUint;
71         float asFloat;
72     } one;
73     one.asUint = gl::Float32One;
74     return one.asFloat == 1.0f;
75 }
76 
GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters & params)77 uint32_t GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters &params)
78 {
79     bool srcIsSint      = params.srcFormat->isSint();
80     bool srcIsUint      = params.srcFormat->isUint();
81     bool srcIsSnorm     = params.srcFormat->isSnorm();
82     bool srcIsUnorm     = params.srcFormat->isUnorm();
83     bool srcIsFixed     = params.srcFormat->isFixed;
84     bool srcIsFloat     = params.srcFormat->isFloat();
85     bool srcIsHalfFloat = params.srcFormat->isVertexTypeHalfFloat();
86 
87     bool destIsSint      = params.destFormat->isSint();
88     bool destIsUint      = params.destFormat->isUint();
89     bool destIsSnorm     = params.destFormat->isSnorm();
90     bool destIsUnorm     = params.destFormat->isUnorm();
91     bool destIsFloat     = params.destFormat->isFloat();
92     bool destIsHalfFloat = params.destFormat->isVertexTypeHalfFloat();
93 
94     // Assert on the types to make sure the shader supports its.  These are based on
95     // ConvertVertex_comp::Conversion values.
96     ASSERT(!destIsSint || srcIsSint);    // If destination is sint, src must be sint too
97     ASSERT(!destIsUint || srcIsUint);    // If destination is uint, src must be uint too
98     ASSERT(!srcIsFixed || destIsFloat);  // If source is fixed, dest must be float
99 
100     // One of each bool set must be true
101     ASSERT(srcIsSint || srcIsUint || srcIsSnorm || srcIsUnorm || srcIsFixed || srcIsFloat);
102     ASSERT(destIsSint || destIsUint || destIsSnorm || destIsUnorm || destIsFloat ||
103            destIsHalfFloat);
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 && destIsHalfFloat)
115     {
116         // Note that HalfFloat conversion uses the same shader as Uint.
117         flags = ConvertVertex_comp::kUintToUint;
118     }
119     else if ((srcIsSnorm && destIsSnorm) || (srcIsUnorm && destIsUnorm))
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.destFormat->redBits);
124         flags = ConvertVertex_comp::kUintToUint;
125     }
126     else if (srcIsSint && destIsSint)
127     {
128         flags = ConvertVertex_comp::kSintToSint;
129     }
130     else if (srcIsUint && destIsUint)
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 vk::Format & srcFormat,const vk::Format & dstFormat)216 uint32_t GetImageCopyFlags(const vk::Format &srcFormat, const vk::Format &dstFormat)
217 {
218     const angle::Format &srcIntendedFormat = srcFormat.intendedFormat();
219     const angle::Format &dstIntendedFormat = dstFormat.intendedFormat();
220 
221     uint32_t flags = 0;
222 
223     flags |= GetFormatFlags(srcIntendedFormat, ImageCopy_frag::kSrcIsSint,
224                             ImageCopy_frag::kSrcIsUint, ImageCopy_frag::kSrcIsFloat);
225     flags |= GetFormatFlags(dstIntendedFormat, ImageCopy_frag::kDestIsSint,
226                             ImageCopy_frag::kDestIsUint, ImageCopy_frag::kDestIsFloat);
227 
228     return flags;
229 }
230 
GetBlitResolveFlags(bool blitColor,bool blitDepth,bool blitStencil,const vk::Format & format)231 uint32_t GetBlitResolveFlags(bool blitColor,
232                              bool blitDepth,
233                              bool blitStencil,
234                              const vk::Format &format)
235 {
236     if (blitColor)
237     {
238         const angle::Format &intendedFormat = format.intendedFormat();
239 
240         return GetFormatFlags(intendedFormat, BlitResolve_frag::kBlitColorInt,
241                               BlitResolve_frag::kBlitColorUint, BlitResolve_frag::kBlitColorFloat);
242     }
243 
244     if (blitDepth)
245     {
246         if (blitStencil)
247         {
248             return BlitResolve_frag::kBlitDepthStencil;
249         }
250         else
251         {
252             return BlitResolve_frag::kBlitDepth;
253         }
254     }
255     else
256     {
257         return BlitResolve_frag::kBlitStencil;
258     }
259 }
260 
GetConvertIndexIndirectLineLoopFlag(uint32_t indicesBitsWidth)261 uint32_t GetConvertIndexIndirectLineLoopFlag(uint32_t indicesBitsWidth)
262 {
263     switch (indicesBitsWidth)
264     {
265         case 8:
266             return ConvertIndexIndirectLineLoop_comp::kIs8Bits;
267         case 16:
268             return ConvertIndexIndirectLineLoop_comp::kIs16Bits;
269         case 32:
270             return ConvertIndexIndirectLineLoop_comp::kIs32Bits;
271         default:
272             UNREACHABLE();
273             return 0;
274     }
275 }
276 
GetGenerateMipmapFlags(ContextVk * contextVk,const vk::Format & format)277 uint32_t GetGenerateMipmapFlags(ContextVk *contextVk, const vk::Format &format)
278 {
279     const angle::Format &actualFormat = format.actualImageFormat();
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]->getFormat().intendedFormat();
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 vk::Format & format)363 uint32_t GetFormatDefaultChannelMask(const vk::Format &format)
364 {
365     uint32_t mask = 0;
366 
367     const angle::Format &intendedFormat = format.intendedFormat();
368     const angle::Format &imageFormat    = format.actualImageFormat();
369 
370     // Red can never be introduced due to format emulation (except for luma which is handled
371     // especially)
372     ASSERT(((intendedFormat.redBits > 0) == (imageFormat.redBits > 0)) || intendedFormat.isLUMA());
373     mask |= intendedFormat.greenBits == 0 && imageFormat.greenBits > 0 ? 2 : 0;
374     mask |= intendedFormat.blueBits == 0 && imageFormat.blueBits > 0 ? 4 : 0;
375     mask |= intendedFormat.alphaBits == 0 && imageFormat.alphaBits > 0 ? 8 : 0;
376 
377     return mask;
378 }
379 
380 // Calculate the transformation offset for blit/resolve.  See BlitResolve.frag for details on how
381 // these values are derived.
CalculateBlitOffset(const UtilsVk::BlitResolveParameters & params,float offset[2])382 void CalculateBlitOffset(const UtilsVk::BlitResolveParameters &params, float offset[2])
383 {
384     int srcOffsetFactorX = params.flipX ? -1 : 1;
385     int srcOffsetFactorY = params.flipY ? -1 : 1;
386 
387     offset[0] = params.destOffset[0] * params.stretch[0] - params.srcOffset[0] * srcOffsetFactorX;
388     offset[1] = params.destOffset[1] * params.stretch[1] - params.srcOffset[1] * srcOffsetFactorY;
389 }
390 
CalculateResolveOffset(const UtilsVk::BlitResolveParameters & params,int32_t offset[2])391 void CalculateResolveOffset(const UtilsVk::BlitResolveParameters &params, int32_t offset[2])
392 {
393     int srcOffsetFactorX = params.flipX ? -1 : 1;
394     int srcOffsetFactorY = params.flipY ? -1 : 1;
395 
396     // There's no stretching in resolve.
397     offset[0] = params.destOffset[0] - params.srcOffset[0] * srcOffsetFactorX;
398     offset[1] = params.destOffset[1] - params.srcOffset[1] * srcOffsetFactorY;
399 }
400 
401 // Sets the appropriate settings in the pipeline for the shader to output stencil.  Requires the
402 // shader stencil export extension.
SetStencilForShaderExport(ContextVk * contextVk,vk::GraphicsPipelineDesc * desc)403 void SetStencilForShaderExport(ContextVk *contextVk, vk::GraphicsPipelineDesc *desc)
404 {
405     ASSERT(contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled);
406 
407     const uint8_t completeMask    = 0xFF;
408     const uint8_t unusedReference = 0x00;
409 
410     desc->setStencilTestEnabled(true);
411     desc->setStencilFrontFuncs(unusedReference, VK_COMPARE_OP_ALWAYS, completeMask);
412     desc->setStencilBackFuncs(unusedReference, VK_COMPARE_OP_ALWAYS, completeMask);
413     desc->setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE);
414     desc->setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE);
415     desc->setStencilFrontWriteMask(completeMask);
416     desc->setStencilBackWriteMask(completeMask);
417 }
418 
419 namespace unresolve
420 {
421 // The unresolve shader looks like the following, based on the number and types of unresolve
422 // attachments.
423 //
424 //     #version 450 core
425 //     #extension GL_ARB_shader_stencil_export : require
426 //
427 //     layout(location = 0) out vec4 colorOut0;
428 //     layout(location = 1) out ivec4 colorOut1;
429 //     layout(location = 2) out uvec4 colorOut2;
430 //     layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput colorIn0;
431 //     layout(input_attachment_index = 1, set = 0, binding = 1) uniform isubpassInput colorIn1;
432 //     layout(input_attachment_index = 2, set = 0, binding = 2) uniform usubpassInput colorIn2;
433 //     layout(input_attachment_index = 3, set = 0, binding = 3) uniform subpassInput depthIn;
434 //     layout(input_attachment_index = 3, set = 0, binding = 4) uniform usubpassInput stencilIn;
435 //
436 //     void main()
437 //     {
438 //         colorOut0 = subpassLoad(colorIn0);
439 //         colorOut1 = subpassLoad(colorIn1);
440 //         colorOut2 = subpassLoad(colorIn2);
441 //         gl_FragDepth = subpassLoad(depthIn).x;
442 //         gl_FragStencilRefARB = int(subpassLoad(stencilIn).x);
443 //     }
444 //
445 // This shader compiles to the following SPIR-V:
446 //
447 //           OpCapability Shader                              \
448 //           OpCapability InputAttachment                      \
449 //           OpCapability StencilExportEXT                      \   Preamble.  Mostly fixed, except
450 //           OpExtension "SPV_EXT_shader_stencil_export"         \  OpEntryPoint should enumerate
451 //      %1 = OpExtInstImport "GLSL.std.450"                       \ out variables, stencil export
452 //           OpMemoryModel Logical GLSL450                        / is conditional to stencil
453 //           OpEntryPoint Fragment %4 "main" %26 %27 %28 %29 %30 /  unresolve, and depth replacing
454 //           OpExecutionMode %4 OriginUpperLeft                 /   conditional to depth unresolve.
455 //           OpExecutionMode %4 DepthReplacing                 /
456 //           OpSource GLSL 450                                /
457 //
458 //           OpName %4 "main"              \
459 //           OpName %26 "colorOut0"         \
460 //           OpName %27 "colorOut1"          \
461 //           OpName %28 "colorOut2"           \
462 //           OpName %29 "gl_FragDepth"         \ Debug information.  Not generated here.
463 //           OpName %30 "gl_FragStencilRefARB" /
464 //           OpName %31 "colorIn0"            /
465 //           OpName %32 "colorIn1"           /
466 //           OpName %33 "colorIn2"          /
467 //           OpName %34 "depthIn"          /
468 //           OpName %35 "stencilIn"       /
469 //
470 //           OpDecorate %26 Location 0      \
471 //           OpDecorate %27 Location 1       \ Location decoration of out variables.
472 //           OpDecorate %28 Location 2       /
473 //
474 //           OpDecorate %29 BuiltIn FragDepth          \ Builtin outputs, conditional to depth
475 //           OpDecorate %30 BuiltIn FragStencilRefEXT  / and stencil unresolve.
476 //
477 //           OpDecorate %31 DescriptorSet 0        \
478 //           OpDecorate %31 Binding 0               \
479 //           OpDecorate %31 InputAttachmentIndex 0   \
480 //           OpDecorate %32 DescriptorSet 0           \
481 //           OpDecorate %32 Binding 1                  \
482 //           OpDecorate %32 InputAttachmentIndex 1      \
483 //           OpDecorate %33 DescriptorSet 0              \  set, binding and input_attachment
484 //           OpDecorate %33 Binding 2                     \ decorations of the subpassInput
485 //           OpDecorate %33 InputAttachmentIndex 2        / variables.
486 //           OpDecorate %34 DescriptorSet 0              /
487 //           OpDecorate %34 Binding 3                   /
488 //           OpDecorate %34 InputAttachmentIndex 3     /
489 //           OpDecorate %35 DescriptorSet 0           /
490 //           OpDecorate %35 Binding 4                /
491 //           OpDecorate %35 InputAttachmentIndex 3  /
492 //
493 //      %2 = OpTypeVoid         \ Type of main().  Fixed.
494 //      %3 = OpTypeFunction %2  /
495 //
496 //      %6 = OpTypeFloat 32                             \
497 //      %7 = OpTypeVector %6 4                           \
498 //      %8 = OpTypePointer Output %7                      \ Type declaration for "out vec4"
499 //      %9 = OpTypeImage %6 SubpassData 0 0 0 2 Unknown   / and "subpassInput".  Fixed.
500 //     %10 = OpTypePointer UniformConstant %9            /
501 //
502 //     %11 = OpTypeInt 32 1                              \
503 //     %12 = OpTypeVector %11 4                           \
504 //     %13 = OpTypePointer Output %12                      \ Type declaration for "out ivec4"
505 //     %14 = OpTypeImage %11 SubpassData 0 0 0 2 Unknown   / and "isubpassInput".  Fixed.
506 //     %15 = OpTypePointer UniformConstant %14            /
507 //
508 //     %16 = OpTypeInt 32 0                              \
509 //     %17 = OpTypeVector %16 4                           \
510 //     %18 = OpTypePointer Output %17                      \ Type declaration for "out uvec4"
511 //     %19 = OpTypeImage %16 SubpassData 0 0 0 2 Unknown   / and "usubpassInput".  Fixed.
512 //     %20 = OpTypePointer UniformConstant %19            /
513 //
514 //     %21 = OpTypePointer Output %6         \ Type declaraions for depth and stencil. Fixed.
515 //     %22 = OpTypePointer Output %11        /
516 //
517 //     %23 = OpConstant %11 0                \
518 //     %24 = OpTypeVector %11 2               \ ivec2(0) for OpImageRead.  subpassLoad
519 //     %25 = OpConstantComposite %22 %21 %21  / doesn't require coordinates.  Fixed.
520 //
521 //     %26 = OpVariable %8 Output            \
522 //     %27 = OpVariable %13 Output            \
523 //     %28 = OpVariable %18 Output             \
524 //     %29 = OpVariable %21 Output              \
525 //     %30 = OpVariable %22 Output               \ Actual "out" and "*subpassInput"
526 //     %31 = OpVariable %10 UniformConstant      / variable declarations.
527 //     %32 = OpVariable %15 UniformConstant     /
528 //     %33 = OpVariable %20 UniformConstant    /
529 //     %34 = OpVariable %10 UniformConstant   /
530 //     %35 = OpVariable %20 UniformConstant  /
531 //
532 //      %4 = OpFunction %2 None %3   \ Top of main().  Fixed.
533 //      %5 = OpLabel                 /
534 //
535 //     %36 = OpLoad %9 %31           \
536 //     %37 = OpImageRead %7 %36 %23   \ colorOut0 = subpassLoad(colorIn0);
537 //           OpStore %26 %37          /
538 //
539 //     %38 = OpLoad %14 %32          \
540 //     %39 = OpImageRead %12 %38 %23  \ colorOut1 = subpassLoad(colorIn1);
541 //           OpStore %27 %39          /
542 //
543 //     %40 = OpLoad %19 %33          \
544 //     %41 = OpImageRead %17 %40 %23  \ colorOut2 = subpassLoad(colorIn2);
545 //           OpStore %28 %41          /
546 //
547 //     %42 = OpLoad %9 %34              \
548 //     %43 = OpImageRead %7 %42 %23      \ gl_FragDepth = subpassLoad(depthIn).x;
549 //     %44 = OpCompositeExtract %6 %43 0 /
550 //           OpStore %29 %44            /
551 //
552 //     %45 = OpLoad %19 %35              \
553 //     %46 = OpImageRead %17 %45 %23      \
554 //     %47 = OpCompositeExtract %16 %46 0  \ gl_FragStencilRefARB = int(subpassLoad(stencilIn).x);
555 //     %48 = OpBitcast %11 %47             /
556 //           OpStore %30 %48              /
557 //
558 //           OpReturn           \ Bottom of main().  Fixed.
559 //           OpFunctionEnd      /
560 //
561 // What makes the generation of this shader manageable is that the majority of it is constant
562 // between the different variations of the shader.  The rest are repeating patterns with different
563 // ids or indices.
564 
565 enum
566 {
567     // main() ids
568     kIdExtInstImport = 1,
569     kIdVoid,
570     kIdMainType,
571     kIdMain,
572     kIdMainLabel,
573 
574     // Types for "out vec4" and "subpassInput"
575     kIdFloatType,
576     kIdFloat4Type,
577     kIdFloat4OutType,
578     kIdFloatSubpassImageType,
579     kIdFloatSubpassInputType,
580 
581     // Types for "out ivec4" and "isubpassInput"
582     kIdSIntType,
583     kIdSInt4Type,
584     kIdSInt4OutType,
585     kIdSIntSubpassImageType,
586     kIdSIntSubpassInputType,
587 
588     // Types for "out uvec4" and "usubpassInput"
589     kIdUIntType,
590     kIdUInt4Type,
591     kIdUInt4OutType,
592     kIdUIntSubpassImageType,
593     kIdUIntSubpassInputType,
594 
595     // Types for gl_FragDepth && gl_FragStencilRefARB
596     kIdFloatOutType,
597     kIdSIntOutType,
598 
599     // ivec2(0) constant
600     kIdSIntZero,
601     kIdSInt2Type,
602     kIdSInt2Zero,
603 
604     // Output variable ids
605     kIdColor0Out,
606     kIdDepthOut = kIdColor0Out + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
607     kIdStencilOut,
608 
609     // Input variable ids
610     kIdColor0In,
611     kIdDepthIn = kIdColor0In + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS,
612     kIdStencilIn,
613 
614     // Ids for temp variables
615     kIdColor0Load,
616     // 2 temp ids per color unresolve
617     kIdDepthLoad = kIdColor0Load + gl::IMPLEMENTATION_MAX_DRAW_BUFFERS * 2,
618     // 3 temp ids for depth unresolve
619     kIdStencilLoad = kIdDepthLoad + 3,
620     // Total number of ids used
621     // 4 temp ids for stencil unresolve
622     kIdCount = kIdStencilLoad + 4,
623 };
624 
InsertPreamble(uint32_t colorAttachmentCount,bool unresolveDepth,bool unresolveStencil,angle::spirv::Blob * blobOut)625 void InsertPreamble(uint32_t colorAttachmentCount,
626                     bool unresolveDepth,
627                     bool unresolveStencil,
628                     angle::spirv::Blob *blobOut)
629 {
630     spirv::WriteCapability(blobOut, spv::CapabilityShader);
631     spirv::WriteCapability(blobOut, spv::CapabilityInputAttachment);
632     if (unresolveStencil)
633     {
634         spirv::WriteCapability(blobOut, spv::CapabilityStencilExportEXT);
635         spirv::WriteExtension(blobOut, "SPV_EXT_shader_stencil_export");
636     }
637     // OpExtInstImport is actually not needed by this shader.  We don't use any instructions from
638     // GLSL.std.450.
639     spirv::WriteMemoryModel(blobOut, spv::AddressingModelLogical, spv::MemoryModelGLSL450);
640 
641     // Create the list of entry point ids, including only the out variables.
642     spirv::IdRefList entryPointIds;
643     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; ++colorIndex)
644     {
645         entryPointIds.push_back(spirv::IdRef(kIdColor0Out + colorIndex));
646     }
647     if (unresolveDepth)
648     {
649         entryPointIds.push_back(spirv::IdRef(kIdDepthOut));
650     }
651     if (unresolveStencil)
652     {
653         entryPointIds.push_back(spirv::IdRef(kIdStencilOut));
654     }
655     spirv::WriteEntryPoint(blobOut, spv::ExecutionModelFragment, spirv::IdRef(kIdMain), "main",
656                            entryPointIds);
657 
658     spirv::WriteExecutionMode(blobOut, spirv::IdRef(kIdMain), spv::ExecutionModeOriginUpperLeft,
659                               {});
660     if (unresolveDepth)
661     {
662         spirv::WriteExecutionMode(blobOut, spirv::IdRef(kIdMain), spv::ExecutionModeDepthReplacing,
663                                   {});
664     }
665     spirv::WriteSource(blobOut, spv::SourceLanguageGLSL, spirv::LiteralInteger(450), nullptr,
666                        nullptr);
667 }
668 
InsertInputDecorations(spirv::IdRef id,uint32_t attachmentIndex,uint32_t binding,angle::spirv::Blob * blobOut)669 void InsertInputDecorations(spirv::IdRef id,
670                             uint32_t attachmentIndex,
671                             uint32_t binding,
672                             angle::spirv::Blob *blobOut)
673 {
674     spirv::WriteDecorate(blobOut, id, spv::DecorationDescriptorSet,
675                          {spirv::LiteralInteger(ToUnderlying(DescriptorSetIndex::Internal))});
676     spirv::WriteDecorate(blobOut, id, spv::DecorationBinding, {spirv::LiteralInteger(binding)});
677     spirv::WriteDecorate(blobOut, id, spv::DecorationInputAttachmentIndex,
678                          {spirv::LiteralInteger(attachmentIndex)});
679 }
680 
InsertColorDecorations(uint32_t colorIndex,angle::spirv::Blob * blobOut)681 void InsertColorDecorations(uint32_t colorIndex, angle::spirv::Blob *blobOut)
682 {
683     // Decorate the output color attachment with Location
684     spirv::WriteDecorate(blobOut, spirv::IdRef(kIdColor0Out + colorIndex), spv::DecorationLocation,
685                          {spirv::LiteralInteger(colorIndex)});
686     // Decorate the subpasss input color attachment with Set/Binding/InputAttachmentIndex.
687     InsertInputDecorations(spirv::IdRef(kIdColor0In + colorIndex), colorIndex, colorIndex, blobOut);
688 }
689 
InsertDepthStencilDecorations(uint32_t depthStencilInputIndex,uint32_t depthStencilBindingIndex,bool unresolveDepth,bool unresolveStencil,angle::spirv::Blob * blobOut)690 void InsertDepthStencilDecorations(uint32_t depthStencilInputIndex,
691                                    uint32_t depthStencilBindingIndex,
692                                    bool unresolveDepth,
693                                    bool unresolveStencil,
694                                    angle::spirv::Blob *blobOut)
695 {
696     if (unresolveDepth)
697     {
698         // Decorate the output depth attachment with Location
699         spirv::WriteDecorate(blobOut, spirv::IdRef(kIdDepthOut), spv::DecorationBuiltIn,
700                              {spirv::LiteralInteger(spv::BuiltInFragDepth)});
701         // Decorate the subpasss input depth attachment with Set/Binding/InputAttachmentIndex.
702         InsertInputDecorations(spirv::IdRef(kIdDepthIn), depthStencilInputIndex,
703                                depthStencilBindingIndex, blobOut);
704         // Advance the binding.  Note that the depth/stencil attachment has the same input
705         // attachment index (it's the same attachment in the subpass), but different bindings (one
706         // aspect per image view).
707         ++depthStencilBindingIndex;
708     }
709     if (unresolveStencil)
710     {
711         // Decorate the output stencil attachment with Location
712         spirv::WriteDecorate(blobOut, spirv::IdRef(kIdStencilOut), spv::DecorationBuiltIn,
713                              {spirv::LiteralInteger(spv::BuiltInFragStencilRefEXT)});
714         // Decorate the subpasss input stencil attachment with Set/Binding/InputAttachmentIndex.
715         InsertInputDecorations(spirv::IdRef(kIdStencilIn), depthStencilInputIndex,
716                                depthStencilBindingIndex, blobOut);
717     }
718 }
719 
InsertDerivativeTypes(spirv::IdRef baseId,spirv::IdRef vec4Id,spirv::IdRef vec4OutId,spirv::IdRef imageTypeId,spirv::IdRef inputTypeId,angle::spirv::Blob * blobOut)720 void InsertDerivativeTypes(spirv::IdRef baseId,
721                            spirv::IdRef vec4Id,
722                            spirv::IdRef vec4OutId,
723                            spirv::IdRef imageTypeId,
724                            spirv::IdRef inputTypeId,
725                            angle::spirv::Blob *blobOut)
726 {
727     spirv::WriteTypeVector(blobOut, vec4Id, baseId, spirv::LiteralInteger(4));
728     spirv::WriteTypePointer(blobOut, vec4OutId, spv::StorageClassOutput, vec4Id);
729     spirv::WriteTypeImage(blobOut, imageTypeId, baseId, spv::DimSubpassData,
730                           // Unused with subpass inputs
731                           spirv::LiteralInteger(0),
732                           // Not arrayed
733                           spirv::LiteralInteger(0),
734                           // Not multisampled
735                           spirv::LiteralInteger(0),
736                           // Used without a sampler
737                           spirv::LiteralInteger(2), spv::ImageFormatUnknown, nullptr);
738     spirv::WriteTypePointer(blobOut, inputTypeId, spv::StorageClassUniformConstant, imageTypeId);
739 }
740 
InsertCommonTypes(angle::spirv::Blob * blobOut)741 void InsertCommonTypes(angle::spirv::Blob *blobOut)
742 {
743     // Types to support main().
744     spirv::WriteTypeVoid(blobOut, spirv::IdRef(kIdVoid));
745     spirv::WriteTypeFunction(blobOut, spirv::IdRef(kIdMainType), spirv::IdRef(kIdVoid), {});
746 
747     // Float types
748     spirv::WriteTypeFloat(blobOut, spirv::IdRef(kIdFloatType), spirv::LiteralInteger(32));
749     InsertDerivativeTypes(spirv::IdRef(kIdFloatType), spirv::IdRef(kIdFloat4Type),
750                           spirv::IdRef(kIdFloat4OutType), spirv::IdRef(kIdFloatSubpassImageType),
751                           spirv::IdRef(kIdFloatSubpassInputType), blobOut);
752 
753     // Int types
754     spirv::WriteTypeInt(blobOut, spirv::IdRef(kIdSIntType), spirv::LiteralInteger(32),
755                         spirv::LiteralInteger(1));
756     InsertDerivativeTypes(spirv::IdRef(kIdSIntType), spirv::IdRef(kIdSInt4Type),
757                           spirv::IdRef(kIdSInt4OutType), spirv::IdRef(kIdSIntSubpassImageType),
758                           spirv::IdRef(kIdSIntSubpassInputType), blobOut);
759 
760     // Unsigned int types
761     spirv::WriteTypeInt(blobOut, spirv::IdRef(kIdUIntType), spirv::LiteralInteger(32),
762                         spirv::LiteralInteger(0));
763     InsertDerivativeTypes(spirv::IdRef(kIdUIntType), spirv::IdRef(kIdUInt4Type),
764                           spirv::IdRef(kIdUInt4OutType), spirv::IdRef(kIdUIntSubpassImageType),
765                           spirv::IdRef(kIdUIntSubpassInputType), blobOut);
766 
767     // Types to support depth/stencil
768     spirv::WriteTypePointer(blobOut, spirv::IdRef(kIdFloatOutType), spv::StorageClassOutput,
769                             spirv::IdRef(kIdFloatType));
770     spirv::WriteTypePointer(blobOut, spirv::IdRef(kIdSIntOutType), spv::StorageClassOutput,
771                             spirv::IdRef(kIdSIntType));
772 
773     // Constants used to load from subpass inputs
774     spirv::WriteConstant(blobOut, spirv::IdRef(kIdSIntType), spirv::IdRef(kIdSIntZero),
775                          spirv::LiteralInteger(0));
776     spirv::WriteTypeVector(blobOut, spirv::IdRef(kIdSInt2Type), spirv::IdRef(kIdSIntType),
777                            spirv::LiteralInteger(2));
778     spirv::WriteConstantComposite(blobOut, spirv::IdRef(kIdSInt2Type), spirv::IdRef(kIdSInt2Zero),
779                                   {spirv::IdRef(kIdSIntZero), spirv::IdRef(kIdSIntZero)});
780 }
781 
InsertVariableDecl(spirv::IdRef outType,spirv::IdRef outId,spirv::IdRef inType,spirv::IdRef inId,angle::spirv::Blob * blobOut)782 void InsertVariableDecl(spirv::IdRef outType,
783                         spirv::IdRef outId,
784                         spirv::IdRef inType,
785                         spirv::IdRef inId,
786                         angle::spirv::Blob *blobOut)
787 {
788     // Declare both the output and subpass input variables.
789     spirv::WriteVariable(blobOut, outType, outId, spv::StorageClassOutput, nullptr);
790     spirv::WriteVariable(blobOut, inType, inId, spv::StorageClassUniformConstant, nullptr);
791 }
792 
InsertColorVariableDecl(uint32_t colorIndex,UnresolveColorAttachmentType type,angle::spirv::Blob * blobOut)793 void InsertColorVariableDecl(uint32_t colorIndex,
794                              UnresolveColorAttachmentType type,
795                              angle::spirv::Blob *blobOut)
796 {
797     // Find the correct types for color variable declarations.
798     spirv::IdRef outType(kIdFloat4OutType);
799     spirv::IdRef outId(kIdColor0Out + colorIndex);
800     spirv::IdRef inType(kIdFloatSubpassInputType);
801     spirv::IdRef inId(kIdColor0In + colorIndex);
802     switch (type)
803     {
804         case kUnresolveTypeSint:
805             outType = spirv::IdRef(kIdSInt4OutType);
806             inType  = spirv::IdRef(kIdSIntSubpassInputType);
807             break;
808         case kUnresolveTypeUint:
809             outType = spirv::IdRef(kIdUInt4OutType);
810             inType  = spirv::IdRef(kIdUIntSubpassInputType);
811             break;
812         default:
813             break;
814     }
815     InsertVariableDecl(outType, outId, inType, inId, blobOut);
816 }
817 
InsertDepthStencilVariableDecl(bool unresolveDepth,bool unresolveStencil,angle::spirv::Blob * blobOut)818 void InsertDepthStencilVariableDecl(bool unresolveDepth,
819                                     bool unresolveStencil,
820                                     angle::spirv::Blob *blobOut)
821 {
822     if (unresolveDepth)
823     {
824         InsertVariableDecl(spirv::IdRef(kIdFloatOutType), spirv::IdRef(kIdDepthOut),
825                            spirv::IdRef(kIdFloatSubpassInputType), spirv::IdRef(kIdDepthIn),
826                            blobOut);
827     }
828     if (unresolveStencil)
829     {
830         InsertVariableDecl(spirv::IdRef(kIdSIntOutType), spirv::IdRef(kIdStencilOut),
831                            spirv::IdRef(kIdUIntSubpassInputType), spirv::IdRef(kIdStencilIn),
832                            blobOut);
833     }
834 }
835 
InsertTopOfMain(angle::spirv::Blob * blobOut)836 void InsertTopOfMain(angle::spirv::Blob *blobOut)
837 {
838     spirv::WriteFunction(blobOut, spirv::IdRef(kIdVoid), spirv::IdRef(kIdMain),
839                          spv::FunctionControlMaskNone, spirv::IdRef(kIdMainType));
840     spirv::WriteLabel(blobOut, spirv::IdRef(kIdMainLabel));
841 }
842 
InsertColorUnresolveLoadStore(uint32_t colorIndex,UnresolveColorAttachmentType type,angle::spirv::Blob * blobOut)843 void InsertColorUnresolveLoadStore(uint32_t colorIndex,
844                                    UnresolveColorAttachmentType type,
845                                    angle::spirv::Blob *blobOut)
846 {
847     spirv::IdRef loadResult(kIdColor0Load + colorIndex * 2);
848     spirv::IdRef imageReadResult(loadResult + 1);
849 
850     // Find the correct types for load/store.
851     spirv::IdRef loadType(kIdFloatSubpassImageType);
852     spirv::IdRef readType(kIdFloat4Type);
853     spirv::IdRef inId(kIdColor0In + colorIndex);
854     spirv::IdRef outId(kIdColor0Out + colorIndex);
855     switch (type)
856     {
857         case kUnresolveTypeSint:
858             loadType = spirv::IdRef(kIdSIntSubpassImageType);
859             readType = spirv::IdRef(kIdSInt4Type);
860             break;
861         case kUnresolveTypeUint:
862             loadType = spirv::IdRef(kIdUIntSubpassImageType);
863             readType = spirv::IdRef(kIdUInt4Type);
864             break;
865         default:
866             break;
867     }
868 
869     // Load the subpass input image, read from it, and store in output.
870     spirv::WriteLoad(blobOut, loadType, loadResult, inId, nullptr);
871     spirv::WriteImageRead(blobOut, readType, imageReadResult, loadResult,
872                           spirv::IdRef(kIdSInt2Zero), nullptr, {});
873     spirv::WriteStore(blobOut, outId, imageReadResult, nullptr);
874 }
875 
InsertDepthStencilUnresolveLoadStore(bool unresolveDepth,bool unresolveStencil,angle::spirv::Blob * blobOut)876 void InsertDepthStencilUnresolveLoadStore(bool unresolveDepth,
877                                           bool unresolveStencil,
878                                           angle::spirv::Blob *blobOut)
879 {
880     if (unresolveDepth)
881     {
882         spirv::IdRef loadResult(kIdDepthLoad);
883         spirv::IdRef imageReadResult(loadResult + 1);
884         spirv::IdRef extractResult(imageReadResult + 1);
885 
886         spirv::IdRef loadType(kIdFloatSubpassImageType);
887         spirv::IdRef readType(kIdFloat4Type);
888         spirv::IdRef inId(kIdDepthIn);
889         spirv::IdRef outId(kIdDepthOut);
890 
891         // Load the subpass input image, read from it, select .x, and store in output.
892         spirv::WriteLoad(blobOut, loadType, loadResult, inId, nullptr);
893         spirv::WriteImageRead(blobOut, readType, imageReadResult, loadResult,
894                               spirv::IdRef(kIdSInt2Zero), nullptr, {});
895         spirv::WriteCompositeExtract(blobOut, spirv::IdRef(kIdFloatType), extractResult,
896                                      imageReadResult, {spirv::LiteralInteger(0)});
897         spirv::WriteStore(blobOut, outId, extractResult, nullptr);
898     }
899     if (unresolveStencil)
900     {
901         spirv::IdRef loadResult(kIdStencilLoad);
902         spirv::IdRef imageReadResult(loadResult + 1);
903         spirv::IdRef extractResult(imageReadResult + 1);
904         spirv::IdRef bitcastResult(extractResult + 1);
905 
906         spirv::IdRef loadType(kIdUIntSubpassImageType);
907         spirv::IdRef readType(kIdUInt4Type);
908         spirv::IdRef inId(kIdStencilIn);
909         spirv::IdRef outId(kIdStencilOut);
910 
911         // Load the subpass input image, read from it, select .x, and store in output.  There's a
912         // bitcast involved since the stencil subpass input has unsigned type, while
913         // gl_FragStencilRefARB is signed!
914         spirv::WriteLoad(blobOut, loadType, loadResult, inId, nullptr);
915         spirv::WriteImageRead(blobOut, readType, imageReadResult, loadResult,
916                               spirv::IdRef(kIdSInt2Zero), nullptr, {});
917         spirv::WriteCompositeExtract(blobOut, spirv::IdRef(kIdUIntType), extractResult,
918                                      imageReadResult, {spirv::LiteralInteger(0)});
919         spirv::WriteBitcast(blobOut, spirv::IdRef(kIdSIntType), bitcastResult, extractResult);
920         spirv::WriteStore(blobOut, outId, bitcastResult, nullptr);
921     }
922 }
923 
InsertBottomOfMain(angle::spirv::Blob * blobOut)924 void InsertBottomOfMain(angle::spirv::Blob *blobOut)
925 {
926     spirv::WriteReturn(blobOut);
927     spirv::WriteFunctionEnd(blobOut);
928 }
929 
MakeFragShader(uint32_t colorAttachmentCount,gl::DrawBuffersArray<UnresolveColorAttachmentType> & colorAttachmentTypes,bool unresolveDepth,bool unresolveStencil)930 angle::spirv::Blob MakeFragShader(
931     uint32_t colorAttachmentCount,
932     gl::DrawBuffersArray<UnresolveColorAttachmentType> &colorAttachmentTypes,
933     bool unresolveDepth,
934     bool unresolveStencil)
935 {
936     angle::spirv::Blob code;
937 
938     // Reserve a sensible amount of memory.  A single-attachment shader is 169 words.
939     code.reserve(169);
940 
941     // Header
942     spirv::WriteSpirvHeader(&code, kIdCount);
943 
944     // The preamble
945     InsertPreamble(colorAttachmentCount, unresolveDepth, unresolveStencil, &code);
946 
947     // Color attachment decorations
948     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; ++colorIndex)
949     {
950         InsertColorDecorations(colorIndex, &code);
951     }
952 
953     const uint32_t depthStencilInputIndex = colorAttachmentCount;
954     uint32_t depthStencilBindingIndex     = colorAttachmentCount;
955     InsertDepthStencilDecorations(depthStencilInputIndex, depthStencilBindingIndex, unresolveDepth,
956                                   unresolveStencil, &code);
957 
958     // Common types
959     InsertCommonTypes(&code);
960 
961     // Attachment declarations
962     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; ++colorIndex)
963     {
964         InsertColorVariableDecl(colorIndex, colorAttachmentTypes[colorIndex], &code);
965     }
966     InsertDepthStencilVariableDecl(unresolveDepth, unresolveStencil, &code);
967 
968     // Top of main
969     InsertTopOfMain(&code);
970 
971     // Load and store for each attachment
972     for (uint32_t colorIndex = 0; colorIndex < colorAttachmentCount; ++colorIndex)
973     {
974         InsertColorUnresolveLoadStore(colorIndex, colorAttachmentTypes[colorIndex], &code);
975     }
976     InsertDepthStencilUnresolveLoadStore(unresolveDepth, unresolveStencil, &code);
977 
978     // Bottom of main
979     InsertBottomOfMain(&code);
980 
981     return code;
982 }
983 }  // namespace unresolve
984 
GetUnresolveFrag(vk::Context * context,uint32_t colorAttachmentCount,gl::DrawBuffersArray<UnresolveColorAttachmentType> & colorAttachmentTypes,bool unresolveDepth,bool unresolveStencil,vk::RefCounted<vk::ShaderAndSerial> * shader)985 angle::Result GetUnresolveFrag(
986     vk::Context *context,
987     uint32_t colorAttachmentCount,
988     gl::DrawBuffersArray<UnresolveColorAttachmentType> &colorAttachmentTypes,
989     bool unresolveDepth,
990     bool unresolveStencil,
991     vk::RefCounted<vk::ShaderAndSerial> *shader)
992 {
993     if (shader->get().valid())
994     {
995         return angle::Result::Continue;
996     }
997 
998     angle::spirv::Blob shaderCode = unresolve::MakeFragShader(
999         colorAttachmentCount, colorAttachmentTypes, unresolveDepth, unresolveStencil);
1000 
1001     ASSERT(spirv::Validate(shaderCode));
1002 
1003     // Create shader lazily. Access will need to be locked for multi-threading.
1004     return vk::InitShaderAndSerial(context, &shader->get(), shaderCode.data(),
1005                                    shaderCode.size() * 4);
1006 }
1007 }  // namespace
1008 
1009 const uint32_t UtilsVk::kGenerateMipmapMaxLevels;
1010 
1011 UtilsVk::ConvertVertexShaderParams::ConvertVertexShaderParams() = default;
1012 
1013 UtilsVk::ImageCopyShaderParams::ImageCopyShaderParams() = default;
1014 
GetGenerateMipmapMaxLevels(ContextVk * contextVk)1015 uint32_t UtilsVk::GetGenerateMipmapMaxLevels(ContextVk *contextVk)
1016 {
1017     RendererVk *renderer = contextVk->getRenderer();
1018 
1019     uint32_t maxPerStageDescriptorStorageImages =
1020         renderer->getPhysicalDeviceProperties().limits.maxPerStageDescriptorStorageImages;
1021 
1022     // Vulkan requires that there be support for at least 4 storage images per stage.
1023     constexpr uint32_t kMinimumStorageImagesLimit = 4;
1024     ASSERT(maxPerStageDescriptorStorageImages >= kMinimumStorageImagesLimit);
1025 
1026     // If fewer than max-levels are supported, use 4 levels (which is the minimum required number
1027     // of storage image bindings).
1028     return maxPerStageDescriptorStorageImages < kGenerateMipmapMaxLevels
1029                ? kMinimumStorageImagesLimit
1030                : kGenerateMipmapMaxLevels;
1031 }
1032 
UtilsVk()1033 UtilsVk::UtilsVk() : mPerfCounters{}, mCumulativePerfCounters{} {}
1034 
1035 UtilsVk::~UtilsVk() = default;
1036 
destroy(RendererVk * renderer)1037 void UtilsVk::destroy(RendererVk *renderer)
1038 {
1039     VkDevice device = renderer->getDevice();
1040 
1041     outputCumulativePerfCounters();
1042 
1043     for (Function f : angle::AllEnums<Function>())
1044     {
1045         for (auto &descriptorSetLayout : mDescriptorSetLayouts[f])
1046         {
1047             descriptorSetLayout.reset();
1048         }
1049         mPipelineLayouts[f].reset();
1050         mDescriptorPools[f].destroy(device);
1051     }
1052 
1053     for (vk::ShaderProgramHelper &program : mConvertIndexPrograms)
1054     {
1055         program.destroy(renderer);
1056     }
1057     for (vk::ShaderProgramHelper &program : mConvertIndirectLineLoopPrograms)
1058     {
1059         program.destroy(renderer);
1060     }
1061     for (vk::ShaderProgramHelper &program : mConvertIndexIndirectLineLoopPrograms)
1062     {
1063         program.destroy(renderer);
1064     }
1065     for (vk::ShaderProgramHelper &program : mConvertVertexPrograms)
1066     {
1067         program.destroy(renderer);
1068     }
1069     mImageClearProgramVSOnly.destroy(renderer);
1070     for (vk::ShaderProgramHelper &program : mImageClearProgram)
1071     {
1072         program.destroy(renderer);
1073     }
1074     for (vk::ShaderProgramHelper &program : mImageCopyPrograms)
1075     {
1076         program.destroy(renderer);
1077     }
1078     for (vk::ShaderProgramHelper &program : mBlitResolvePrograms)
1079     {
1080         program.destroy(renderer);
1081     }
1082     for (vk::ShaderProgramHelper &program : mBlitResolveStencilNoExportPrograms)
1083     {
1084         program.destroy(renderer);
1085     }
1086     for (vk::ShaderProgramHelper &program : mOverlayCullPrograms)
1087     {
1088         program.destroy(renderer);
1089     }
1090     for (vk::ShaderProgramHelper &program : mOverlayDrawPrograms)
1091     {
1092         program.destroy(renderer);
1093     }
1094     for (vk::ShaderProgramHelper &program : mGenerateMipmapPrograms)
1095     {
1096         program.destroy(renderer);
1097     }
1098 
1099     for (auto &programIter : mUnresolvePrograms)
1100     {
1101         vk::ShaderProgramHelper &program = programIter.second;
1102         program.destroy(renderer);
1103     }
1104     mUnresolvePrograms.clear();
1105 
1106     for (auto &shaderIter : mUnresolveFragShaders)
1107     {
1108         vk::RefCounted<vk::ShaderAndSerial> &shader = shaderIter.second;
1109         shader.get().destroy(device);
1110     }
1111     mUnresolveFragShaders.clear();
1112 
1113     mPointSampler.destroy(device);
1114     mLinearSampler.destroy(device);
1115 }
1116 
ensureResourcesInitialized(ContextVk * contextVk,Function function,VkDescriptorPoolSize * setSizes,size_t setSizesCount,size_t pushConstantsSize)1117 angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
1118                                                   Function function,
1119                                                   VkDescriptorPoolSize *setSizes,
1120                                                   size_t setSizesCount,
1121                                                   size_t pushConstantsSize)
1122 {
1123     vk::DescriptorSetLayoutDesc descriptorSetDesc;
1124     bool isCompute = function >= Function::ComputeStartIndex;
1125     const VkShaderStageFlags descStages =
1126         isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
1127 
1128     uint32_t currentBinding = 0;
1129     for (size_t i = 0; i < setSizesCount; ++i)
1130     {
1131         descriptorSetDesc.update(currentBinding, setSizes[i].type, setSizes[i].descriptorCount,
1132                                  descStages, nullptr);
1133         ++currentBinding;
1134     }
1135 
1136     ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1137         contextVk, descriptorSetDesc,
1138         &mDescriptorSetLayouts[function][DescriptorSetIndex::Internal]));
1139 
1140     vk::DescriptorSetLayoutBindingVector bindingVector;
1141     std::vector<VkSampler> immutableSamplers;
1142     descriptorSetDesc.unpackBindings(&bindingVector, &immutableSamplers);
1143     std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
1144 
1145     for (const VkDescriptorSetLayoutBinding &binding : bindingVector)
1146     {
1147         if (binding.descriptorCount > 0)
1148         {
1149             VkDescriptorPoolSize poolSize = {};
1150 
1151             poolSize.type            = binding.descriptorType;
1152             poolSize.descriptorCount = binding.descriptorCount;
1153             descriptorPoolSizes.emplace_back(poolSize);
1154         }
1155     }
1156     if (!descriptorPoolSizes.empty())
1157     {
1158         ANGLE_TRY(mDescriptorPools[function].init(
1159             contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
1160             mDescriptorSetLayouts[function][DescriptorSetIndex::Internal].get().getHandle()));
1161     }
1162 
1163     gl::ShaderType pushConstantsShaderStage =
1164         isCompute ? gl::ShaderType::Compute : gl::ShaderType::Fragment;
1165 
1166     // Corresponding pipeline layouts:
1167     vk::PipelineLayoutDesc pipelineLayoutDesc;
1168 
1169     pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Internal, descriptorSetDesc);
1170     if (pushConstantsSize)
1171     {
1172         pipelineLayoutDesc.updatePushConstantRange(pushConstantsShaderStage, 0,
1173                                                    static_cast<uint32_t>(pushConstantsSize));
1174     }
1175 
1176     ANGLE_TRY(contextVk->getPipelineLayoutCache().getPipelineLayout(contextVk, pipelineLayoutDesc,
1177                                                                     mDescriptorSetLayouts[function],
1178                                                                     &mPipelineLayouts[function]));
1179 
1180     return angle::Result::Continue;
1181 }
1182 
ensureConvertIndexResourcesInitialized(ContextVk * contextVk)1183 angle::Result UtilsVk::ensureConvertIndexResourcesInitialized(ContextVk *contextVk)
1184 {
1185     if (mPipelineLayouts[Function::ConvertIndexBuffer].valid())
1186     {
1187         return angle::Result::Continue;
1188     }
1189 
1190     VkDescriptorPoolSize setSizes[2] = {
1191         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1192         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1193     };
1194 
1195     return ensureResourcesInitialized(contextVk, Function::ConvertIndexBuffer, setSizes,
1196                                       ArraySize(setSizes), sizeof(ConvertIndexShaderParams));
1197 }
1198 
ensureConvertIndexIndirectResourcesInitialized(ContextVk * contextVk)1199 angle::Result UtilsVk::ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk)
1200 {
1201     if (mPipelineLayouts[Function::ConvertIndexIndirectBuffer].valid())
1202     {
1203         return angle::Result::Continue;
1204     }
1205 
1206     VkDescriptorPoolSize setSizes[4] = {
1207         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest index buffer
1208         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // source index buffer
1209         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // src indirect buffer
1210         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest indirect buffer
1211     };
1212 
1213     return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectBuffer, setSizes,
1214                                       ArraySize(setSizes),
1215                                       sizeof(ConvertIndexIndirectShaderParams));
1216 }
1217 
ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk * contextVk)1218 angle::Result UtilsVk::ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
1219 {
1220     if (mPipelineLayouts[Function::ConvertIndexIndirectLineLoopBuffer].valid())
1221     {
1222         return angle::Result::Continue;
1223     }
1224 
1225     VkDescriptorPoolSize setSizes[4] = {
1226         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // cmd buffer
1227         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest cmd buffer
1228         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // source index buffer
1229         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest index buffer
1230     };
1231 
1232     return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
1233                                       setSizes, ArraySize(setSizes),
1234                                       sizeof(ConvertIndexIndirectLineLoopShaderParams));
1235 }
1236 
ensureConvertIndirectLineLoopResourcesInitialized(ContextVk * contextVk)1237 angle::Result UtilsVk::ensureConvertIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
1238 {
1239     if (mPipelineLayouts[Function::ConvertIndirectLineLoopBuffer].valid())
1240     {
1241         return angle::Result::Continue;
1242     }
1243 
1244     VkDescriptorPoolSize setSizes[3] = {
1245         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // cmd buffer
1246         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest cmd buffer
1247         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},  // dest index buffer
1248     };
1249 
1250     return ensureResourcesInitialized(contextVk, Function::ConvertIndirectLineLoopBuffer, setSizes,
1251                                       ArraySize(setSizes),
1252                                       sizeof(ConvertIndirectLineLoopShaderParams));
1253 }
1254 
ensureConvertVertexResourcesInitialized(ContextVk * contextVk)1255 angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk)
1256 {
1257     if (mPipelineLayouts[Function::ConvertVertexBuffer].valid())
1258     {
1259         return angle::Result::Continue;
1260     }
1261 
1262     VkDescriptorPoolSize setSizes[2] = {
1263         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1264         {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1265     };
1266 
1267     return ensureResourcesInitialized(contextVk, Function::ConvertVertexBuffer, setSizes,
1268                                       ArraySize(setSizes), sizeof(ConvertVertexShaderParams));
1269 }
1270 
ensureImageClearResourcesInitialized(ContextVk * contextVk)1271 angle::Result UtilsVk::ensureImageClearResourcesInitialized(ContextVk *contextVk)
1272 {
1273     if (mPipelineLayouts[Function::ImageClear].valid())
1274     {
1275         return angle::Result::Continue;
1276     }
1277 
1278     // The shader does not use any descriptor sets.
1279     return ensureResourcesInitialized(contextVk, Function::ImageClear, nullptr, 0,
1280                                       sizeof(ImageClearShaderParams));
1281 }
1282 
ensureImageCopyResourcesInitialized(ContextVk * contextVk)1283 angle::Result UtilsVk::ensureImageCopyResourcesInitialized(ContextVk *contextVk)
1284 {
1285     if (mPipelineLayouts[Function::ImageCopy].valid())
1286     {
1287         return angle::Result::Continue;
1288     }
1289 
1290     VkDescriptorPoolSize setSizes[1] = {
1291         {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1292     };
1293 
1294     return ensureResourcesInitialized(contextVk, Function::ImageCopy, setSizes, ArraySize(setSizes),
1295                                       sizeof(ImageCopyShaderParams));
1296 }
1297 
ensureBlitResolveResourcesInitialized(ContextVk * contextVk)1298 angle::Result UtilsVk::ensureBlitResolveResourcesInitialized(ContextVk *contextVk)
1299 {
1300     if (!mPipelineLayouts[Function::BlitResolve].valid())
1301     {
1302         VkDescriptorPoolSize setSizes[3] = {
1303             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1304             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1305             {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
1306         };
1307 
1308         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolve, setSizes,
1309                                              ArraySize(setSizes), sizeof(BlitResolveShaderParams)));
1310     }
1311 
1312     return ensureSamplersInitialized(contextVk);
1313 }
1314 
ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk * contextVk)1315 angle::Result UtilsVk::ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk *contextVk)
1316 {
1317     if (!mPipelineLayouts[Function::BlitResolveStencilNoExport].valid())
1318     {
1319         VkDescriptorPoolSize setSizes[3] = {
1320             {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1321             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1322             {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
1323         };
1324 
1325         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolveStencilNoExport,
1326                                              setSizes, ArraySize(setSizes),
1327                                              sizeof(BlitResolveStencilNoExportShaderParams)));
1328     }
1329 
1330     return ensureSamplersInitialized(contextVk);
1331 }
1332 
ensureOverlayCullResourcesInitialized(ContextVk * contextVk)1333 angle::Result UtilsVk::ensureOverlayCullResourcesInitialized(ContextVk *contextVk)
1334 {
1335     if (mPipelineLayouts[Function::OverlayCull].valid())
1336     {
1337         return angle::Result::Continue;
1338     }
1339 
1340     VkDescriptorPoolSize setSizes[2] = {
1341         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
1342         {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
1343     };
1344 
1345     return ensureResourcesInitialized(contextVk, Function::OverlayCull, setSizes,
1346                                       ArraySize(setSizes), 0);
1347 }
1348 
ensureOverlayDrawResourcesInitialized(ContextVk * contextVk)1349 angle::Result UtilsVk::ensureOverlayDrawResourcesInitialized(ContextVk *contextVk)
1350 {
1351     if (!mPipelineLayouts[Function::OverlayDraw].valid())
1352     {
1353         VkDescriptorPoolSize setSizes[5] = {
1354             {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},  {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
1355             {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1}, {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1356             {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1357         };
1358 
1359         ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::OverlayDraw, setSizes,
1360                                              ArraySize(setSizes), sizeof(OverlayDrawShaderParams)));
1361     }
1362 
1363     return ensureSamplersInitialized(contextVk);
1364 }
1365 
ensureGenerateMipmapResourcesInitialized(ContextVk * contextVk)1366 angle::Result UtilsVk::ensureGenerateMipmapResourcesInitialized(ContextVk *contextVk)
1367 {
1368     if (mPipelineLayouts[Function::GenerateMipmap].valid())
1369     {
1370         return angle::Result::Continue;
1371     }
1372 
1373     VkDescriptorPoolSize setSizes[2] = {
1374         {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, GetGenerateMipmapMaxLevels(contextVk)},
1375         {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1},
1376     };
1377 
1378     return ensureResourcesInitialized(contextVk, Function::GenerateMipmap, setSizes,
1379                                       ArraySize(setSizes), sizeof(GenerateMipmapShaderParams));
1380 }
1381 
ensureUnresolveResourcesInitialized(ContextVk * contextVk,Function function,uint32_t attachmentCount)1382 angle::Result UtilsVk::ensureUnresolveResourcesInitialized(ContextVk *contextVk,
1383                                                            Function function,
1384                                                            uint32_t attachmentCount)
1385 {
1386     ASSERT(static_cast<uint32_t>(function) -
1387                static_cast<uint32_t>(Function::Unresolve1Attachment) ==
1388            attachmentCount - 1);
1389 
1390     if (mPipelineLayouts[function].valid())
1391     {
1392         return angle::Result::Continue;
1393     }
1394 
1395     vk::FramebufferAttachmentArray<VkDescriptorPoolSize> setSizes;
1396     std::fill(setSizes.begin(), setSizes.end(),
1397               VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1});
1398 
1399     return ensureResourcesInitialized(contextVk, function, setSizes.data(), attachmentCount, 0);
1400 }
1401 
ensureSamplersInitialized(ContextVk * contextVk)1402 angle::Result UtilsVk::ensureSamplersInitialized(ContextVk *contextVk)
1403 {
1404     VkSamplerCreateInfo samplerInfo     = {};
1405     samplerInfo.sType                   = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
1406     samplerInfo.flags                   = 0;
1407     samplerInfo.magFilter               = VK_FILTER_NEAREST;
1408     samplerInfo.minFilter               = VK_FILTER_NEAREST;
1409     samplerInfo.mipmapMode              = VK_SAMPLER_MIPMAP_MODE_NEAREST;
1410     samplerInfo.addressModeU            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1411     samplerInfo.addressModeV            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1412     samplerInfo.addressModeW            = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1413     samplerInfo.mipLodBias              = 0.0f;
1414     samplerInfo.anisotropyEnable        = VK_FALSE;
1415     samplerInfo.maxAnisotropy           = 1;
1416     samplerInfo.compareEnable           = VK_FALSE;
1417     samplerInfo.compareOp               = VK_COMPARE_OP_ALWAYS;
1418     samplerInfo.minLod                  = 0;
1419     samplerInfo.maxLod                  = 0;
1420     samplerInfo.borderColor             = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
1421     samplerInfo.unnormalizedCoordinates = VK_FALSE;
1422 
1423     if (!mPointSampler.valid())
1424     {
1425         ANGLE_VK_TRY(contextVk, mPointSampler.init(contextVk->getDevice(), samplerInfo));
1426     }
1427 
1428     samplerInfo.magFilter = VK_FILTER_LINEAR;
1429     samplerInfo.minFilter = VK_FILTER_LINEAR;
1430 
1431     if (!mLinearSampler.valid())
1432     {
1433         ANGLE_VK_TRY(contextVk, mLinearSampler.init(contextVk->getDevice(), samplerInfo));
1434     }
1435 
1436     return angle::Result::Continue;
1437 }
1438 
setupProgram(ContextVk * contextVk,Function function,vk::RefCounted<vk::ShaderAndSerial> * fsCsShader,vk::RefCounted<vk::ShaderAndSerial> * vsShader,vk::ShaderProgramHelper * program,const vk::GraphicsPipelineDesc * pipelineDesc,const VkDescriptorSet descriptorSet,const void * pushConstants,size_t pushConstantsSize,vk::CommandBuffer * commandBuffer)1439 angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
1440                                     Function function,
1441                                     vk::RefCounted<vk::ShaderAndSerial> *fsCsShader,
1442                                     vk::RefCounted<vk::ShaderAndSerial> *vsShader,
1443                                     vk::ShaderProgramHelper *program,
1444                                     const vk::GraphicsPipelineDesc *pipelineDesc,
1445                                     const VkDescriptorSet descriptorSet,
1446                                     const void *pushConstants,
1447                                     size_t pushConstantsSize,
1448                                     vk::CommandBuffer *commandBuffer)
1449 {
1450     RendererVk *renderer = contextVk->getRenderer();
1451 
1452     const bool isCompute = function >= Function::ComputeStartIndex;
1453     const VkShaderStageFlags pushConstantsShaderStage =
1454         isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
1455     const VkPipelineBindPoint pipelineBindPoint =
1456         isCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
1457 
1458     // If compute, vsShader and pipelineDesc should be nullptr, and if not compute they shouldn't
1459     // be.
1460     ASSERT(isCompute != (vsShader && pipelineDesc));
1461 
1462     const vk::BindingPointer<vk::PipelineLayout> &pipelineLayout = mPipelineLayouts[function];
1463 
1464     Serial serial = contextVk->getCurrentQueueSerial();
1465 
1466     if (isCompute)
1467     {
1468         vk::PipelineAndSerial *pipelineAndSerial;
1469         program->setShader(gl::ShaderType::Compute, fsCsShader);
1470         ANGLE_TRY(program->getComputePipeline(contextVk, pipelineLayout.get(), &pipelineAndSerial));
1471         // TODO: https://issuetracker.google.com/issues/169788986: Update serial handling.
1472         pipelineAndSerial->updateSerial(serial);
1473         commandBuffer->bindComputePipeline(pipelineAndSerial->get());
1474 
1475         contextVk->invalidateComputePipelineBinding();
1476     }
1477     else
1478     {
1479         program->setShader(gl::ShaderType::Vertex, vsShader);
1480         if (fsCsShader)
1481         {
1482             program->setShader(gl::ShaderType::Fragment, fsCsShader);
1483         }
1484 
1485         // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
1486         const vk::GraphicsPipelineDesc *descPtr;
1487         vk::PipelineHelper *helper;
1488         vk::PipelineCache *pipelineCache = nullptr;
1489         ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
1490         ANGLE_TRY(program->getGraphicsPipeline(
1491             contextVk, &contextVk->getRenderPassCache(), *pipelineCache, pipelineLayout.get(),
1492             *pipelineDesc, gl::AttributesMask(), gl::ComponentTypeMask(), &descPtr, &helper));
1493         helper->updateSerial(serial);
1494         commandBuffer->bindGraphicsPipeline(helper->getPipeline());
1495 
1496         contextVk->invalidateGraphicsPipelineBinding();
1497     }
1498 
1499     if (descriptorSet != VK_NULL_HANDLE)
1500     {
1501         commandBuffer->bindDescriptorSets(pipelineLayout.get(), pipelineBindPoint,
1502                                           DescriptorSetIndex::Internal, 1, &descriptorSet, 0,
1503                                           nullptr);
1504         if (isCompute)
1505         {
1506             contextVk->invalidateComputeDescriptorSet(DescriptorSetIndex::Internal);
1507         }
1508         else
1509         {
1510             contextVk->invalidateGraphicsDescriptorSet(DescriptorSetIndex::Internal);
1511         }
1512     }
1513 
1514     if (pushConstants)
1515     {
1516         commandBuffer->pushConstants(pipelineLayout.get(), pushConstantsShaderStage, 0,
1517                                      static_cast<uint32_t>(pushConstantsSize), pushConstants);
1518     }
1519 
1520     return angle::Result::Continue;
1521 }
1522 
convertIndexBuffer(ContextVk * contextVk,vk::BufferHelper * dest,vk::BufferHelper * src,const ConvertIndexParameters & params)1523 angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
1524                                           vk::BufferHelper *dest,
1525                                           vk::BufferHelper *src,
1526                                           const ConvertIndexParameters &params)
1527 {
1528     ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk));
1529 
1530     vk::CommandBufferAccess access;
1531     access.onBufferComputeShaderRead(src);
1532     access.onBufferComputeShaderWrite(dest);
1533 
1534     vk::CommandBuffer *commandBuffer;
1535     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1536 
1537     VkDescriptorSet descriptorSet;
1538     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1539     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexBuffer, &descriptorPoolBinding,
1540                                     &descriptorSet));
1541 
1542     std::array<VkDescriptorBufferInfo, 2> buffers = {{
1543         {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1544         {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1545     }};
1546 
1547     VkWriteDescriptorSet writeInfo = {};
1548     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1549     writeInfo.dstSet               = descriptorSet;
1550     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
1551     writeInfo.descriptorCount      = 2;
1552     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1553     writeInfo.pBufferInfo          = buffers.data();
1554 
1555     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1556 
1557     ConvertIndexShaderParams shaderParams = {params.srcOffset, params.dstOffset >> 2,
1558                                              params.maxIndex, 0};
1559 
1560     uint32_t flags = 0;
1561     if (contextVk->getState().isPrimitiveRestartEnabled())
1562     {
1563         flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
1564     }
1565 
1566     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1567     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
1568 
1569     ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexBuffer, shader, nullptr,
1570                            &mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
1571                            sizeof(ConvertIndexShaderParams), commandBuffer));
1572 
1573     constexpr uint32_t kInvocationsPerGroup = 64;
1574     constexpr uint32_t kInvocationsPerIndex = 2;
1575     const uint32_t kIndexCount              = params.maxIndex;
1576     const uint32_t kGroupCount =
1577         UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
1578     commandBuffer->dispatch(kGroupCount, 1, 1);
1579 
1580     descriptorPoolBinding.reset();
1581 
1582     return angle::Result::Continue;
1583 }
1584 
convertIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuf,vk::BufferHelper * srcIndexBuf,vk::BufferHelper * dstIndirectBuf,vk::BufferHelper * dstIndexBuf,const ConvertIndexIndirectParameters & params)1585 angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
1586                                                   vk::BufferHelper *srcIndirectBuf,
1587                                                   vk::BufferHelper *srcIndexBuf,
1588                                                   vk::BufferHelper *dstIndirectBuf,
1589                                                   vk::BufferHelper *dstIndexBuf,
1590                                                   const ConvertIndexIndirectParameters &params)
1591 {
1592     ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk));
1593 
1594     vk::CommandBufferAccess access;
1595     access.onBufferComputeShaderRead(srcIndirectBuf);
1596     access.onBufferComputeShaderRead(srcIndexBuf);
1597     access.onBufferComputeShaderWrite(dstIndirectBuf);
1598     access.onBufferComputeShaderWrite(dstIndexBuf);
1599 
1600     vk::CommandBuffer *commandBuffer;
1601     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1602 
1603     VkDescriptorSet descriptorSet;
1604     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1605     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexIndirectBuffer,
1606                                     &descriptorPoolBinding, &descriptorSet));
1607 
1608     std::array<VkDescriptorBufferInfo, 4> buffers = {{
1609         {dstIndexBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1610         {srcIndexBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1611         {srcIndirectBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1612         {dstIndirectBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1613     }};
1614 
1615     VkWriteDescriptorSet writeInfo = {};
1616     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1617     writeInfo.dstSet               = descriptorSet;
1618     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
1619     writeInfo.descriptorCount      = 4;
1620     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1621     writeInfo.pBufferInfo          = buffers.data();
1622 
1623     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1624 
1625     ConvertIndexIndirectShaderParams shaderParams = {
1626         params.srcIndirectBufOffset >> 2, params.srcIndexBufOffset, params.dstIndexBufOffset >> 2,
1627         params.maxIndex, params.dstIndirectBufOffset >> 2};
1628 
1629     uint32_t flags = vk::InternalShader::ConvertIndex_comp::kIsIndirect;
1630     if (contextVk->getState().isPrimitiveRestartEnabled())
1631     {
1632         flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
1633     }
1634 
1635     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1636     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
1637 
1638     ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader, nullptr,
1639                            &mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
1640                            sizeof(ConvertIndexIndirectShaderParams), commandBuffer));
1641 
1642     constexpr uint32_t kInvocationsPerGroup = 64;
1643     constexpr uint32_t kInvocationsPerIndex = 2;
1644     const uint32_t kIndexCount              = params.maxIndex;
1645     const uint32_t kGroupCount =
1646         UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
1647     commandBuffer->dispatch(kGroupCount, 1, 1);
1648 
1649     descriptorPoolBinding.reset();
1650 
1651     return angle::Result::Continue;
1652 }
1653 
convertLineLoopIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * dstIndirectBuffer,vk::BufferHelper * dstIndexBuffer,vk::BufferHelper * srcIndexBuffer,const ConvertLineLoopIndexIndirectParameters & params)1654 angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
1655     ContextVk *contextVk,
1656     vk::BufferHelper *srcIndirectBuffer,
1657     vk::BufferHelper *dstIndirectBuffer,
1658     vk::BufferHelper *dstIndexBuffer,
1659     vk::BufferHelper *srcIndexBuffer,
1660     const ConvertLineLoopIndexIndirectParameters &params)
1661 {
1662     ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk));
1663 
1664     vk::CommandBufferAccess access;
1665     access.onBufferComputeShaderRead(srcIndirectBuffer);
1666     access.onBufferComputeShaderRead(srcIndexBuffer);
1667     access.onBufferComputeShaderWrite(dstIndirectBuffer);
1668     access.onBufferComputeShaderWrite(dstIndexBuffer);
1669 
1670     vk::CommandBuffer *commandBuffer;
1671     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1672 
1673     VkDescriptorSet descriptorSet;
1674     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1675     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
1676                                     &descriptorPoolBinding, &descriptorSet));
1677 
1678     std::array<VkDescriptorBufferInfo, 4> buffers = {{
1679         {dstIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1680         {srcIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1681         {srcIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1682         {dstIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1683     }};
1684 
1685     VkWriteDescriptorSet writeInfo = {};
1686     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1687     writeInfo.dstSet               = descriptorSet;
1688     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
1689     writeInfo.descriptorCount      = 4;
1690     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1691     writeInfo.pBufferInfo          = buffers.data();
1692 
1693     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1694 
1695     ConvertIndexIndirectLineLoopShaderParams shaderParams = {
1696         params.indirectBufferOffset >> 2, params.dstIndirectBufferOffset >> 2,
1697         params.srcIndexBufferOffset, params.dstIndexBufferOffset >> 2,
1698         contextVk->getState().isPrimitiveRestartEnabled()};
1699 
1700     uint32_t flags = GetConvertIndexIndirectLineLoopFlag(params.indicesBitsWidth);
1701 
1702     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1703     ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndexIndirectLineLoop_comp(contextVk, flags,
1704                                                                                  &shader));
1705 
1706     ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader, nullptr,
1707                            &mConvertIndexIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
1708                            &shaderParams, sizeof(ConvertIndexIndirectLineLoopShaderParams),
1709                            commandBuffer));
1710 
1711     commandBuffer->dispatch(1, 1, 1);
1712 
1713     descriptorPoolBinding.reset();
1714 
1715     return angle::Result::Continue;
1716 }
1717 
convertLineLoopArrayIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * destIndirectBuffer,vk::BufferHelper * destIndexBuffer,const ConvertLineLoopArrayIndirectParameters & params)1718 angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer(
1719     ContextVk *contextVk,
1720     vk::BufferHelper *srcIndirectBuffer,
1721     vk::BufferHelper *destIndirectBuffer,
1722     vk::BufferHelper *destIndexBuffer,
1723     const ConvertLineLoopArrayIndirectParameters &params)
1724 {
1725     ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk));
1726 
1727     vk::CommandBufferAccess access;
1728     access.onBufferComputeShaderRead(srcIndirectBuffer);
1729     access.onBufferComputeShaderWrite(destIndirectBuffer);
1730     access.onBufferComputeShaderWrite(destIndexBuffer);
1731 
1732     vk::CommandBuffer *commandBuffer;
1733     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1734 
1735     VkDescriptorSet descriptorSet;
1736     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1737     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndirectLineLoopBuffer,
1738                                     &descriptorPoolBinding, &descriptorSet));
1739 
1740     std::array<VkDescriptorBufferInfo, 3> buffers = {{
1741         {srcIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1742         {destIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1743         {destIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1744     }};
1745 
1746     VkWriteDescriptorSet writeInfo = {};
1747     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1748     writeInfo.dstSet               = descriptorSet;
1749     writeInfo.dstBinding           = kConvertIndexDestinationBinding;
1750     writeInfo.descriptorCount      = 3;
1751     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1752     writeInfo.pBufferInfo          = buffers.data();
1753 
1754     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1755 
1756     ConvertIndirectLineLoopShaderParams shaderParams = {params.indirectBufferOffset >> 2,
1757                                                         params.dstIndirectBufferOffset >> 2,
1758                                                         params.dstIndexBufferOffset >> 2};
1759 
1760     uint32_t flags = 0;
1761 
1762     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1763     ANGLE_TRY(
1764         contextVk->getShaderLibrary().getConvertIndirectLineLoop_comp(contextVk, flags, &shader));
1765 
1766     ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndirectLineLoopBuffer, shader, nullptr,
1767                            &mConvertIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
1768                            &shaderParams, sizeof(ConvertIndirectLineLoopShaderParams),
1769                            commandBuffer));
1770 
1771     commandBuffer->dispatch(1, 1, 1);
1772 
1773     descriptorPoolBinding.reset();
1774 
1775     return angle::Result::Continue;
1776 }
1777 
convertVertexBuffer(ContextVk * contextVk,vk::BufferHelper * dest,vk::BufferHelper * src,const ConvertVertexParameters & params)1778 angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk,
1779                                            vk::BufferHelper *dest,
1780                                            vk::BufferHelper *src,
1781                                            const ConvertVertexParameters &params)
1782 {
1783     vk::CommandBufferAccess access;
1784     access.onBufferComputeShaderRead(src);
1785     access.onBufferComputeShaderWrite(dest);
1786 
1787     vk::CommandBuffer *commandBuffer;
1788     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
1789 
1790     ConvertVertexShaderParams shaderParams;
1791     shaderParams.Ns = params.srcFormat->channelCount;
1792     shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount;
1793     shaderParams.Ss = static_cast<uint32_t>(params.srcStride);
1794     shaderParams.Nd = params.destFormat->channelCount;
1795     shaderParams.Bd = params.destFormat->pixelBytes / params.destFormat->channelCount;
1796     shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
1797     // The component size is expected to either be 1, 2 or 4 bytes.
1798     ASSERT(4 % shaderParams.Bs == 0);
1799     ASSERT(4 % shaderParams.Bd == 0);
1800     shaderParams.Es = 4 / shaderParams.Bs;
1801     shaderParams.Ed = 4 / shaderParams.Bd;
1802     // Total number of output components is simply the number of vertices by number of components in
1803     // each.
1804     shaderParams.componentCount = static_cast<uint32_t>(params.vertexCount * shaderParams.Nd);
1805     // Total number of 4-byte outputs is the number of components divided by how many components can
1806     // fit in a 4-byte value.  Note that this value is also the invocation size of the shader.
1807     shaderParams.outputCount = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
1808     shaderParams.srcOffset   = static_cast<uint32_t>(params.srcOffset);
1809     shaderParams.destOffset  = static_cast<uint32_t>(params.destOffset);
1810 
1811     bool isSrcA2BGR10 =
1812         params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt2101010 ||
1813         params.srcFormat->vertexAttribType == gl::VertexAttribType::Int2101010;
1814     bool isSrcRGB10A2 =
1815         params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt1010102 ||
1816         params.srcFormat->vertexAttribType == gl::VertexAttribType::Int1010102;
1817 
1818     shaderParams.isSrcHDR     = isSrcA2BGR10 || isSrcRGB10A2;
1819     shaderParams.isSrcA2BGR10 = isSrcA2BGR10;
1820 
1821     uint32_t flags = GetConvertVertexFlags(params);
1822 
1823     // See GLES3.0 section 2.9.1 Transferring Array Elements
1824     const uint32_t srcValueBits = shaderParams.isSrcHDR ? 2 : shaderParams.Bs * 8;
1825     const uint32_t srcValueMask =
1826         srcValueBits == 32 ? 0xFFFFFFFFu : angle::BitMask<uint32_t>(srcValueBits);
1827     switch (flags)
1828     {
1829         case ConvertVertex_comp::kSintToSint:
1830         case ConvertVertex_comp::kSintToFloat:
1831         case ConvertVertex_comp::kUintToFloat:
1832             // For integers, alpha should take a value of 1.
1833             shaderParams.srcEmulatedAlpha = 1;
1834             break;
1835 
1836         case ConvertVertex_comp::kUintToUint:
1837             // For integers, alpha should take a value of 1.  However, uint->uint is also used to
1838             // add channels to RGB snorm, unorm and half formats.
1839             if (params.destFormat->isSnorm())
1840             {
1841                 // See case ConvertVertex_comp::kSnormToFloat below.
1842                 shaderParams.srcEmulatedAlpha = srcValueMask >> 1;
1843             }
1844             else if (params.destFormat->isUnorm())
1845             {
1846                 // See case ConvertVertex_comp::kUnormToFloat below.
1847                 shaderParams.srcEmulatedAlpha = srcValueMask;
1848             }
1849             else if (params.destFormat->isVertexTypeHalfFloat())
1850             {
1851                 shaderParams.srcEmulatedAlpha = gl::Float16One;
1852             }
1853             else
1854             {
1855                 shaderParams.srcEmulatedAlpha = 1;
1856             }
1857             break;
1858 
1859         case ConvertVertex_comp::kSnormToFloat:
1860             // The largest signed number with as many bits as the alpha channel of the source is
1861             // 0b011...1 which is srcValueMask >> 1
1862             shaderParams.srcEmulatedAlpha = srcValueMask >> 1;
1863             break;
1864 
1865         case ConvertVertex_comp::kUnormToFloat:
1866             // The largest unsigned number with as many bits as the alpha channel of the source is
1867             // 0b11...1 which is srcValueMask
1868             shaderParams.srcEmulatedAlpha = srcValueMask;
1869             break;
1870 
1871         case ConvertVertex_comp::kFixedToFloat:
1872             // 1.0 in fixed point is 0x10000
1873             shaderParams.srcEmulatedAlpha = 0x10000;
1874             break;
1875 
1876         case ConvertVertex_comp::kFloatToFloat:
1877             ASSERT(ValidateFloatOneAsUint());
1878             shaderParams.srcEmulatedAlpha = gl::Float32One;
1879             break;
1880 
1881         default:
1882             UNREACHABLE();
1883     }
1884 
1885     return convertVertexBufferImpl(contextVk, dest, src, flags, commandBuffer, shaderParams);
1886 }
1887 
convertVertexBufferImpl(ContextVk * contextVk,vk::BufferHelper * dest,vk::BufferHelper * src,uint32_t flags,vk::CommandBuffer * commandBuffer,const ConvertVertexShaderParams & shaderParams)1888 angle::Result UtilsVk::convertVertexBufferImpl(ContextVk *contextVk,
1889                                                vk::BufferHelper *dest,
1890                                                vk::BufferHelper *src,
1891                                                uint32_t flags,
1892                                                vk::CommandBuffer *commandBuffer,
1893                                                const ConvertVertexShaderParams &shaderParams)
1894 {
1895     ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk));
1896 
1897     VkDescriptorSet descriptorSet;
1898     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1899     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertVertexBuffer,
1900                                     &descriptorPoolBinding, &descriptorSet));
1901 
1902     VkWriteDescriptorSet writeInfo    = {};
1903     VkDescriptorBufferInfo buffers[2] = {
1904         {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1905         {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1906     };
1907     static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
1908                   "Update write info");
1909 
1910     writeInfo.sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1911     writeInfo.dstSet          = descriptorSet;
1912     writeInfo.dstBinding      = kConvertVertexDestinationBinding;
1913     writeInfo.descriptorCount = 2;
1914     writeInfo.descriptorType  = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1915     writeInfo.pBufferInfo     = buffers;
1916 
1917     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1918 
1919     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1920     ANGLE_TRY(contextVk->getShaderLibrary().getConvertVertex_comp(contextVk, flags, &shader));
1921 
1922     ANGLE_TRY(setupProgram(contextVk, Function::ConvertVertexBuffer, shader, nullptr,
1923                            &mConvertVertexPrograms[flags], nullptr, descriptorSet, &shaderParams,
1924                            sizeof(shaderParams), commandBuffer));
1925 
1926     commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
1927 
1928     descriptorPoolBinding.reset();
1929 
1930     return angle::Result::Continue;
1931 }
1932 
startRenderPass(ContextVk * contextVk,vk::ImageHelper * image,const vk::ImageView * imageView,const vk::RenderPassDesc & renderPassDesc,const gl::Rectangle & renderArea,vk::CommandBuffer ** commandBufferOut)1933 angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
1934                                        vk::ImageHelper *image,
1935                                        const vk::ImageView *imageView,
1936                                        const vk::RenderPassDesc &renderPassDesc,
1937                                        const gl::Rectangle &renderArea,
1938                                        vk::CommandBuffer **commandBufferOut)
1939 {
1940     vk::RenderPass *compatibleRenderPass = nullptr;
1941     ANGLE_TRY(contextVk->getCompatibleRenderPass(renderPassDesc, &compatibleRenderPass));
1942 
1943     VkFramebufferCreateInfo framebufferInfo = {};
1944 
1945     // Minimize the framebuffer coverage to only cover up to the render area.
1946     framebufferInfo.sType           = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
1947     framebufferInfo.flags           = 0;
1948     framebufferInfo.renderPass      = compatibleRenderPass->getHandle();
1949     framebufferInfo.attachmentCount = 1;
1950     framebufferInfo.pAttachments    = imageView->ptr();
1951     framebufferInfo.width           = renderArea.x + renderArea.width;
1952     framebufferInfo.height          = renderArea.y + renderArea.height;
1953     framebufferInfo.layers          = 1;
1954 
1955     vk::Framebuffer framebuffer;
1956     ANGLE_VK_TRY(contextVk, framebuffer.init(contextVk->getDevice(), framebufferInfo));
1957 
1958     vk::AttachmentOpsArray renderPassAttachmentOps;
1959     vk::PackedClearValuesArray clearValues;
1960     clearValues.store(vk::kAttachmentIndexZero, VK_IMAGE_ASPECT_COLOR_BIT, {});
1961 
1962     renderPassAttachmentOps.initWithLoadStore(vk::kAttachmentIndexZero,
1963                                               vk::ImageLayout::ColorAttachment,
1964                                               vk::ImageLayout::ColorAttachment);
1965 
1966     ANGLE_TRY(contextVk->beginNewRenderPass(
1967         framebuffer, renderArea, renderPassDesc, renderPassAttachmentOps,
1968         vk::PackedAttachmentCount(1), vk::kAttachmentIndexInvalid, clearValues, commandBufferOut));
1969 
1970     contextVk->addGarbage(&framebuffer);
1971 
1972     return angle::Result::Continue;
1973 }
1974 
clearFramebuffer(ContextVk * contextVk,FramebufferVk * framebuffer,const ClearFramebufferParameters & params)1975 angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
1976                                         FramebufferVk *framebuffer,
1977                                         const ClearFramebufferParameters &params)
1978 {
1979     ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
1980 
1981     const gl::Rectangle &scissoredRenderArea = params.clearArea;
1982     vk::Framebuffer *currentFramebuffer      = nullptr;
1983     vk::CommandBuffer *commandBuffer;
1984 
1985     // Start a new render pass if not already started
1986     ANGLE_TRY(framebuffer->getFramebuffer(contextVk, &currentFramebuffer, nullptr));
1987     if (contextVk->hasStartedRenderPassWithFramebuffer(currentFramebuffer))
1988     {
1989         commandBuffer = &contextVk->getStartedRenderPassCommands().getCommandBuffer();
1990     }
1991     else
1992     {
1993         ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer, nullptr));
1994     }
1995 
1996     if (params.clearStencil || params.clearDepth)
1997     {
1998         vk::CommandBufferHelper *renderpassCommands;
1999         renderpassCommands = &contextVk->getStartedRenderPassCommands();
2000 
2001         // Because clear is not affected by depth/stencil test, we have to explicitly mark
2002         // depth/stencil write here.
2003         if (params.clearDepth)
2004         {
2005             renderpassCommands->onDepthAccess(vk::ResourceAccess::Write);
2006         }
2007         if (params.clearStencil)
2008         {
2009             renderpassCommands->onStencilAccess(vk::ResourceAccess::Write);
2010         }
2011 
2012         // We may have changed depth stencil access mode, so update read only depth stencil mode
2013         // here.
2014         framebuffer->updateRenderPassReadOnlyDepthMode(contextVk, renderpassCommands);
2015     }
2016 
2017     ImageClearShaderParams shaderParams;
2018     shaderParams.clearValue = params.colorClearValue;
2019     shaderParams.clearDepth = params.depthStencilClearValue.depth;
2020 
2021     vk::GraphicsPipelineDesc pipelineDesc;
2022     pipelineDesc.initDefaults(contextVk);
2023     pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
2024     pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
2025     pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags);
2026     pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
2027     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
2028     // Note: depth test is disabled by default so this should be unnecessary, but works around an
2029     // Intel bug on windows.  http://anglebug.com/3348
2030     pipelineDesc.setDepthWriteEnabled(false);
2031     // Clears can be done on a currently open render pass, so make sure the correct subpass index is
2032     // used.
2033     pipelineDesc.setSubpass(contextVk->getCurrentSubpassIndex());
2034 
2035     // Clear depth by enabling depth clamping and setting the viewport depth range to the clear
2036     // value if possible.  Otherwise use the shader to export depth.
2037     const bool supportsDepthClamp =
2038         contextVk->getRenderer()->getPhysicalDeviceFeatures().depthClamp == VK_TRUE;
2039     if (params.clearDepth)
2040     {
2041         pipelineDesc.setDepthTestEnabled(true);
2042         pipelineDesc.setDepthWriteEnabled(true);
2043         pipelineDesc.setDepthFunc(VK_COMPARE_OP_ALWAYS);
2044         if (supportsDepthClamp)
2045         {
2046             // Note: this path requires the depthClamp Vulkan feature.
2047             pipelineDesc.setDepthClampEnabled(true);
2048         }
2049     }
2050 
2051     // Clear stencil by enabling stencil write with the right mask.
2052     if (params.clearStencil)
2053     {
2054         const uint8_t compareMask = 0xFF;
2055         const uint8_t clearStencilValue =
2056             static_cast<uint8_t>(params.depthStencilClearValue.stencil);
2057 
2058         pipelineDesc.setStencilTestEnabled(true);
2059         pipelineDesc.setStencilFrontFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
2060         pipelineDesc.setStencilBackFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
2061         pipelineDesc.setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
2062                                         VK_STENCIL_OP_REPLACE);
2063         pipelineDesc.setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
2064                                        VK_STENCIL_OP_REPLACE);
2065         pipelineDesc.setStencilFrontWriteMask(params.stencilMask);
2066         pipelineDesc.setStencilBackWriteMask(params.stencilMask);
2067     }
2068 
2069     VkViewport viewport;
2070     gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
2071     bool invertViewport              = contextVk->isViewportFlipEnabledForDrawFBO();
2072     bool clipSpaceOriginUpperLeft =
2073         contextVk->getState().getClipSpaceOrigin() == gl::ClipSpaceOrigin::UpperLeft;
2074     // Set depth range to clear value.  If clearing depth, the vertex shader depth output is clamped
2075     // to this value, thus clearing the depth buffer to the desired clear value.
2076     const float clearDepthValue = params.depthStencilClearValue.depth;
2077     gl_vk::GetViewport(completeRenderArea, clearDepthValue, clearDepthValue, invertViewport,
2078                        clipSpaceOriginUpperLeft, completeRenderArea.height, &viewport);
2079     commandBuffer->setViewport(0, 1, &viewport);
2080 
2081     const VkRect2D scissor = gl_vk::GetRect(params.clearArea);
2082     commandBuffer->setScissor(0, 1, &scissor);
2083 
2084     contextVk->invalidateViewportAndScissor();
2085 
2086     vk::ShaderLibrary &shaderLibrary                    = contextVk->getShaderLibrary();
2087     vk::RefCounted<vk::ShaderAndSerial> *vertexShader   = nullptr;
2088     vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
2089     vk::ShaderProgramHelper *imageClearProgram          = &mImageClearProgramVSOnly;
2090 
2091     ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
2092     if (params.clearColor)
2093     {
2094         uint32_t flags = GetImageClearFlags(*params.colorFormat, params.colorAttachmentIndexGL,
2095                                             params.clearDepth && !supportsDepthClamp);
2096         ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
2097         imageClearProgram = &mImageClearProgram[flags];
2098     }
2099 
2100     ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
2101                            imageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
2102                            sizeof(shaderParams), commandBuffer));
2103 
2104     // Make sure transform feedback is paused
2105     bool isTransformFeedbackActiveUnpaused =
2106         contextVk->getStartedRenderPassCommands().isTransformFeedbackActiveUnpaused();
2107     contextVk->pauseTransformFeedbackIfActiveUnpaused();
2108 
2109     // Make sure this draw call doesn't count towards occlusion query results.
2110     contextVk->pauseRenderPassQueriesIfActive();
2111 
2112     commandBuffer->draw(3, 0);
2113     ANGLE_TRY(contextVk->resumeRenderPassQueriesIfActive());
2114 
2115     // If transform feedback was active, we can't pause and resume it in the same render pass
2116     // because we can't insert a memory barrier for the counter buffers.  In that case, break the
2117     // render pass.
2118     if (isTransformFeedbackActiveUnpaused)
2119     {
2120         ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
2121     }
2122 
2123     return angle::Result::Continue;
2124 }
2125 
colorBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcView,const BlitResolveParameters & params)2126 angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk,
2127                                         FramebufferVk *framebuffer,
2128                                         vk::ImageHelper *src,
2129                                         const vk::ImageView *srcView,
2130                                         const BlitResolveParameters &params)
2131 {
2132     return blitResolveImpl(contextVk, framebuffer, src, srcView, nullptr, nullptr, params);
2133 }
2134 
depthStencilBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)2135 angle::Result UtilsVk::depthStencilBlitResolve(ContextVk *contextVk,
2136                                                FramebufferVk *framebuffer,
2137                                                vk::ImageHelper *src,
2138                                                const vk::ImageView *srcDepthView,
2139                                                const vk::ImageView *srcStencilView,
2140                                                const BlitResolveParameters &params)
2141 {
2142     return blitResolveImpl(contextVk, framebuffer, src, nullptr, srcDepthView, srcStencilView,
2143                            params);
2144 }
2145 
blitResolveImpl(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcColorView,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)2146 angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
2147                                        FramebufferVk *framebuffer,
2148                                        vk::ImageHelper *src,
2149                                        const vk::ImageView *srcColorView,
2150                                        const vk::ImageView *srcDepthView,
2151                                        const vk::ImageView *srcStencilView,
2152                                        const BlitResolveParameters &params)
2153 {
2154     // Possible ways to resolve color are:
2155     //
2156     // - vkCmdResolveImage: This is by far the easiest method, but lacks the ability to flip
2157     //   images during resolve.
2158     // - Manual resolve: A shader can read all samples from input, average them and output.
2159     // - Using subpass resolve attachment: A shader can transform the sample colors from source to
2160     //   destination coordinates and the subpass resolve would finish the job.
2161     //
2162     // The first method is unable to handle flipping, so it's not generally applicable.  The last
2163     // method would have been great were we able to modify the last render pass that rendered into
2164     // source, but still wouldn't be able to handle flipping.  The second method is implemented in
2165     // this function for complete control.
2166 
2167     // Possible ways to resolve depth/stencil are:
2168     //
2169     // - Manual resolve: A shader can read a samples from input and choose that for output.
2170     // - Using subpass resolve attachment through VkSubpassDescriptionDepthStencilResolveKHR: This
2171     //   requires an extension that's not very well supported.
2172     //
2173     // The first method is implemented in this function.
2174 
2175     // Possible ways to blit color, depth or stencil are:
2176     //
2177     // - vkCmdBlitImage: This function works if the source and destination formats have the blit
2178     //   feature.
2179     // - Manual blit: A shader can sample from the source image and write it to the destination.
2180     //
2181     // The first method has a serious shortcoming.  GLES allows blit parameters to exceed the
2182     // source or destination boundaries.  The actual blit is clipped to these limits, but the
2183     // scaling applied is determined solely by the input areas.  Vulkan requires the blit parameters
2184     // to be within the source and destination bounds.  This makes it hard to keep the scaling
2185     // constant.
2186     //
2187     // The second method is implemented in this function, which shares code with the resolve method.
2188 
2189     ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
2190 
2191     bool isResolve = src->getSamples() > 1;
2192 
2193     BlitResolveShaderParams shaderParams;
2194     // Note: adjustments made for pre-rotatation in FramebufferVk::blit() affect these
2195     // Calculate*Offset() functions.
2196     if (isResolve)
2197     {
2198         CalculateResolveOffset(params, shaderParams.offset.resolve);
2199     }
2200     else
2201     {
2202         CalculateBlitOffset(params, shaderParams.offset.blit);
2203     }
2204     shaderParams.stretch[0]      = params.stretch[0];
2205     shaderParams.stretch[1]      = params.stretch[1];
2206     shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
2207     shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
2208     shaderParams.srcLayer        = params.srcLayer;
2209     shaderParams.samples         = src->getSamples();
2210     shaderParams.invSamples      = 1.0f / shaderParams.samples;
2211     shaderParams.outputMask =
2212         static_cast<uint32_t>(framebuffer->getState().getEnabledDrawBuffers().to_ulong());
2213     shaderParams.flipX    = params.flipX;
2214     shaderParams.flipY    = params.flipY;
2215     shaderParams.rotateXY = 0;
2216 
2217     // Potentially make adjustments for pre-rotatation.  Depending on the angle some of the
2218     // shaderParams need to be adjusted.
2219     switch (params.rotation)
2220     {
2221         case SurfaceRotation::Identity:
2222             break;
2223         case SurfaceRotation::Rotated90Degrees:
2224             shaderParams.rotateXY = 1;
2225             break;
2226         case SurfaceRotation::Rotated180Degrees:
2227             if (isResolve)
2228             {
2229                 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0];
2230                 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1];
2231             }
2232             else
2233             {
2234                 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0];
2235                 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1];
2236             }
2237             break;
2238         case SurfaceRotation::Rotated270Degrees:
2239             if (isResolve)
2240             {
2241                 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0];
2242                 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1];
2243             }
2244             else
2245             {
2246                 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0];
2247                 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1];
2248             }
2249             shaderParams.rotateXY = 1;
2250             break;
2251         default:
2252             UNREACHABLE();
2253             break;
2254     }
2255 
2256     bool blitColor   = srcColorView != nullptr;
2257     bool blitDepth   = srcDepthView != nullptr;
2258     bool blitStencil = srcStencilView != nullptr;
2259 
2260     // Either color is blitted/resolved or depth/stencil, but not both.
2261     ASSERT(blitColor != (blitDepth || blitStencil));
2262 
2263     // Linear sampling is only valid with color blitting.
2264     ASSERT((blitColor && !isResolve) || !params.linear);
2265 
2266     uint32_t flags = GetBlitResolveFlags(blitColor, blitDepth, blitStencil, src->getFormat());
2267     flags |= src->getLayerCount() > 1 ? BlitResolve_frag::kSrcIsArray : 0;
2268     flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
2269 
2270     VkDescriptorSet descriptorSet;
2271     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
2272     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BlitResolve, &descriptorPoolBinding,
2273                                     &descriptorSet));
2274 
2275     constexpr VkColorComponentFlags kAllColorComponents =
2276         VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
2277         VK_COLOR_COMPONENT_A_BIT;
2278 
2279     vk::GraphicsPipelineDesc pipelineDesc;
2280     pipelineDesc.initDefaults(contextVk);
2281     if (blitColor)
2282     {
2283         pipelineDesc.setColorWriteMasks(
2284             gl::BlendStateExt::ColorMaskStorage::GetReplicatedValue(
2285                 kAllColorComponents, gl::BlendStateExt::ColorMaskStorage::GetMask(
2286                                          framebuffer->getRenderPassDesc().colorAttachmentRange())),
2287             framebuffer->getEmulatedAlphaAttachmentMask(), ~gl::DrawBufferMask());
2288     }
2289     else
2290     {
2291         pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
2292     }
2293     pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
2294     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
2295     pipelineDesc.setDepthTestEnabled(blitDepth);
2296     pipelineDesc.setDepthWriteEnabled(blitDepth);
2297     pipelineDesc.setDepthFunc(VK_COMPARE_OP_ALWAYS);
2298 
2299     if (blitStencil)
2300     {
2301         SetStencilForShaderExport(contextVk, &pipelineDesc);
2302     }
2303 
2304     vk::CommandBuffer *commandBuffer;
2305     ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer, nullptr));
2306 
2307     VkViewport viewport;
2308     gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
2309     gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, false, completeRenderArea.height,
2310                        &viewport);
2311     commandBuffer->setViewport(0, 1, &viewport);
2312 
2313     VkRect2D scissor = gl_vk::GetRect(params.blitArea);
2314     commandBuffer->setScissor(0, 1, &scissor);
2315 
2316     contextVk->invalidateViewportAndScissor();
2317 
2318     contextVk->onImageRenderPassRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
2319                                      src);
2320 
2321     vk::CommandBufferHelper *renderPassCommands = &contextVk->getStartedRenderPassCommands();
2322     if (blitDepth)
2323     {
2324         // Explicitly mark a depth write because we are modifying the depth buffer.
2325         renderPassCommands->onDepthAccess(vk::ResourceAccess::Write);
2326     }
2327     if (blitStencil)
2328     {
2329         // Explicitly mark a stencil write because we are modifying the stencil buffer.
2330         renderPassCommands->onStencilAccess(vk::ResourceAccess::Write);
2331     }
2332     if (blitDepth || blitStencil)
2333     {
2334         // Because we may have changed the depth stencil access mode, update read only depth mode
2335         // now.
2336         framebuffer->updateRenderPassReadOnlyDepthMode(contextVk, renderPassCommands);
2337     }
2338 
2339     VkDescriptorImageInfo imageInfos[2] = {};
2340 
2341     if (blitColor)
2342     {
2343         imageInfos[0].imageView   = srcColorView->getHandle();
2344         imageInfos[0].imageLayout = src->getCurrentLayout();
2345     }
2346     if (blitDepth)
2347     {
2348         imageInfos[0].imageView   = srcDepthView->getHandle();
2349         imageInfos[0].imageLayout = src->getCurrentLayout();
2350     }
2351     if (blitStencil)
2352     {
2353         imageInfos[1].imageView   = srcStencilView->getHandle();
2354         imageInfos[1].imageLayout = src->getCurrentLayout();
2355     }
2356 
2357     VkDescriptorImageInfo samplerInfo = {};
2358     samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
2359 
2360     VkWriteDescriptorSet writeInfos[3] = {};
2361     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2362     writeInfos[0].dstSet               = descriptorSet;
2363     writeInfos[0].dstBinding           = kBlitResolveColorOrDepthBinding;
2364     writeInfos[0].descriptorCount      = 1;
2365     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2366     writeInfos[0].pImageInfo           = &imageInfos[0];
2367 
2368     writeInfos[1]            = writeInfos[0];
2369     writeInfos[1].dstBinding = kBlitResolveStencilBinding;
2370     writeInfos[1].pImageInfo = &imageInfos[1];
2371 
2372     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2373     writeInfos[2].dstSet          = descriptorSet;
2374     writeInfos[2].dstBinding      = kBlitResolveSamplerBinding;
2375     writeInfos[2].descriptorCount = 1;
2376     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
2377     writeInfos[2].pImageInfo      = &samplerInfo;
2378 
2379     // If resolving color, there's one write info; index 0
2380     // If resolving depth, write info index 0 must be written
2381     // If resolving stencil, write info index 1 must also be written
2382     //
2383     // Note again that resolving color and depth/stencil are mutually exclusive here.
2384     uint32_t writeInfoOffset = blitDepth || blitColor ? 0 : 1;
2385     uint32_t writeInfoCount  = blitColor + blitDepth + blitStencil;
2386 
2387     vkUpdateDescriptorSets(contextVk->getDevice(), writeInfoCount, writeInfos + writeInfoOffset, 0,
2388                            nullptr);
2389     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfos[2], 0, nullptr);
2390 
2391     vk::ShaderLibrary &shaderLibrary                    = contextVk->getShaderLibrary();
2392     vk::RefCounted<vk::ShaderAndSerial> *vertexShader   = nullptr;
2393     vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
2394     ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
2395     ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
2396 
2397     ANGLE_TRY(setupProgram(contextVk, Function::BlitResolve, fragmentShader, vertexShader,
2398                            &mBlitResolvePrograms[flags], &pipelineDesc, descriptorSet,
2399                            &shaderParams, sizeof(shaderParams), commandBuffer));
2400 
2401     // Note: this utility starts the render pass directly, thus bypassing
2402     // ContextVk::startRenderPass. As such, occlusion queries are not enabled.
2403     commandBuffer->draw(3, 0);
2404 
2405     descriptorPoolBinding.reset();
2406 
2407     return angle::Result::Continue;
2408 }
2409 
stencilBlitResolveNoShaderExport(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)2410 angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
2411                                                         FramebufferVk *framebuffer,
2412                                                         vk::ImageHelper *src,
2413                                                         const vk::ImageView *srcStencilView,
2414                                                         const BlitResolveParameters &params)
2415 {
2416     // When VK_EXT_shader_stencil_export is not available, stencil is blitted/resolved into a
2417     // temporary buffer which is then copied into the stencil aspect of the image.
2418 
2419     ANGLE_TRY(ensureBlitResolveStencilNoExportResourcesInitialized(contextVk));
2420 
2421     bool isResolve = src->getSamples() > 1;
2422 
2423     VkDescriptorSet descriptorSet;
2424     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
2425     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BlitResolveStencilNoExport,
2426                                     &descriptorPoolBinding, &descriptorSet));
2427 
2428     // Create a temporary buffer to blit/resolve stencil into.
2429     vk::RendererScoped<vk::BufferHelper> blitBuffer(contextVk->getRenderer());
2430 
2431     uint32_t bufferRowLengthInUints = UnsignedCeilDivide(params.blitArea.width, sizeof(uint32_t));
2432     VkDeviceSize bufferSize = bufferRowLengthInUints * sizeof(uint32_t) * params.blitArea.height;
2433 
2434     VkBufferCreateInfo blitBufferInfo = {};
2435     blitBufferInfo.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
2436     blitBufferInfo.flags              = 0;
2437     blitBufferInfo.size               = bufferSize;
2438     blitBufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
2439     blitBufferInfo.sharingMode           = VK_SHARING_MODE_EXCLUSIVE;
2440     blitBufferInfo.queueFamilyIndexCount = 0;
2441     blitBufferInfo.pQueueFamilyIndices   = nullptr;
2442 
2443     ANGLE_TRY(
2444         blitBuffer.get().init(contextVk, blitBufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
2445     blitBuffer.get().retain(&contextVk->getResourceUseList());
2446 
2447     BlitResolveStencilNoExportShaderParams shaderParams;
2448     // Note: adjustments made for pre-rotatation in FramebufferVk::blit() affect these
2449     // Calculate*Offset() functions.
2450     if (isResolve)
2451     {
2452         CalculateResolveOffset(params, shaderParams.offset.resolve);
2453     }
2454     else
2455     {
2456         CalculateBlitOffset(params, shaderParams.offset.blit);
2457     }
2458     shaderParams.stretch[0]      = params.stretch[0];
2459     shaderParams.stretch[1]      = params.stretch[1];
2460     shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
2461     shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
2462     shaderParams.srcLayer        = params.srcLayer;
2463     shaderParams.srcWidth        = params.srcExtents[0];
2464     shaderParams.destPitch       = bufferRowLengthInUints;
2465     shaderParams.blitArea[0]     = params.blitArea.x;
2466     shaderParams.blitArea[1]     = params.blitArea.y;
2467     shaderParams.blitArea[2]     = params.blitArea.width;
2468     shaderParams.blitArea[3]     = params.blitArea.height;
2469     shaderParams.flipX           = params.flipX;
2470     shaderParams.flipY           = params.flipY;
2471     shaderParams.rotateXY        = 0;
2472 
2473     // Potentially make adjustments for pre-rotatation.  Depending on the angle some of the
2474     // shaderParams need to be adjusted.
2475     switch (params.rotation)
2476     {
2477         case SurfaceRotation::Identity:
2478             break;
2479         case SurfaceRotation::Rotated90Degrees:
2480             shaderParams.rotateXY = 1;
2481             break;
2482         case SurfaceRotation::Rotated180Degrees:
2483             if (isResolve)
2484             {
2485                 // Align the offset with minus 1, or the sample position near the edge will be
2486                 // wrong.
2487                 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0] - 1;
2488                 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1];
2489             }
2490             else
2491             {
2492                 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0] - 1;
2493                 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1];
2494             }
2495             break;
2496         case SurfaceRotation::Rotated270Degrees:
2497             if (isResolve)
2498             {
2499                 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0] - 1;
2500                 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1] - 1;
2501             }
2502             else
2503             {
2504                 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0] - 1;
2505                 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1] - 1;
2506             }
2507             shaderParams.rotateXY = 1;
2508             break;
2509         default:
2510             UNREACHABLE();
2511             break;
2512     }
2513 
2514     // Linear sampling is only valid with color blitting.
2515     ASSERT(!params.linear);
2516 
2517     uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0;
2518     flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
2519 
2520     RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
2521     ASSERT(depthStencilRenderTarget != nullptr);
2522     vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImageForWrite();
2523 
2524     // Change layouts prior to computation.
2525     vk::CommandBufferAccess access;
2526     access.onImageComputeShaderRead(src->getAspectFlags(), src);
2527     access.onImageTransferWrite(depthStencilRenderTarget->getLevelIndex(), 1,
2528                                 depthStencilRenderTarget->getLayerIndex(), 1,
2529                                 depthStencilImage->getAspectFlags(), depthStencilImage);
2530 
2531     vk::CommandBuffer *commandBuffer;
2532     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
2533 
2534     // Blit/resolve stencil into the buffer.
2535     VkDescriptorImageInfo imageInfo = {};
2536     imageInfo.imageView             = srcStencilView->getHandle();
2537     imageInfo.imageLayout           = src->getCurrentLayout();
2538 
2539     VkDescriptorBufferInfo bufferInfo = {};
2540     bufferInfo.buffer                 = blitBuffer.get().getBuffer().getHandle();
2541     bufferInfo.offset                 = 0;
2542     bufferInfo.range                  = VK_WHOLE_SIZE;
2543 
2544     VkDescriptorImageInfo samplerInfo = {};
2545     samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
2546 
2547     VkWriteDescriptorSet writeInfos[3] = {};
2548     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2549     writeInfos[0].dstSet               = descriptorSet;
2550     writeInfos[0].dstBinding           = kBlitResolveStencilNoExportDestBinding;
2551     writeInfos[0].descriptorCount      = 1;
2552     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2553     writeInfos[0].pBufferInfo          = &bufferInfo;
2554 
2555     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2556     writeInfos[1].dstSet          = descriptorSet;
2557     writeInfos[1].dstBinding      = kBlitResolveStencilNoExportSrcBinding;
2558     writeInfos[1].descriptorCount = 1;
2559     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2560     writeInfos[1].pImageInfo      = &imageInfo;
2561 
2562     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2563     writeInfos[2].dstSet          = descriptorSet;
2564     writeInfos[2].dstBinding      = kBlitResolveStencilNoExportSamplerBinding;
2565     writeInfos[2].descriptorCount = 1;
2566     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLER;
2567     writeInfos[2].pImageInfo      = &samplerInfo;
2568 
2569     vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
2570 
2571     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
2572     ANGLE_TRY(contextVk->getShaderLibrary().getBlitResolveStencilNoExport_comp(contextVk, flags,
2573                                                                                &shader));
2574 
2575     ANGLE_TRY(setupProgram(contextVk, Function::BlitResolveStencilNoExport, shader, nullptr,
2576                            &mBlitResolveStencilNoExportPrograms[flags], nullptr, descriptorSet,
2577                            &shaderParams, sizeof(shaderParams), commandBuffer));
2578     commandBuffer->dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
2579                             UnsignedCeilDivide(params.blitArea.height, 8), 1);
2580     descriptorPoolBinding.reset();
2581 
2582     // Add a barrier prior to copy.
2583     VkMemoryBarrier memoryBarrier = {};
2584     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2585     memoryBarrier.srcAccessMask   = VK_ACCESS_SHADER_WRITE_BIT;
2586     memoryBarrier.dstAccessMask   = VK_ACCESS_TRANSFER_READ_BIT;
2587 
2588     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
2589                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &memoryBarrier);
2590 
2591     // Copy the resulting buffer into dest.
2592     VkBufferImageCopy region           = {};
2593     region.bufferOffset                = 0;
2594     region.bufferRowLength             = bufferRowLengthInUints * sizeof(uint32_t);
2595     region.bufferImageHeight           = params.blitArea.height;
2596     region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
2597     region.imageSubresource.mipLevel =
2598         depthStencilImage->toVkLevel(depthStencilRenderTarget->getLevelIndex()).get();
2599     region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex();
2600     region.imageSubresource.layerCount     = 1;
2601     region.imageOffset.x                   = params.blitArea.x;
2602     region.imageOffset.y                   = params.blitArea.y;
2603     region.imageOffset.z                   = 0;
2604     region.imageExtent.width               = params.blitArea.width;
2605     region.imageExtent.height              = params.blitArea.height;
2606     region.imageExtent.depth               = 1;
2607 
2608     commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(),
2609                                      depthStencilImage->getImage(),
2610                                      depthStencilImage->getCurrentLayout(), 1, &region);
2611 
2612     return angle::Result::Continue;
2613 }
2614 
copyImage(ContextVk * contextVk,vk::ImageHelper * dest,const vk::ImageView * destView,vk::ImageHelper * src,const vk::ImageView * srcView,const CopyImageParameters & params)2615 angle::Result UtilsVk::copyImage(ContextVk *contextVk,
2616                                  vk::ImageHelper *dest,
2617                                  const vk::ImageView *destView,
2618                                  vk::ImageHelper *src,
2619                                  const vk::ImageView *srcView,
2620                                  const CopyImageParameters &params)
2621 {
2622     ANGLE_TRY(ensureImageCopyResourcesInitialized(contextVk));
2623 
2624     const vk::Format &srcFormat            = src->getFormat();
2625     const vk::Format &dstFormat            = dest->getFormat();
2626     const angle::Format &dstIntendedFormat = dstFormat.intendedFormat();
2627 
2628     ImageCopyShaderParams shaderParams;
2629     shaderParams.flipX            = 0;
2630     shaderParams.flipY            = params.srcFlipY || params.destFlipY;
2631     shaderParams.premultiplyAlpha = params.srcPremultiplyAlpha;
2632     shaderParams.unmultiplyAlpha  = params.srcUnmultiplyAlpha;
2633     shaderParams.destHasLuminance = dstIntendedFormat.luminanceBits > 0;
2634     shaderParams.destIsAlpha      = dstIntendedFormat.isLUMA() && dstIntendedFormat.alphaBits > 0;
2635     shaderParams.destDefaultChannelsMask = GetFormatDefaultChannelMask(dstFormat);
2636     shaderParams.srcMip                  = params.srcMip;
2637     shaderParams.srcLayer                = params.srcLayer;
2638     shaderParams.srcOffset[0]            = params.srcOffset[0];
2639     shaderParams.srcOffset[1]            = params.srcOffset[1];
2640     shaderParams.destOffset[0]           = params.destOffset[0];
2641     shaderParams.destOffset[1]           = params.destOffset[1];
2642     shaderParams.rotateXY                = 0;
2643 
2644     shaderParams.srcIsSRGB =
2645         gl::GetSizedInternalFormatInfo(srcFormat.intendedGLFormat).colorEncoding == GL_SRGB;
2646     shaderParams.destIsSRGB =
2647         gl::GetSizedInternalFormatInfo(dstFormat.intendedGLFormat).colorEncoding == GL_SRGB;
2648 
2649     // If both src and dest are sRGB, and there is no alpha multiplication/division necessary, then
2650     // the shader can work with sRGB data and pretend they are linear.
2651     if (shaderParams.srcIsSRGB && shaderParams.destIsSRGB && !shaderParams.premultiplyAlpha &&
2652         !shaderParams.unmultiplyAlpha)
2653     {
2654         shaderParams.srcIsSRGB  = false;
2655         shaderParams.destIsSRGB = false;
2656     }
2657 
2658     ASSERT(!(params.srcFlipY && params.destFlipY));
2659     if (params.srcFlipY)
2660     {
2661         // If viewport is flipped, the shader expects srcOffset[1] to have the
2662         // last row's index instead of the first's.
2663         shaderParams.srcOffset[1] = params.srcHeight - params.srcOffset[1] - 1;
2664     }
2665     else if (params.destFlipY)
2666     {
2667         // If image is flipped during copy, the shader uses the same code path as above,
2668         // with srcOffset being set to the last row's index instead of the first's.
2669         shaderParams.srcOffset[1] = params.srcOffset[1] + params.srcExtents[1] - 1;
2670     }
2671 
2672     switch (params.srcRotation)
2673     {
2674         case SurfaceRotation::Identity:
2675             break;
2676         case SurfaceRotation::Rotated90Degrees:
2677             shaderParams.rotateXY = 1;
2678             break;
2679         case SurfaceRotation::Rotated180Degrees:
2680             shaderParams.flipX = true;
2681             ASSERT(shaderParams.flipY);
2682             shaderParams.flipY = false;
2683             shaderParams.srcOffset[0] += params.srcExtents[0];
2684             shaderParams.srcOffset[1] -= params.srcExtents[1];
2685             break;
2686         case SurfaceRotation::Rotated270Degrees:
2687             shaderParams.flipX = true;
2688             ASSERT(!shaderParams.flipY);
2689             shaderParams.flipY = true;
2690             shaderParams.srcOffset[0] += params.srcExtents[0];
2691             shaderParams.srcOffset[1] += params.srcExtents[1];
2692             shaderParams.rotateXY = 1;
2693             break;
2694         default:
2695             UNREACHABLE();
2696             break;
2697     }
2698 
2699     uint32_t flags = GetImageCopyFlags(srcFormat, dstFormat);
2700     if (src->getType() == VK_IMAGE_TYPE_3D)
2701     {
2702         flags |= ImageCopy_frag::kSrcIs3D;
2703     }
2704     else if (src->getLayerCount() > 1)
2705     {
2706         flags |= ImageCopy_frag::kSrcIs2DArray;
2707     }
2708     else
2709     {
2710         flags |= ImageCopy_frag::kSrcIs2D;
2711     }
2712 
2713     VkDescriptorSet descriptorSet;
2714     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
2715     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ImageCopy, &descriptorPoolBinding,
2716                                     &descriptorSet));
2717 
2718     vk::RenderPassDesc renderPassDesc;
2719     renderPassDesc.setSamples(dest->getSamples());
2720     renderPassDesc.packColorAttachment(0, dstFormat.intendedFormatID);
2721 
2722     // Copy from multisampled image is not supported.
2723     ASSERT(src->getSamples() == 1);
2724 
2725     vk::GraphicsPipelineDesc pipelineDesc;
2726     pipelineDesc.initDefaults(contextVk);
2727     pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
2728     pipelineDesc.setRenderPassDesc(renderPassDesc);
2729     pipelineDesc.setRasterizationSamples(dest->getSamples());
2730 
2731     gl::Rectangle renderArea;
2732     renderArea.x      = params.destOffset[0];
2733     renderArea.y      = params.destOffset[1];
2734     renderArea.width  = params.srcExtents[0];
2735     renderArea.height = params.srcExtents[1];
2736     if ((params.srcRotation == SurfaceRotation::Rotated90Degrees) ||
2737         (params.srcRotation == SurfaceRotation::Rotated270Degrees))
2738     {
2739         // The surface is rotated 90/270 degrees.  This changes the aspect ratio of the surface.
2740         std::swap(renderArea.x, renderArea.y);
2741         std::swap(renderArea.width, renderArea.height);
2742     }
2743 
2744     vk::CommandBuffer *commandBuffer;
2745     ANGLE_TRY(
2746         startRenderPass(contextVk, dest, destView, renderPassDesc, renderArea, &commandBuffer));
2747 
2748     VkViewport viewport;
2749     gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dest->getExtents().height, &viewport);
2750     commandBuffer->setViewport(0, 1, &viewport);
2751 
2752     VkRect2D scissor = gl_vk::GetRect(renderArea);
2753     commandBuffer->setScissor(0, 1, &scissor);
2754 
2755     contextVk->invalidateViewportAndScissor();
2756 
2757     // Change source layout inside render pass.
2758     contextVk->onImageRenderPassRead(VK_IMAGE_ASPECT_COLOR_BIT,
2759                                      vk::ImageLayout::FragmentShaderReadOnly, src);
2760     contextVk->onImageRenderPassWrite(params.dstMip, params.dstLayer, 1, VK_IMAGE_ASPECT_COLOR_BIT,
2761                                       vk::ImageLayout::ColorAttachment, dest);
2762 
2763     VkDescriptorImageInfo imageInfo = {};
2764     imageInfo.imageView             = srcView->getHandle();
2765     imageInfo.imageLayout           = src->getCurrentLayout();
2766 
2767     VkWriteDescriptorSet writeInfo = {};
2768     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2769     writeInfo.dstSet               = descriptorSet;
2770     writeInfo.dstBinding           = kImageCopySourceBinding;
2771     writeInfo.descriptorCount      = 1;
2772     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2773     writeInfo.pImageInfo           = &imageInfo;
2774 
2775     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2776 
2777     vk::ShaderLibrary &shaderLibrary                    = contextVk->getShaderLibrary();
2778     vk::RefCounted<vk::ShaderAndSerial> *vertexShader   = nullptr;
2779     vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
2780     ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
2781     ANGLE_TRY(shaderLibrary.getImageCopy_frag(contextVk, flags, &fragmentShader));
2782 
2783     ANGLE_TRY(setupProgram(contextVk, Function::ImageCopy, fragmentShader, vertexShader,
2784                            &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
2785                            sizeof(shaderParams), commandBuffer));
2786 
2787     // Note: this utility creates its own framebuffer, thus bypassing ContextVk::startRenderPass.
2788     // As such, occlusion queries are not enabled.
2789     commandBuffer->draw(3, 0);
2790 
2791     descriptorPoolBinding.reset();
2792 
2793     // Close the render pass for this temporary framebuffer.
2794     ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass());
2795 
2796     return angle::Result::Continue;
2797 }
2798 
copyImageBits(ContextVk * contextVk,vk::ImageHelper * dest,vk::ImageHelper * src,const CopyImageBitsParameters & params)2799 angle::Result UtilsVk::copyImageBits(ContextVk *contextVk,
2800                                      vk::ImageHelper *dest,
2801                                      vk::ImageHelper *src,
2802                                      const CopyImageBitsParameters &params)
2803 {
2804     // This function is used to copy the bit representation of an image to another, and is used to
2805     // support EXT_copy_image when a format is emulated.  Currently, only RGB->RGBA emulation is
2806     // possible, and so this function is tailored to this specific kind of emulation.
2807     //
2808     // The copy can be done with various degrees of efficiency:
2809     //
2810     // - If the UINT reinterpretation format for src supports SAMPLED usage, texels can be read
2811     //   directly from that.  Otherwise vkCmdCopyImageToBuffer can be used and data then read from
2812     //   the buffer.
2813     // - If the UINT reinterpretation format for dest supports STORAGE usage, texels can be written
2814     //   directly to that.  Otherwise conversion can be done to a buffer and then
2815     //   vkCmdCopyBufferToImage used.
2816     //
2817     // This requires four different shaders.  For simplicity, this function unconditionally copies
2818     // src to a temp buffer, transforms to another temp buffer and copies to the dest.  No known
2819     // applications use EXT_copy_image on RGB formats, so no further optimization is currently
2820     // necessary.
2821     //
2822     // The conversion between buffers can be done with ConvertVertex.comp in UintToUint mode, so no
2823     // new shader is necessary.  The srcEmulatedAlpha parameter is used to make sure the destination
2824     // alpha value is correct, if dest is RGBA.
2825 
2826     const vk::Format &srcFormat = src->getFormat();
2827     const vk::Format &dstFormat = dest->getFormat();
2828 
2829     // This path should only be necessary for when RGBA is used as fallback for RGB.  No other
2830     // format which can be used with EXT_copy_image has a fallback.
2831     ASSERT(srcFormat.intendedFormat().blueBits > 0 && srcFormat.intendedFormat().alphaBits == 0);
2832     ASSERT(dstFormat.intendedFormat().blueBits > 0 && dstFormat.intendedFormat().alphaBits == 0);
2833 
2834     const angle::Format &srcImageFormat = srcFormat.actualImageFormat();
2835     const angle::Format &dstImageFormat = dstFormat.actualImageFormat();
2836 
2837     // Create temporary buffers.
2838     vk::RendererScoped<vk::BufferHelper> srcBuffer(contextVk->getRenderer());
2839     vk::RendererScoped<vk::BufferHelper> dstBuffer(contextVk->getRenderer());
2840 
2841     const uint32_t srcPixelBytes = srcImageFormat.pixelBytes;
2842     const uint32_t dstPixelBytes = dstImageFormat.pixelBytes;
2843 
2844     const uint32_t totalPixelCount =
2845         params.copyExtents[0] * params.copyExtents[1] * params.copyExtents[2];
2846     // Note that buffer sizes are rounded up a multiple of uint size, as that the granularity in
2847     // which the compute shader accesses these buffers.
2848     const VkDeviceSize srcBufferSize =
2849         roundUpPow2<uint32_t>(srcPixelBytes * totalPixelCount, sizeof(uint32_t));
2850     const VkDeviceSize dstBufferSize =
2851         roundUpPow2<uint32_t>(dstPixelBytes * totalPixelCount, sizeof(uint32_t));
2852 
2853     VkBufferCreateInfo bufferInfo = {};
2854     bufferInfo.sType              = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
2855     bufferInfo.flags              = 0;
2856     bufferInfo.size               = srcBufferSize;
2857     bufferInfo.usage       = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
2858     bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
2859     bufferInfo.queueFamilyIndexCount = 0;
2860     bufferInfo.pQueueFamilyIndices   = nullptr;
2861 
2862     ANGLE_TRY(srcBuffer.get().init(contextVk, bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
2863 
2864     bufferInfo.size  = dstBufferSize;
2865     bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
2866 
2867     ANGLE_TRY(dstBuffer.get().init(contextVk, bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
2868 
2869     srcBuffer.get().retain(&contextVk->getResourceUseList());
2870     dstBuffer.get().retain(&contextVk->getResourceUseList());
2871 
2872     bool isSrc3D = src->getType() == VK_IMAGE_TYPE_3D;
2873     bool isDst3D = dest->getType() == VK_IMAGE_TYPE_3D;
2874 
2875     // Change layouts prior to computation.
2876     vk::CommandBufferAccess access;
2877     access.onImageTransferRead(src->getAspectFlags(), src);
2878     access.onImageTransferWrite(params.dstLevel, 1, isDst3D ? 0 : params.dstOffset[2],
2879                                 isDst3D ? 1 : params.copyExtents[2], VK_IMAGE_ASPECT_COLOR_BIT,
2880                                 dest);
2881 
2882     vk::CommandBuffer *commandBuffer;
2883     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
2884 
2885     // Copy src into buffer, completely packed.
2886     VkBufferImageCopy srcRegion               = {};
2887     srcRegion.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
2888     srcRegion.imageSubresource.mipLevel       = src->toVkLevel(params.srcLevel).get();
2889     srcRegion.imageSubresource.baseArrayLayer = isSrc3D ? 0 : params.srcOffset[2];
2890     srcRegion.imageSubresource.layerCount     = isSrc3D ? 1 : params.copyExtents[2];
2891     srcRegion.imageOffset.x                   = params.srcOffset[0];
2892     srcRegion.imageOffset.y                   = params.srcOffset[1];
2893     srcRegion.imageOffset.z                   = isSrc3D ? params.srcOffset[2] : 0;
2894     srcRegion.imageExtent.width               = params.copyExtents[0];
2895     srcRegion.imageExtent.height              = params.copyExtents[1];
2896     srcRegion.imageExtent.depth               = isSrc3D ? params.copyExtents[2] : 1;
2897 
2898     commandBuffer->copyImageToBuffer(src->getImage(), src->getCurrentLayout(),
2899                                      srcBuffer.get().getBuffer().getHandle(), 1, &srcRegion);
2900 
2901     // Add a barrier prior to dispatch call.
2902     VkMemoryBarrier memoryBarrier = {};
2903     memoryBarrier.sType           = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
2904     memoryBarrier.srcAccessMask   = VK_ACCESS_TRANSFER_WRITE_BIT;
2905     memoryBarrier.dstAccessMask   = VK_ACCESS_SHADER_READ_BIT;
2906 
2907     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
2908                                  VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, &memoryBarrier);
2909 
2910     // Set up ConvertVertex shader to convert between the formats.  Only the following three cases
2911     // are possible:
2912     //
2913     // - RGB -> RGBA: Ns = 3, Ss = src.pixelBytes,
2914     //                Nd = 4, Sd = dst.pixelBytes, use srcEmulatedAlpha
2915     //
2916     // - RGBA -> RGBA: Ns = 3, Ss = src.pixelBytes,
2917     //                 Nd = 4, Sd = dst.pixelBytes, use srcEmulatedAlpha
2918     //
2919     // - RGBA -> RGB:  Ns = 3, Ss = src.pixelBytes,
2920     //                 Nd = 3, Sd = dst.pixelBytes
2921     //
2922     // The trick here is with RGBA -> RGBA, where Ns is specified as 3, so that the emulated alpha
2923     // from source is not taken (as uint), but rather one is provided such that the destination
2924     // alpha would contain the correct emulated alpha.
2925     //
2926     ConvertVertexShaderParams shaderParams;
2927     shaderParams.Ns = 3;
2928     shaderParams.Bs = srcImageFormat.pixelBytes / srcImageFormat.channelCount;
2929     shaderParams.Ss = srcImageFormat.pixelBytes;
2930     shaderParams.Nd = dstImageFormat.channelCount;
2931     shaderParams.Bd = dstImageFormat.pixelBytes / dstImageFormat.channelCount;
2932     shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
2933     // The component size is expected to either be 1, 2 or 4 bytes.
2934     ASSERT(4 % shaderParams.Bs == 0);
2935     ASSERT(4 % shaderParams.Bd == 0);
2936     shaderParams.Es = 4 / shaderParams.Bs;
2937     shaderParams.Ed = 4 / shaderParams.Bd;
2938     // Total number of output components is simply the number of pixels by number of components in
2939     // each.
2940     shaderParams.componentCount = totalPixelCount * shaderParams.Nd;
2941     // Total number of 4-byte outputs is the number of components divided by how many components can
2942     // fit in a 4-byte value.  Note that this value is also the invocation size of the shader.
2943     shaderParams.outputCount  = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
2944     shaderParams.srcOffset    = 0;
2945     shaderParams.destOffset   = 0;
2946     shaderParams.isSrcHDR     = 0;
2947     shaderParams.isSrcA2BGR10 = 0;
2948 
2949     // Due to the requirements of EXT_copy_image, the channel size of src and dest must be
2950     // identical.  Usage of srcEmulatedAlpha relies on this as it's used to output an alpha value in
2951     // dest through the source.
2952     ASSERT(shaderParams.Bs == shaderParams.Bd);
2953 
2954     // The following RGB formats are allowed in EXT_copy_image:
2955     //
2956     // - RGB32F, RGB32UI, RGB32I
2957     // - RGB16F, RGB16UI, RGB16I
2958     // - RGB8, RGB8_SNORM, SRGB8, RGB8UI, RGB8I
2959     //
2960     // The value of emulated alpha is:
2961     //
2962     // - 1 for all RGB*I and RGB*UI formats
2963     // - bit representation of 1.0f for RGB32F
2964     // - bit representation of half-float 1.0f for RGB16F
2965     // - 0xFF for RGB8 and SRGB8
2966     // - 0x7F for RGB8_SNORM
2967     if (dstImageFormat.isInt())
2968     {
2969         shaderParams.srcEmulatedAlpha = 1;
2970     }
2971     else if (dstImageFormat.isUnorm())
2972     {
2973         ASSERT(shaderParams.Bd == 1);
2974         shaderParams.srcEmulatedAlpha = 0xFF;
2975     }
2976     else if (dstImageFormat.isSnorm())
2977     {
2978         ASSERT(shaderParams.Bd == 1);
2979         shaderParams.srcEmulatedAlpha = 0x7F;
2980     }
2981     else if (shaderParams.Bd == 2)
2982     {
2983         ASSERT(dstImageFormat.isFloat());
2984         shaderParams.srcEmulatedAlpha = gl::Float16One;
2985     }
2986     else if (shaderParams.Bd == 4)
2987     {
2988         ASSERT(dstImageFormat.isFloat());
2989         ASSERT(ValidateFloatOneAsUint());
2990         shaderParams.srcEmulatedAlpha = gl::Float32One;
2991     }
2992     else
2993     {
2994         UNREACHABLE();
2995     }
2996 
2997     // Use UintToUint conversion to preserve the bit pattern during transfer.
2998     const uint32_t flags = ConvertVertex_comp::kUintToUint;
2999 
3000     ANGLE_TRY(convertVertexBufferImpl(contextVk, &dstBuffer.get(), &srcBuffer.get(), flags,
3001                                       commandBuffer, shaderParams));
3002 
3003     // Add a barrier prior to copy.
3004     memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
3005     memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
3006 
3007     commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3008                                  VK_PIPELINE_STAGE_TRANSFER_BIT, &memoryBarrier);
3009 
3010     // Copy buffer into dst.  It's completely packed.
3011     VkBufferImageCopy dstRegion               = {};
3012     dstRegion.imageSubresource.aspectMask     = VK_IMAGE_ASPECT_COLOR_BIT;
3013     dstRegion.imageSubresource.mipLevel       = dest->toVkLevel(params.dstLevel).get();
3014     dstRegion.imageSubresource.baseArrayLayer = isDst3D ? 0 : params.dstOffset[2];
3015     dstRegion.imageSubresource.layerCount     = isDst3D ? 1 : params.copyExtents[2];
3016     dstRegion.imageOffset.x                   = params.dstOffset[0];
3017     dstRegion.imageOffset.y                   = params.dstOffset[1];
3018     dstRegion.imageOffset.z                   = isDst3D ? params.dstOffset[2] : 0;
3019     dstRegion.imageExtent.width               = params.copyExtents[0];
3020     dstRegion.imageExtent.height              = params.copyExtents[1];
3021     dstRegion.imageExtent.depth               = isDst3D ? params.copyExtents[2] : 1;
3022 
3023     commandBuffer->copyBufferToImage(dstBuffer.get().getBuffer().getHandle(), dest->getImage(),
3024                                      dest->getCurrentLayout(), 1, &dstRegion);
3025 
3026     return angle::Result::Continue;
3027 }
3028 
generateMipmap(ContextVk * contextVk,vk::ImageHelper * src,const vk::ImageView * srcLevelZeroView,vk::ImageHelper * dest,const GenerateMipmapDestLevelViews & destLevelViews,const vk::Sampler & sampler,const GenerateMipmapParameters & params)3029 angle::Result UtilsVk::generateMipmap(ContextVk *contextVk,
3030                                       vk::ImageHelper *src,
3031                                       const vk::ImageView *srcLevelZeroView,
3032                                       vk::ImageHelper *dest,
3033                                       const GenerateMipmapDestLevelViews &destLevelViews,
3034                                       const vk::Sampler &sampler,
3035                                       const GenerateMipmapParameters &params)
3036 {
3037     ANGLE_TRY(ensureGenerateMipmapResourcesInitialized(contextVk));
3038 
3039     const gl::Extents &srcExtents = src->getLevelExtents(vk::LevelIndex(params.srcLevel));
3040     ASSERT(srcExtents.depth == 1);
3041 
3042     // Each workgroup processes a 64x64 tile of the image.
3043     constexpr uint32_t kPixelWorkgroupRatio = 64;
3044     const uint32_t workGroupX = UnsignedCeilDivide(srcExtents.width, kPixelWorkgroupRatio);
3045     const uint32_t workGroupY = UnsignedCeilDivide(srcExtents.height, kPixelWorkgroupRatio);
3046 
3047     GenerateMipmapShaderParams shaderParams;
3048     shaderParams.invSrcExtent[0] = 1.0f / srcExtents.width;
3049     shaderParams.invSrcExtent[1] = 1.0f / srcExtents.height;
3050     shaderParams.levelCount      = params.destLevelCount;
3051 
3052     uint32_t flags = GetGenerateMipmapFlags(contextVk, src->getFormat());
3053 
3054     VkDescriptorSet descriptorSet;
3055     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
3056     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::GenerateMipmap, &descriptorPoolBinding,
3057                                     &descriptorSet));
3058 
3059     VkDescriptorImageInfo destImageInfos[kGenerateMipmapMaxLevels] = {};
3060     for (uint32_t level = 0; level < kGenerateMipmapMaxLevels; ++level)
3061     {
3062         destImageInfos[level].imageView   = destLevelViews[level]->getHandle();
3063         destImageInfos[level].imageLayout = dest->getCurrentLayout();
3064     }
3065 
3066     VkDescriptorImageInfo srcImageInfo = {};
3067     srcImageInfo.imageView             = srcLevelZeroView->getHandle();
3068     srcImageInfo.imageLayout           = src->getCurrentLayout();
3069     srcImageInfo.sampler               = sampler.getHandle();
3070 
3071     VkWriteDescriptorSet writeInfos[2] = {};
3072     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3073     writeInfos[0].dstSet               = descriptorSet;
3074     writeInfos[0].dstBinding           = kGenerateMipmapDestinationBinding;
3075     writeInfos[0].descriptorCount      = GetGenerateMipmapMaxLevels(contextVk);
3076     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
3077     writeInfos[0].pImageInfo           = destImageInfos;
3078 
3079     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3080     writeInfos[1].dstSet          = descriptorSet;
3081     writeInfos[1].dstBinding      = kGenerateMipmapSourceBinding;
3082     writeInfos[1].descriptorCount = 1;
3083     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
3084     writeInfos[1].pImageInfo      = &srcImageInfo;
3085 
3086     vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
3087 
3088     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
3089     ANGLE_TRY(contextVk->getShaderLibrary().getGenerateMipmap_comp(contextVk, flags, &shader));
3090 
3091     // Note: onImageRead/onImageWrite is expected to be called by the caller.  This avoids inserting
3092     // barriers between calls for each layer of the image.
3093     vk::CommandBuffer *commandBuffer;
3094     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &commandBuffer));
3095 
3096     ANGLE_TRY(setupProgram(contextVk, Function::GenerateMipmap, shader, nullptr,
3097                            &mGenerateMipmapPrograms[flags], nullptr, descriptorSet, &shaderParams,
3098                            sizeof(shaderParams), commandBuffer));
3099 
3100     commandBuffer->dispatch(workGroupX, workGroupY, 1);
3101     descriptorPoolBinding.reset();
3102 
3103     return angle::Result::Continue;
3104 }
3105 
unresolve(ContextVk * contextVk,const FramebufferVk * framebuffer,const UnresolveParameters & params)3106 angle::Result UtilsVk::unresolve(ContextVk *contextVk,
3107                                  const FramebufferVk *framebuffer,
3108                                  const UnresolveParameters &params)
3109 {
3110     // Get attachment count and pointers to resolve images and views.
3111     gl::DrawBuffersArray<vk::ImageHelper *> colorSrc         = {};
3112     gl::DrawBuffersArray<const vk::ImageView *> colorSrcView = {};
3113 
3114     vk::DeviceScoped<vk::ImageView> depthView(contextVk->getDevice());
3115     vk::DeviceScoped<vk::ImageView> stencilView(contextVk->getDevice());
3116 
3117     const vk::ImageView *depthSrcView   = nullptr;
3118     const vk::ImageView *stencilSrcView = nullptr;
3119 
3120     // The subpass that initializes the multisampled-render-to-texture attachments packs the
3121     // attachments that need to be unresolved, so the attachment indices of this subpass are not the
3122     // same.  See InitializeUnresolveSubpass for details.
3123     vk::PackedAttachmentIndex colorIndexVk(0);
3124     for (size_t colorIndexGL : params.unresolveColorMask)
3125     {
3126         RenderTargetVk *colorRenderTarget = framebuffer->getColorDrawRenderTarget(colorIndexGL);
3127 
3128         ASSERT(colorRenderTarget->hasResolveAttachment());
3129         ASSERT(colorRenderTarget->isImageTransient());
3130 
3131         colorSrc[colorIndexVk.get()] = &colorRenderTarget->getResolveImageForRenderPass();
3132         ANGLE_TRY(
3133             colorRenderTarget->getResolveImageView(contextVk, &colorSrcView[colorIndexVk.get()]));
3134 
3135         ++colorIndexVk;
3136     }
3137 
3138     if (params.unresolveDepth || params.unresolveStencil)
3139     {
3140         RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
3141 
3142         ASSERT(depthStencilRenderTarget->hasResolveAttachment());
3143         ASSERT(depthStencilRenderTarget->isImageTransient());
3144 
3145         vk::ImageHelper *depthStencilSrc =
3146             &depthStencilRenderTarget->getResolveImageForRenderPass();
3147 
3148         // The resolved depth/stencil image is necessarily single-sampled.
3149         ASSERT(depthStencilSrc->getSamples() == 1);
3150         gl::TextureType textureType = vk::Get2DTextureType(depthStencilSrc->getLayerCount(), 1);
3151 
3152         const vk::LevelIndex levelIndex =
3153             depthStencilSrc->toVkLevel(depthStencilRenderTarget->getLevelIndex());
3154         const uint32_t layerIndex = depthStencilRenderTarget->getLayerIndex();
3155 
3156         if (params.unresolveDepth)
3157         {
3158             ANGLE_TRY(depthStencilSrc->initLayerImageView(
3159                 contextVk, textureType, VK_IMAGE_ASPECT_DEPTH_BIT, gl::SwizzleState(),
3160                 &depthView.get(), levelIndex, 1, layerIndex, 1, gl::SrgbWriteControlMode::Default));
3161             depthSrcView = &depthView.get();
3162         }
3163 
3164         if (params.unresolveStencil)
3165         {
3166             ANGLE_TRY(depthStencilSrc->initLayerImageView(
3167                 contextVk, textureType, VK_IMAGE_ASPECT_STENCIL_BIT, gl::SwizzleState(),
3168                 &stencilView.get(), levelIndex, 1, layerIndex, 1,
3169                 gl::SrgbWriteControlMode::Default));
3170             stencilSrcView = &stencilView.get();
3171         }
3172     }
3173 
3174     const uint32_t colorAttachmentCount = colorIndexVk.get();
3175     const uint32_t depthStencilBindingCount =
3176         (params.unresolveDepth ? 1 : 0) + (params.unresolveStencil ? 1 : 0);
3177     const uint32_t totalBindingCount = colorAttachmentCount + depthStencilBindingCount;
3178 
3179     ASSERT(totalBindingCount > 0);
3180     const Function function = static_cast<Function>(
3181         static_cast<uint32_t>(Function::Unresolve1Attachment) + totalBindingCount - 1);
3182 
3183     ANGLE_TRY(ensureUnresolveResourcesInitialized(contextVk, function, totalBindingCount));
3184 
3185     vk::GraphicsPipelineDesc pipelineDesc;
3186     pipelineDesc.initDefaults(contextVk);
3187     pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
3188     pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
3189     pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
3190     pipelineDesc.setDepthTestEnabled(params.unresolveDepth);
3191     pipelineDesc.setDepthWriteEnabled(params.unresolveDepth);
3192     pipelineDesc.setDepthFunc(VK_COMPARE_OP_ALWAYS);
3193 
3194     if (params.unresolveStencil)
3195     {
3196         SetStencilForShaderExport(contextVk, &pipelineDesc);
3197     }
3198 
3199     vk::CommandBuffer *commandBuffer =
3200         &contextVk->getStartedRenderPassCommands().getCommandBuffer();
3201 
3202     VkViewport viewport;
3203     gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
3204     bool invertViewport              = contextVk->isViewportFlipEnabledForDrawFBO();
3205     bool clipSpaceOriginUpperLeft =
3206         contextVk->getState().getClipSpaceOrigin() == gl::ClipSpaceOrigin::UpperLeft;
3207     gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, clipSpaceOriginUpperLeft,
3208                        completeRenderArea.height, &viewport);
3209     commandBuffer->setViewport(0, 1, &viewport);
3210 
3211     VkRect2D scissor = gl_vk::GetRect(completeRenderArea);
3212     commandBuffer->setScissor(0, 1, &scissor);
3213 
3214     contextVk->invalidateViewportAndScissor();
3215 
3216     VkDescriptorSet descriptorSet;
3217     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
3218     ANGLE_TRY(allocateDescriptorSet(contextVk, function, &descriptorPoolBinding, &descriptorSet));
3219 
3220     vk::FramebufferAttachmentArray<VkDescriptorImageInfo> inputImageInfo = {};
3221     for (uint32_t attachmentIndex = 0; attachmentIndex < colorAttachmentCount; ++attachmentIndex)
3222     {
3223         inputImageInfo[attachmentIndex].imageView   = colorSrcView[attachmentIndex]->getHandle();
3224         inputImageInfo[attachmentIndex].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
3225     }
3226 
3227     uint32_t depthStencilBindingIndex = colorAttachmentCount;
3228     if (params.unresolveDepth)
3229     {
3230         inputImageInfo[depthStencilBindingIndex].imageView = depthSrcView->getHandle();
3231         inputImageInfo[depthStencilBindingIndex].imageLayout =
3232             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
3233         ++depthStencilBindingIndex;
3234     }
3235     if (params.unresolveStencil)
3236     {
3237         inputImageInfo[depthStencilBindingIndex].imageView = stencilSrcView->getHandle();
3238         inputImageInfo[depthStencilBindingIndex].imageLayout =
3239             VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
3240     }
3241 
3242     VkWriteDescriptorSet writeInfo = {};
3243     writeInfo.sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3244     writeInfo.dstSet               = descriptorSet;
3245     writeInfo.dstBinding           = 0;
3246     writeInfo.descriptorCount      = totalBindingCount;
3247     writeInfo.descriptorType       = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
3248     writeInfo.pImageInfo           = inputImageInfo.data();
3249 
3250     vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
3251 
3252     gl::DrawBuffersArray<UnresolveColorAttachmentType> colorAttachmentTypes;
3253     uint32_t flags = GetUnresolveFlags(colorAttachmentCount, colorSrc, params.unresolveDepth,
3254                                        params.unresolveStencil, &colorAttachmentTypes);
3255 
3256     vk::ShaderLibrary &shaderLibrary                    = contextVk->getShaderLibrary();
3257     vk::RefCounted<vk::ShaderAndSerial> *vertexShader   = nullptr;
3258     vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = &mUnresolveFragShaders[flags];
3259     ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
3260     ANGLE_TRY(GetUnresolveFrag(contextVk, colorAttachmentCount, colorAttachmentTypes,
3261                                params.unresolveDepth, params.unresolveStencil, fragmentShader));
3262 
3263     ANGLE_TRY(setupProgram(contextVk, function, fragmentShader, vertexShader,
3264                            &mUnresolvePrograms[flags], &pipelineDesc, descriptorSet, nullptr, 0,
3265                            commandBuffer));
3266     // This draw call is made before ContextVk gets a chance to start the occlusion query.  As such,
3267     // occlusion queries are not enabled.
3268     commandBuffer->draw(3, 0);
3269 
3270     // Release temporary views
3271     vk::ImageView depthViewObject   = depthView.release();
3272     vk::ImageView stencilViewObject = stencilView.release();
3273 
3274     contextVk->addGarbage(&depthViewObject);
3275     contextVk->addGarbage(&stencilViewObject);
3276 
3277     return angle::Result::Continue;
3278 }
3279 
cullOverlayWidgets(ContextVk * contextVk,vk::BufferHelper * enabledWidgetsBuffer,vk::ImageHelper * dest,const vk::ImageView * destView,const OverlayCullParameters & params)3280 angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk,
3281                                           vk::BufferHelper *enabledWidgetsBuffer,
3282                                           vk::ImageHelper *dest,
3283                                           const vk::ImageView *destView,
3284                                           const OverlayCullParameters &params)
3285 {
3286     ANGLE_TRY(ensureOverlayCullResourcesInitialized(contextVk));
3287 
3288     ASSERT(params.subgroupSize[0] == 8 &&
3289            (params.subgroupSize[1] == 8 || params.subgroupSize[1] == 4));
3290     uint32_t flags =
3291         params.subgroupSize[1] == 8 ? OverlayCull_comp::kIs8x8 : OverlayCull_comp::kIs8x4;
3292     if (params.supportsSubgroupBallot)
3293     {
3294         flags |= OverlayCull_comp::kSupportsBallot;
3295     }
3296     else if (params.supportsSubgroupBallot)
3297     {
3298         flags |= OverlayCull_comp::kSupportsArithmetic;
3299     }
3300     else
3301     {
3302         flags |= OverlayCull_comp::kSupportsNone;
3303     }
3304 
3305     VkDescriptorSet descriptorSet;
3306     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
3307     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::OverlayCull, &descriptorPoolBinding,
3308                                     &descriptorSet));
3309 
3310     ASSERT(dest->getLevelCount() == 1 && dest->getLayerCount() == 1 &&
3311            dest->getFirstAllocatedLevel() == gl::LevelIndex(0));
3312 
3313     vk::CommandBufferAccess access;
3314     access.onBufferComputeShaderRead(enabledWidgetsBuffer);
3315     access.onImageComputeShaderWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, dest);
3316 
3317     vk::CommandBuffer *commandBuffer;
3318     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
3319 
3320     VkDescriptorImageInfo imageInfo = {};
3321     imageInfo.imageView             = destView->getHandle();
3322     imageInfo.imageLayout           = dest->getCurrentLayout();
3323 
3324     VkDescriptorBufferInfo bufferInfo = {};
3325     bufferInfo.buffer                 = enabledWidgetsBuffer->getBuffer().getHandle();
3326     bufferInfo.offset                 = 0;
3327     bufferInfo.range                  = VK_WHOLE_SIZE;
3328 
3329     VkWriteDescriptorSet writeInfos[2] = {};
3330     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3331     writeInfos[0].dstSet               = descriptorSet;
3332     writeInfos[0].dstBinding           = kOverlayCullCulledWidgetsBinding;
3333     writeInfos[0].descriptorCount      = 1;
3334     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
3335     writeInfos[0].pImageInfo           = &imageInfo;
3336 
3337     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3338     writeInfos[1].dstSet          = descriptorSet;
3339     writeInfos[1].dstBinding      = kOverlayCullWidgetCoordsBinding;
3340     writeInfos[1].descriptorCount = 1;
3341     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
3342     writeInfos[1].pBufferInfo     = &bufferInfo;
3343 
3344     vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
3345 
3346     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
3347     ANGLE_TRY(contextVk->getShaderLibrary().getOverlayCull_comp(contextVk, flags, &shader));
3348 
3349     ANGLE_TRY(setupProgram(contextVk, Function::OverlayCull, shader, nullptr,
3350                            &mOverlayCullPrograms[flags], nullptr, descriptorSet, nullptr, 0,
3351                            commandBuffer));
3352 
3353     commandBuffer->dispatch(dest->getExtents().width, dest->getExtents().height, 1);
3354     descriptorPoolBinding.reset();
3355 
3356     return angle::Result::Continue;
3357 }
3358 
drawOverlay(ContextVk * contextVk,vk::BufferHelper * textWidgetsBuffer,vk::BufferHelper * graphWidgetsBuffer,vk::ImageHelper * font,const vk::ImageView * fontView,vk::ImageHelper * culledWidgets,const vk::ImageView * culledWidgetsView,vk::ImageHelper * dest,const vk::ImageView * destView,const OverlayDrawParameters & params)3359 angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
3360                                    vk::BufferHelper *textWidgetsBuffer,
3361                                    vk::BufferHelper *graphWidgetsBuffer,
3362                                    vk::ImageHelper *font,
3363                                    const vk::ImageView *fontView,
3364                                    vk::ImageHelper *culledWidgets,
3365                                    const vk::ImageView *culledWidgetsView,
3366                                    vk::ImageHelper *dest,
3367                                    const vk::ImageView *destView,
3368                                    const OverlayDrawParameters &params)
3369 {
3370     ANGLE_TRY(ensureOverlayDrawResourcesInitialized(contextVk));
3371 
3372     OverlayDrawShaderParams shaderParams;
3373     shaderParams.outputSize[0] = dest->getExtents().width;
3374     shaderParams.outputSize[1] = dest->getExtents().height;
3375     shaderParams.rotateXY      = params.rotateXY;
3376 
3377     ASSERT(params.subgroupSize[0] == 8 &&
3378            (params.subgroupSize[1] == 8 || params.subgroupSize[1] == 4));
3379     uint32_t flags =
3380         params.subgroupSize[1] == 8 ? OverlayDraw_comp::kIs8x8 : OverlayDraw_comp::kIs8x4;
3381 
3382     VkDescriptorSet descriptorSet;
3383     vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
3384     ANGLE_TRY(allocateDescriptorSet(contextVk, Function::OverlayDraw, &descriptorPoolBinding,
3385                                     &descriptorSet));
3386 
3387     ASSERT(dest->getLevelCount() == 1 && dest->getLayerCount() == 1 &&
3388            dest->getFirstAllocatedLevel() == gl::LevelIndex(0));
3389 
3390     vk::CommandBufferAccess access;
3391     access.onImageComputeShaderWrite(gl::LevelIndex(0), 1, 0, 1, VK_IMAGE_ASPECT_COLOR_BIT, dest);
3392     access.onImageComputeShaderRead(VK_IMAGE_ASPECT_COLOR_BIT, culledWidgets);
3393     access.onImageComputeShaderRead(VK_IMAGE_ASPECT_COLOR_BIT, font);
3394     access.onBufferComputeShaderRead(textWidgetsBuffer);
3395     access.onBufferComputeShaderRead(graphWidgetsBuffer);
3396 
3397     vk::CommandBuffer *commandBuffer;
3398     ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
3399 
3400     VkDescriptorImageInfo imageInfos[3] = {};
3401     imageInfos[0].imageView             = destView->getHandle();
3402     imageInfos[0].imageLayout           = dest->getCurrentLayout();
3403 
3404     imageInfos[1].imageView   = culledWidgetsView->getHandle();
3405     imageInfos[1].imageLayout = culledWidgets->getCurrentLayout();
3406 
3407     imageInfos[2].imageView   = fontView->getHandle();
3408     imageInfos[2].imageLayout = font->getCurrentLayout();
3409 
3410     VkDescriptorBufferInfo bufferInfos[2] = {};
3411     bufferInfos[0].buffer                 = textWidgetsBuffer->getBuffer().getHandle();
3412     bufferInfos[0].offset                 = 0;
3413     bufferInfos[0].range                  = VK_WHOLE_SIZE;
3414 
3415     bufferInfos[1].buffer = graphWidgetsBuffer->getBuffer().getHandle();
3416     bufferInfos[1].offset = 0;
3417     bufferInfos[1].range  = VK_WHOLE_SIZE;
3418 
3419     VkWriteDescriptorSet writeInfos[5] = {};
3420     writeInfos[0].sType                = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3421     writeInfos[0].dstSet               = descriptorSet;
3422     writeInfos[0].dstBinding           = kOverlayDrawOutputBinding;
3423     writeInfos[0].descriptorCount      = 1;
3424     writeInfos[0].descriptorType       = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
3425     writeInfos[0].pImageInfo           = &imageInfos[0];
3426 
3427     writeInfos[1].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3428     writeInfos[1].dstSet          = descriptorSet;
3429     writeInfos[1].dstBinding      = kOverlayDrawCulledWidgetsBinding;
3430     writeInfos[1].descriptorCount = 1;
3431     writeInfos[1].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3432     writeInfos[1].pImageInfo      = &imageInfos[1];
3433 
3434     writeInfos[2].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3435     writeInfos[2].dstSet          = descriptorSet;
3436     writeInfos[2].dstBinding      = kOverlayDrawFontBinding;
3437     writeInfos[2].descriptorCount = 1;
3438     writeInfos[2].descriptorType  = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3439     writeInfos[2].pImageInfo      = &imageInfos[2];
3440 
3441     writeInfos[3].sType           = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3442     writeInfos[3].dstSet          = descriptorSet;
3443     writeInfos[3].dstBinding      = kOverlayDrawTextWidgetsBinding;
3444     writeInfos[3].descriptorCount = 1;
3445     writeInfos[3].descriptorType  = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
3446     writeInfos[3].pBufferInfo     = &bufferInfos[0];
3447 
3448     writeInfos[4]             = writeInfos[3];
3449     writeInfos[4].dstBinding  = kOverlayDrawGraphWidgetsBinding;
3450     writeInfos[4].pBufferInfo = &bufferInfos[1];
3451 
3452     vkUpdateDescriptorSets(contextVk->getDevice(), 5, writeInfos, 0, nullptr);
3453 
3454     vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
3455     ANGLE_TRY(contextVk->getShaderLibrary().getOverlayDraw_comp(contextVk, flags, &shader));
3456 
3457     ANGLE_TRY(setupProgram(contextVk, Function::OverlayDraw, shader, nullptr,
3458                            &mOverlayDrawPrograms[flags], nullptr, descriptorSet, &shaderParams,
3459                            sizeof(shaderParams), commandBuffer));
3460 
3461     // Every pixel of culledWidgets corresponds to one workgroup, so we can use that as dispatch
3462     // size.
3463     const VkExtent3D &extents = culledWidgets->getExtents();
3464     commandBuffer->dispatch(extents.width, extents.height, 1);
3465     descriptorPoolBinding.reset();
3466 
3467     return angle::Result::Continue;
3468 }
3469 
allocateDescriptorSet(ContextVk * contextVk,Function function,vk::RefCountedDescriptorPoolBinding * bindingOut,VkDescriptorSet * descriptorSetOut)3470 angle::Result UtilsVk::allocateDescriptorSet(ContextVk *contextVk,
3471                                              Function function,
3472                                              vk::RefCountedDescriptorPoolBinding *bindingOut,
3473                                              VkDescriptorSet *descriptorSetOut)
3474 {
3475     ANGLE_TRY(mDescriptorPools[function].allocateSets(
3476         contextVk, mDescriptorSetLayouts[function][DescriptorSetIndex::Internal].get().ptr(), 1,
3477         bindingOut, descriptorSetOut));
3478 
3479     mPerfCounters.descriptorSetsAllocated++;
3480 
3481     return angle::Result::Continue;
3482 }
3483 
ClearFramebufferParameters()3484 UtilsVk::ClearFramebufferParameters::ClearFramebufferParameters()
3485     : clearColor(false),
3486       clearDepth(false),
3487       clearStencil(false),
3488       stencilMask(0),
3489       colorMaskFlags(0),
3490       colorAttachmentIndexGL(0),
3491       colorFormat(nullptr),
3492       colorClearValue{},
3493       depthStencilClearValue{}
3494 {}
3495 
3496 // Requires that trace is enabled to see the output, which is supported with is_debug=true
outputCumulativePerfCounters()3497 void UtilsVk::outputCumulativePerfCounters()
3498 {
3499     if (!vk::kOutputCumulativePerfCounters)
3500     {
3501         return;
3502     }
3503 
3504     INFO() << "Utils Descriptor Set Allocations: "
3505            << mCumulativePerfCounters.descriptorSetsAllocated;
3506 }
3507 
getAndResetObjectPerfCounters()3508 InternalShaderPerfCounters UtilsVk::getAndResetObjectPerfCounters()
3509 {
3510     mCumulativePerfCounters.descriptorSetsAllocated += mPerfCounters.descriptorSetsAllocated;
3511 
3512     InternalShaderPerfCounters counters   = mPerfCounters;
3513     mPerfCounters.descriptorSetsAllocated = 0;
3514     return counters;
3515 }
3516 }  // namespace rx
3517