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