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