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