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