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