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