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