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