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::ErrorContext * context,uint32_t colorAttachmentCount,gl::DrawBuffersArray<UnresolveColorAttachmentType> & colorAttachmentTypes,bool unresolveDepth,bool unresolveStencil,vk::ShaderModulePtr * shader)1143 angle::Result GetUnresolveFrag(
1144 vk::ErrorContext *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 programAndPipelines.pipelines.destroy(contextVk);
1347 }
1348 for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertIndirectLineLoop)
1349 {
1350 programAndPipelines.program.destroy(renderer);
1351 programAndPipelines.pipelines.destroy(contextVk);
1352 }
1353 for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertIndexIndirectLineLoop)
1354 {
1355 programAndPipelines.program.destroy(renderer);
1356 programAndPipelines.pipelines.destroy(contextVk);
1357 }
1358 for (ComputeShaderProgramAndPipelines &programAndPipelines : mConvertVertex)
1359 {
1360 programAndPipelines.program.destroy(renderer);
1361 programAndPipelines.pipelines.destroy(contextVk);
1362 }
1363 mImageClearVSOnly.program.destroy(renderer);
1364 mImageClearVSOnly.pipelines.destroy(contextVk);
1365 for (GraphicsShaderProgramAndPipelines &programAndPipelines : mImageClear)
1366 {
1367 programAndPipelines.program.destroy(renderer);
1368 programAndPipelines.pipelines.destroy(contextVk);
1369 }
1370 for (GraphicsShaderProgramAndPipelines &programAndPipelines : mImageCopy)
1371 {
1372 programAndPipelines.program.destroy(renderer);
1373 programAndPipelines.pipelines.destroy(contextVk);
1374 }
1375 mImageCopyFloat.program.destroy(renderer);
1376 mImageCopyFloat.pipelines.destroy(contextVk);
1377 for (auto &iter : mImageCopyWithSampler)
1378 {
1379 GraphicsShaderProgramAndPipelines &programAndPipelines = iter.second;
1380 programAndPipelines.program.destroy(renderer);
1381 programAndPipelines.pipelines.destroy(contextVk);
1382 }
1383 for (ComputeShaderProgramAndPipelines &programAndPipelines : mCopyImageToBuffer)
1384 {
1385 programAndPipelines.program.destroy(renderer);
1386 programAndPipelines.pipelines.destroy(contextVk);
1387 }
1388 for (GraphicsShaderProgramAndPipelines &programAndPipelines : mBlitResolve)
1389 {
1390 programAndPipelines.program.destroy(renderer);
1391 programAndPipelines.pipelines.destroy(contextVk);
1392 }
1393 for (GraphicsShaderProgramAndPipelines &programAndPipelines : mBlit3DSrc)
1394 {
1395 programAndPipelines.program.destroy(renderer);
1396 programAndPipelines.pipelines.destroy(contextVk);
1397 }
1398 for (ComputeShaderProgramAndPipelines &programAndPipelines : mBlitResolveStencilNoExport)
1399 {
1400 programAndPipelines.program.destroy(renderer);
1401 programAndPipelines.pipelines.destroy(contextVk);
1402 }
1403 mExportStencil.program.destroy(renderer);
1404 mExportStencil.pipelines.destroy(contextVk);
1405 mOverlayDraw.program.destroy(renderer);
1406 mOverlayDraw.pipelines.destroy(contextVk);
1407 for (ComputeShaderProgramAndPipelines &programAndPipelines : mGenerateMipmap)
1408 {
1409 programAndPipelines.program.destroy(renderer);
1410 programAndPipelines.pipelines.destroy(contextVk);
1411 }
1412 for (ComputeShaderProgramAndPipelines &programAndPipelines : mEtcToBc)
1413 {
1414 programAndPipelines.program.destroy(renderer);
1415 programAndPipelines.pipelines.destroy(contextVk);
1416 }
1417 for (auto &programIter : mUnresolve)
1418 {
1419 GraphicsShaderProgramAndPipelines &programAndPipelines = programIter.second;
1420 programAndPipelines.program.destroy(renderer);
1421 programAndPipelines.pipelines.destroy(contextVk);
1422 }
1423 mUnresolve.clear();
1424
1425 mUnresolveFragShaders.clear();
1426
1427 mPointSampler.destroy(device);
1428 mLinearSampler.destroy(device);
1429
1430 mGenerateFragmentShadingRateAttachment.program.destroy(renderer);
1431 mGenerateFragmentShadingRateAttachment.pipelines.destroy(contextVk);
1432 }
1433
ensureResourcesInitialized(ContextVk * contextVk,Function function,VkDescriptorPoolSize * setSizes,size_t setSizesCount,size_t pushConstantsSize)1434 angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
1435 Function function,
1436 VkDescriptorPoolSize *setSizes,
1437 size_t setSizesCount,
1438 size_t pushConstantsSize)
1439 {
1440 vk::DescriptorSetLayoutDesc descriptorSetDesc;
1441 bool isCompute = function >= Function::ComputeStartIndex;
1442 VkShaderStageFlags descStages =
1443 isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
1444 if (function == Function::OverlayDraw)
1445 {
1446 descStages |= VK_SHADER_STAGE_VERTEX_BIT;
1447 }
1448
1449 uint32_t currentBinding = 0;
1450 for (size_t i = 0; i < setSizesCount; ++i)
1451 {
1452 descriptorSetDesc.addBinding(currentBinding, setSizes[i].type, setSizes[i].descriptorCount,
1453 descStages, nullptr);
1454 ++currentBinding;
1455 }
1456
1457 ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1458 contextVk, descriptorSetDesc,
1459 &mDescriptorSetLayouts[function][DescriptorSetIndex::Internal]));
1460
1461 vk::DescriptorSetLayoutBindingVector bindingVector;
1462 descriptorSetDesc.unpackBindings(&bindingVector);
1463 std::vector<VkDescriptorPoolSize> descriptorPoolSizes;
1464
1465 for (const VkDescriptorSetLayoutBinding &binding : bindingVector)
1466 {
1467 if (binding.descriptorCount > 0)
1468 {
1469 VkDescriptorPoolSize poolSize = {};
1470
1471 poolSize.type = binding.descriptorType;
1472 poolSize.descriptorCount = binding.descriptorCount;
1473 descriptorPoolSizes.emplace_back(poolSize);
1474 }
1475 }
1476 if (!descriptorPoolSizes.empty())
1477 {
1478 ANGLE_TRY(mDescriptorPools[function].init(
1479 contextVk, descriptorPoolSizes.data(), descriptorPoolSizes.size(),
1480 *mDescriptorSetLayouts[function][DescriptorSetIndex::Internal]));
1481 }
1482
1483 // Corresponding pipeline layouts:
1484 vk::PipelineLayoutDesc pipelineLayoutDesc;
1485
1486 pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Internal, descriptorSetDesc);
1487 if (pushConstantsSize)
1488 {
1489 pipelineLayoutDesc.updatePushConstantRange(descStages, 0,
1490 static_cast<uint32_t>(pushConstantsSize));
1491 }
1492
1493 ANGLE_TRY(contextVk->getPipelineLayoutCache().getPipelineLayout(contextVk, pipelineLayoutDesc,
1494 mDescriptorSetLayouts[function],
1495 &mPipelineLayouts[function]));
1496
1497 return angle::Result::Continue;
1498 }
1499
ensureConvertIndexResourcesInitialized(ContextVk * contextVk)1500 angle::Result UtilsVk::ensureConvertIndexResourcesInitialized(ContextVk *contextVk)
1501 {
1502 if (mPipelineLayouts[Function::ConvertIndexBuffer])
1503 {
1504 return angle::Result::Continue;
1505 }
1506
1507 VkDescriptorPoolSize setSizes[2] = {
1508 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1509 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1510 };
1511
1512 return ensureResourcesInitialized(contextVk, Function::ConvertIndexBuffer, setSizes,
1513 ArraySize(setSizes), sizeof(ConvertIndexShaderParams));
1514 }
1515
ensureConvertIndexIndirectResourcesInitialized(ContextVk * contextVk)1516 angle::Result UtilsVk::ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk)
1517 {
1518 if (mPipelineLayouts[Function::ConvertIndexIndirectBuffer])
1519 {
1520 return angle::Result::Continue;
1521 }
1522
1523 VkDescriptorPoolSize setSizes[4] = {
1524 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dst index buffer
1525 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // source index buffer
1526 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // src indirect buffer
1527 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dst indirect buffer
1528 };
1529
1530 return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectBuffer, setSizes,
1531 ArraySize(setSizes),
1532 sizeof(ConvertIndexIndirectShaderParams));
1533 }
1534
ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk * contextVk)1535 angle::Result UtilsVk::ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
1536 {
1537 if (mPipelineLayouts[Function::ConvertIndexIndirectLineLoopBuffer])
1538 {
1539 return angle::Result::Continue;
1540 }
1541
1542 VkDescriptorPoolSize setSizes[4] = {
1543 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // cmd buffer
1544 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dst cmd buffer
1545 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // source index buffer
1546 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dst index buffer
1547 };
1548
1549 return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
1550 setSizes, ArraySize(setSizes),
1551 sizeof(ConvertIndexIndirectLineLoopShaderParams));
1552 }
1553
ensureConvertIndirectLineLoopResourcesInitialized(ContextVk * contextVk)1554 angle::Result UtilsVk::ensureConvertIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
1555 {
1556 if (mPipelineLayouts[Function::ConvertIndirectLineLoopBuffer])
1557 {
1558 return angle::Result::Continue;
1559 }
1560
1561 VkDescriptorPoolSize setSizes[3] = {
1562 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // cmd buffer
1563 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dst cmd buffer
1564 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dst index buffer
1565 };
1566
1567 return ensureResourcesInitialized(contextVk, Function::ConvertIndirectLineLoopBuffer, setSizes,
1568 ArraySize(setSizes),
1569 sizeof(ConvertIndirectLineLoopShaderParams));
1570 }
1571
ensureConvertVertexResourcesInitialized(ContextVk * contextVk)1572 angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk)
1573 {
1574 if (mPipelineLayouts[Function::ConvertVertexBuffer])
1575 {
1576 return angle::Result::Continue;
1577 }
1578
1579 VkDescriptorPoolSize setSizes[2] = {
1580 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1581 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1582 };
1583
1584 return ensureResourcesInitialized(contextVk, Function::ConvertVertexBuffer, setSizes,
1585 ArraySize(setSizes), sizeof(ConvertVertexShaderParams));
1586 }
1587
ensureImageClearResourcesInitialized(ContextVk * contextVk)1588 angle::Result UtilsVk::ensureImageClearResourcesInitialized(ContextVk *contextVk)
1589 {
1590 if (mPipelineLayouts[Function::ImageClear])
1591 {
1592 return angle::Result::Continue;
1593 }
1594
1595 // The shader does not use any descriptor sets.
1596 return ensureResourcesInitialized(contextVk, Function::ImageClear, nullptr, 0,
1597 sizeof(ImageClearShaderParams));
1598 }
1599
ensureImageCopyResourcesInitialized(ContextVk * contextVk)1600 angle::Result UtilsVk::ensureImageCopyResourcesInitialized(ContextVk *contextVk)
1601 {
1602 if (mPipelineLayouts[Function::ImageCopy])
1603 {
1604 return angle::Result::Continue;
1605 }
1606
1607 VkDescriptorPoolSize setSizes[1] = {
1608 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1609 };
1610
1611 return ensureResourcesInitialized(contextVk, Function::ImageCopy, setSizes, ArraySize(setSizes),
1612 sizeof(ImageCopyShaderParams));
1613 }
1614
ensureImageCopyResourcesInitializedWithSampler(ContextVk * contextVk,const vk::SamplerDesc & samplerDesc)1615 angle::Result UtilsVk::ensureImageCopyResourcesInitializedWithSampler(
1616 ContextVk *contextVk,
1617 const vk::SamplerDesc &samplerDesc)
1618 {
1619 if (mImageCopyWithSamplerPipelineLayouts[samplerDesc])
1620 {
1621 return angle::Result::Continue;
1622 }
1623
1624 vk::SharedSamplerPtr sampler;
1625 ANGLE_TRY(
1626 contextVk->getRenderer()->getSamplerCache().getSampler(contextVk, samplerDesc, &sampler));
1627
1628 vk::DescriptorSetLayoutDesc descriptorSetDesc;
1629 descriptorSetDesc.addBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1,
1630 VK_SHADER_STAGE_FRAGMENT_BIT, &sampler->get());
1631
1632 ANGLE_TRY(contextVk->getDescriptorSetLayoutCache().getDescriptorSetLayout(
1633 contextVk, descriptorSetDesc,
1634 &mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc][DescriptorSetIndex::Internal]));
1635
1636 VkDescriptorPoolSize setSizes[1] = {
1637 // A single YCbCr sampler may consume up to 3 descriptors.
1638 {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3},
1639 };
1640 ANGLE_TRY(mImageCopyWithSamplerDescriptorPools[samplerDesc].init(
1641 contextVk, setSizes, 1,
1642 *mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc][DescriptorSetIndex::Internal]));
1643
1644 vk::PipelineLayoutDesc pipelineLayoutDesc;
1645 pipelineLayoutDesc.updateDescriptorSetLayout(DescriptorSetIndex::Internal, descriptorSetDesc);
1646 pipelineLayoutDesc.updatePushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0,
1647 sizeof(ImageCopyShaderParams));
1648
1649 ANGLE_TRY(contextVk->getPipelineLayoutCache().getPipelineLayout(
1650 contextVk, pipelineLayoutDesc, mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc],
1651 &mImageCopyWithSamplerPipelineLayouts[samplerDesc]));
1652
1653 return angle::Result::Continue;
1654 }
1655
ensureCopyImageToBufferResourcesInitialized(ContextVk * contextVk)1656 angle::Result UtilsVk::ensureCopyImageToBufferResourcesInitialized(ContextVk *contextVk)
1657 {
1658 if (mPipelineLayouts[Function::CopyImageToBuffer])
1659 {
1660 return angle::Result::Continue;
1661 }
1662
1663 VkDescriptorPoolSize setSizes[2] = {
1664 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1665 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1666 };
1667
1668 return ensureResourcesInitialized(contextVk, Function::CopyImageToBuffer, setSizes,
1669 ArraySize(setSizes), sizeof(CopyImageToBufferShaderParams));
1670 }
1671
ensureBlitResolveResourcesInitialized(ContextVk * contextVk)1672 angle::Result UtilsVk::ensureBlitResolveResourcesInitialized(ContextVk *contextVk)
1673 {
1674 if (!mPipelineLayouts[Function::BlitResolve])
1675 {
1676 VkDescriptorPoolSize setSizes[3] = {
1677 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1678 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1679 {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
1680 };
1681
1682 ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolve, setSizes,
1683 ArraySize(setSizes), sizeof(BlitResolveShaderParams)));
1684 }
1685
1686 return ensureSamplersInitialized(contextVk);
1687 }
1688
ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk * contextVk)1689 angle::Result UtilsVk::ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk *contextVk)
1690 {
1691 if (!mPipelineLayouts[Function::BlitResolveStencilNoExport])
1692 {
1693 VkDescriptorPoolSize setSizes[3] = {
1694 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
1695 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1696 {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
1697 };
1698
1699 ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolveStencilNoExport,
1700 setSizes, ArraySize(setSizes),
1701 sizeof(BlitResolveStencilNoExportShaderParams)));
1702 }
1703
1704 return ensureSamplersInitialized(contextVk);
1705 }
1706
ensureExportStencilResourcesInitialized(ContextVk * contextVk)1707 angle::Result UtilsVk::ensureExportStencilResourcesInitialized(ContextVk *contextVk)
1708 {
1709 if (mPipelineLayouts[Function::ExportStencil])
1710 {
1711 return angle::Result::Continue;
1712 }
1713
1714 VkDescriptorPoolSize setSizes[1] = {
1715 {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1},
1716 };
1717
1718 return ensureResourcesInitialized(contextVk, Function::ExportStencil, setSizes,
1719 ArraySize(setSizes), sizeof(ExportStencilShaderParams));
1720 }
1721
ensureOverlayDrawResourcesInitialized(ContextVk * contextVk)1722 angle::Result UtilsVk::ensureOverlayDrawResourcesInitialized(ContextVk *contextVk)
1723 {
1724 if (!mPipelineLayouts[Function::OverlayDraw])
1725 {
1726 VkDescriptorPoolSize setSizes[3] = {
1727 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
1728 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
1729 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
1730 };
1731
1732 ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::OverlayDraw, setSizes,
1733 ArraySize(setSizes), sizeof(OverlayDrawShaderParams)));
1734 }
1735
1736 return ensureSamplersInitialized(contextVk);
1737 }
1738
ensureGenerateMipmapResourcesInitialized(ContextVk * contextVk)1739 angle::Result UtilsVk::ensureGenerateMipmapResourcesInitialized(ContextVk *contextVk)
1740 {
1741 if (mPipelineLayouts[Function::GenerateMipmap])
1742 {
1743 return angle::Result::Continue;
1744 }
1745
1746 VkDescriptorPoolSize setSizes[2] = {
1747 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, GetGenerateMipmapMaxLevels(contextVk)},
1748 {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1},
1749 };
1750
1751 return ensureResourcesInitialized(contextVk, Function::GenerateMipmap, setSizes,
1752 ArraySize(setSizes), sizeof(GenerateMipmapShaderParams));
1753 }
1754
ensureTransCodeEtcToBcResourcesInitialized(ContextVk * contextVk)1755 angle::Result UtilsVk::ensureTransCodeEtcToBcResourcesInitialized(ContextVk *contextVk)
1756 {
1757 if (mPipelineLayouts[Function::TransCodeEtcToBc])
1758 {
1759 return angle::Result::Continue;
1760 }
1761 VkDescriptorPoolSize setSizes[2] = {
1762 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1},
1763 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
1764 };
1765
1766 return ensureResourcesInitialized(contextVk, Function::TransCodeEtcToBc, setSizes,
1767 ArraySize(setSizes), sizeof(EtcToBcShaderParams));
1768 }
1769
ensureUnresolveResourcesInitialized(ContextVk * contextVk,Function function,uint32_t attachmentCount)1770 angle::Result UtilsVk::ensureUnresolveResourcesInitialized(ContextVk *contextVk,
1771 Function function,
1772 uint32_t attachmentCount)
1773 {
1774 ASSERT(static_cast<uint32_t>(function) -
1775 static_cast<uint32_t>(Function::Unresolve1Attachment) ==
1776 attachmentCount - 1);
1777
1778 if (mPipelineLayouts[function])
1779 {
1780 return angle::Result::Continue;
1781 }
1782
1783 vk::FramebufferAttachmentArray<VkDescriptorPoolSize> setSizes;
1784 std::fill(setSizes.begin(), setSizes.end(),
1785 VkDescriptorPoolSize{VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1});
1786
1787 return ensureResourcesInitialized(contextVk, function, setSizes.data(), attachmentCount, 0);
1788 }
1789
ensureSamplersInitialized(ContextVk * contextVk)1790 angle::Result UtilsVk::ensureSamplersInitialized(ContextVk *contextVk)
1791 {
1792 VkSamplerCreateInfo samplerInfo = {};
1793 samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
1794 samplerInfo.flags = 0;
1795 samplerInfo.magFilter = VK_FILTER_NEAREST;
1796 samplerInfo.minFilter = VK_FILTER_NEAREST;
1797 samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
1798 samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1799 samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1800 samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1801 samplerInfo.mipLodBias = 0.0f;
1802 samplerInfo.anisotropyEnable = VK_FALSE;
1803 samplerInfo.maxAnisotropy = 1;
1804 samplerInfo.compareEnable = VK_FALSE;
1805 samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
1806 samplerInfo.minLod = 0;
1807 samplerInfo.maxLod = 0;
1808 samplerInfo.borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
1809 samplerInfo.unnormalizedCoordinates = VK_FALSE;
1810
1811 if (!mPointSampler.valid())
1812 {
1813 ANGLE_VK_TRY(contextVk, mPointSampler.init(contextVk->getDevice(), samplerInfo));
1814 }
1815
1816 samplerInfo.magFilter = VK_FILTER_LINEAR;
1817 samplerInfo.minFilter = VK_FILTER_LINEAR;
1818
1819 if (!mLinearSampler.valid())
1820 {
1821 ANGLE_VK_TRY(contextVk, mLinearSampler.init(contextVk->getDevice(), samplerInfo));
1822 }
1823
1824 return angle::Result::Continue;
1825 }
1826
ensureGenerateFragmentShadingRateResourcesInitialized(ContextVk * contextVk)1827 angle::Result UtilsVk::ensureGenerateFragmentShadingRateResourcesInitialized(ContextVk *contextVk)
1828 {
1829 if (mGenerateFragmentShadingRateAttachment.program.valid(gl::ShaderType::Compute))
1830 {
1831 return angle::Result::Continue;
1832 }
1833
1834 VkDescriptorPoolSize setSizes[1] = {
1835 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
1836 };
1837
1838 return ensureResourcesInitialized(contextVk, Function::GenerateFragmentShadingRate, setSizes,
1839 ArraySize(setSizes),
1840 sizeof(GenerateFragmentShadingRateParameters));
1841 }
1842
setupComputeProgram(ContextVk * contextVk,Function function,const vk::ShaderModulePtr & csShader,ComputeShaderProgramAndPipelines * programAndPipelines,const VkDescriptorSet descriptorSet,const void * pushConstants,size_t pushConstantsSize,vk::OutsideRenderPassCommandBufferHelper * commandBufferHelper)1843 angle::Result UtilsVk::setupComputeProgram(
1844 ContextVk *contextVk,
1845 Function function,
1846 const vk::ShaderModulePtr &csShader,
1847 ComputeShaderProgramAndPipelines *programAndPipelines,
1848 const VkDescriptorSet descriptorSet,
1849 const void *pushConstants,
1850 size_t pushConstantsSize,
1851 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper)
1852 {
1853 vk::Renderer *renderer = contextVk->getRenderer();
1854
1855 ASSERT(function >= Function::ComputeStartIndex);
1856
1857 const vk::PipelineLayoutPtr &pipelineLayout = mPipelineLayouts[function];
1858
1859 if (!programAndPipelines->program.valid(gl::ShaderType::Compute))
1860 {
1861 programAndPipelines->program.setShader(gl::ShaderType::Compute, csShader);
1862 }
1863
1864 vk::PipelineHelper *pipeline;
1865 vk::PipelineCacheAccess pipelineCache;
1866 ANGLE_TRY(renderer->getPipelineCache(contextVk, &pipelineCache));
1867 ANGLE_TRY(programAndPipelines->program.getOrCreateComputePipeline(
1868 contextVk, &programAndPipelines->pipelines, &pipelineCache, *pipelineLayout,
1869 vk::GetComputePipelineOptions(contextVk->pipelineRobustness(),
1870 contextVk->pipelineProtectedAccess()),
1871 PipelineSource::Utils, &pipeline, nullptr, nullptr));
1872 commandBufferHelper->retainResource(pipeline);
1873
1874 vk::OutsideRenderPassCommandBuffer *commandBuffer = &commandBufferHelper->getCommandBuffer();
1875 commandBuffer->bindComputePipeline(pipeline->getPipeline());
1876
1877 contextVk->invalidateComputePipelineBinding();
1878
1879 if (descriptorSet != VK_NULL_HANDLE)
1880 {
1881 commandBuffer->bindDescriptorSets(*pipelineLayout, VK_PIPELINE_BIND_POINT_COMPUTE,
1882 DescriptorSetIndex::Internal, 1, &descriptorSet, 0,
1883 nullptr);
1884 contextVk->invalidateComputeDescriptorSet(DescriptorSetIndex::Internal);
1885 }
1886
1887 if (pushConstants)
1888 {
1889 commandBuffer->pushConstants(*pipelineLayout, VK_SHADER_STAGE_COMPUTE_BIT, 0,
1890 static_cast<uint32_t>(pushConstantsSize), pushConstants);
1891 }
1892
1893 return angle::Result::Continue;
1894 }
1895
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)1896 angle::Result UtilsVk::setupGraphicsProgramWithLayout(
1897 ContextVk *contextVk,
1898 const vk::PipelineLayout &pipelineLayout,
1899 const vk::ShaderModulePtr &vsShader,
1900 const vk::ShaderModulePtr &fsShader,
1901 GraphicsShaderProgramAndPipelines *programAndPipelines,
1902 const vk::GraphicsPipelineDesc *pipelineDesc,
1903 const VkDescriptorSet descriptorSet,
1904 const void *pushConstants,
1905 size_t pushConstantsSize,
1906 vk::RenderPassCommandBuffer *commandBuffer)
1907 {
1908 vk::Renderer *renderer = contextVk->getRenderer();
1909
1910 if (!programAndPipelines->program.valid(gl::ShaderType::Vertex))
1911 {
1912 programAndPipelines->program.setShader(gl::ShaderType::Vertex, vsShader);
1913 if (fsShader)
1914 {
1915 programAndPipelines->program.setShader(gl::ShaderType::Fragment, fsShader);
1916 }
1917 }
1918
1919 // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
1920 vk::PipelineCacheAccess pipelineCache;
1921 ANGLE_TRY(renderer->getPipelineCache(contextVk, &pipelineCache));
1922
1923 // Pull in a compatible RenderPass.
1924 const vk::RenderPass *compatibleRenderPass = nullptr;
1925 ANGLE_TRY(contextVk->getCompatibleRenderPass(pipelineDesc->getRenderPassDesc(),
1926 &compatibleRenderPass));
1927
1928 const vk::GraphicsPipelineDesc *descPtr;
1929 vk::PipelineHelper *helper;
1930
1931 if (!programAndPipelines->pipelines.getPipeline(*pipelineDesc, &descPtr, &helper))
1932 {
1933 ANGLE_TRY(programAndPipelines->program.createGraphicsPipeline(
1934 contextVk, &programAndPipelines->pipelines, &pipelineCache, *compatibleRenderPass,
1935 pipelineLayout, PipelineSource::Utils, *pipelineDesc, {}, &descPtr, &helper));
1936 }
1937
1938 contextVk->getStartedRenderPassCommands().retainResource(helper);
1939 commandBuffer->bindGraphicsPipeline(helper->getPipeline());
1940
1941 contextVk->invalidateGraphicsPipelineBinding();
1942
1943 if (descriptorSet != VK_NULL_HANDLE)
1944 {
1945 commandBuffer->bindDescriptorSets(pipelineLayout, VK_PIPELINE_BIND_POINT_GRAPHICS,
1946 DescriptorSetIndex::Internal, 1, &descriptorSet, 0,
1947 nullptr);
1948 contextVk->invalidateGraphicsDescriptorSet(DescriptorSetIndex::Internal);
1949 }
1950
1951 if (pushConstants)
1952 {
1953 commandBuffer->pushConstants(pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0,
1954 static_cast<uint32_t>(pushConstantsSize), pushConstants);
1955 }
1956
1957 ResetDynamicState(contextVk, commandBuffer);
1958
1959 return angle::Result::Continue;
1960 }
1961
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)1962 angle::Result UtilsVk::setupGraphicsProgram(ContextVk *contextVk,
1963 Function function,
1964 const vk::ShaderModulePtr &vsShader,
1965 const vk::ShaderModulePtr &fsShader,
1966 GraphicsShaderProgramAndPipelines *programAndPipelines,
1967 const vk::GraphicsPipelineDesc *pipelineDesc,
1968 const VkDescriptorSet descriptorSet,
1969 const void *pushConstants,
1970 size_t pushConstantsSize,
1971 vk::RenderPassCommandBuffer *commandBuffer)
1972 {
1973 ASSERT(function < Function::ComputeStartIndex);
1974
1975 return setupGraphicsProgramWithLayout(
1976 contextVk, *mPipelineLayouts[function], vsShader, fsShader, programAndPipelines,
1977 pipelineDesc, descriptorSet, pushConstants, pushConstantsSize, commandBuffer);
1978 }
1979
convertIndexBuffer(ContextVk * contextVk,vk::BufferHelper * dst,vk::BufferHelper * src,const ConvertIndexParameters & params)1980 angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
1981 vk::BufferHelper *dst,
1982 vk::BufferHelper *src,
1983 const ConvertIndexParameters ¶ms)
1984 {
1985 ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk));
1986
1987 vk::CommandBufferAccess access;
1988 access.onBufferComputeShaderRead(src);
1989 access.onBufferComputeShaderWrite(dst);
1990
1991 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
1992 vk::OutsideRenderPassCommandBuffer *commandBuffer;
1993 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
1994 commandBuffer = &commandBufferHelper->getCommandBuffer();
1995
1996 VkDescriptorSet descriptorSet;
1997 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::ConvertIndexBuffer,
1998 &descriptorSet));
1999
2000 std::array<VkDescriptorBufferInfo, 2> buffers = {{
2001 {dst->getBuffer().getHandle(), dst->getOffset(), dst->getSize()},
2002 {src->getBuffer().getHandle(), src->getOffset(), src->getSize()},
2003 }};
2004
2005 VkWriteDescriptorSet writeInfo = {};
2006 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2007 writeInfo.dstSet = descriptorSet;
2008 writeInfo.dstBinding = kConvertIndexDestinationBinding;
2009 writeInfo.descriptorCount = 2;
2010 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2011 writeInfo.pBufferInfo = buffers.data();
2012
2013 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2014
2015 ConvertIndexShaderParams shaderParams = {params.srcOffset, params.dstOffset >> 2,
2016 params.maxIndex, 0};
2017
2018 uint32_t flags = 0;
2019 if (contextVk->getState().isPrimitiveRestartEnabled())
2020 {
2021 flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
2022 }
2023
2024 vk::ShaderModulePtr shader;
2025 ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
2026
2027 ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexBuffer, shader,
2028 &mConvertIndex[flags], descriptorSet, &shaderParams,
2029 sizeof(ConvertIndexShaderParams), commandBufferHelper));
2030
2031 constexpr uint32_t kInvocationsPerGroup = 64;
2032 constexpr uint32_t kInvocationsPerIndex = 2;
2033 const uint32_t kIndexCount = params.maxIndex;
2034 const uint32_t kGroupCount =
2035 UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
2036 commandBuffer->dispatch(kGroupCount, 1, 1);
2037
2038 return angle::Result::Continue;
2039 }
2040
convertIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuf,vk::BufferHelper * srcIndexBuf,vk::BufferHelper * dstIndirectBuf,vk::BufferHelper * dstIndexBuf,const ConvertIndexIndirectParameters & params)2041 angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
2042 vk::BufferHelper *srcIndirectBuf,
2043 vk::BufferHelper *srcIndexBuf,
2044 vk::BufferHelper *dstIndirectBuf,
2045 vk::BufferHelper *dstIndexBuf,
2046 const ConvertIndexIndirectParameters ¶ms)
2047 {
2048 ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk));
2049
2050 vk::CommandBufferAccess access;
2051 access.onBufferComputeShaderRead(srcIndirectBuf);
2052 access.onBufferComputeShaderRead(srcIndexBuf);
2053 access.onBufferComputeShaderWrite(dstIndirectBuf);
2054 access.onBufferComputeShaderWrite(dstIndexBuf);
2055
2056 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2057 vk::OutsideRenderPassCommandBuffer *commandBuffer;
2058 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2059 commandBuffer = &commandBufferHelper->getCommandBuffer();
2060
2061 VkDescriptorSet descriptorSet;
2062 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
2063 Function::ConvertIndexIndirectBuffer, &descriptorSet));
2064
2065 std::array<VkDescriptorBufferInfo, 4> buffers = {{
2066 {dstIndexBuf->getBuffer().getHandle(), dstIndexBuf->getOffset(), dstIndexBuf->getSize()},
2067 {srcIndexBuf->getBuffer().getHandle(), srcIndexBuf->getOffset(), srcIndexBuf->getSize()},
2068 {srcIndirectBuf->getBuffer().getHandle(), srcIndirectBuf->getOffset(),
2069 srcIndirectBuf->getSize()},
2070 {dstIndirectBuf->getBuffer().getHandle(), dstIndirectBuf->getOffset(),
2071 dstIndirectBuf->getSize()},
2072 }};
2073
2074 VkWriteDescriptorSet writeInfo = {};
2075 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2076 writeInfo.dstSet = descriptorSet;
2077 writeInfo.dstBinding = kConvertIndexDestinationBinding;
2078 writeInfo.descriptorCount = 4;
2079 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2080 writeInfo.pBufferInfo = buffers.data();
2081
2082 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2083
2084 ConvertIndexIndirectShaderParams shaderParams = {
2085 params.srcIndirectBufOffset >> 2, params.srcIndexBufOffset, params.dstIndexBufOffset >> 2,
2086 params.maxIndex, params.dstIndirectBufOffset >> 2};
2087
2088 uint32_t flags = vk::InternalShader::ConvertIndex_comp::kIsIndirect;
2089 if (contextVk->getState().isPrimitiveRestartEnabled())
2090 {
2091 flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
2092 }
2093
2094 vk::ShaderModulePtr shader;
2095 ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
2096
2097 ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader,
2098 &mConvertIndex[flags], descriptorSet, &shaderParams,
2099 sizeof(ConvertIndexIndirectShaderParams), commandBufferHelper));
2100
2101 constexpr uint32_t kInvocationsPerGroup = 64;
2102 constexpr uint32_t kInvocationsPerIndex = 2;
2103 const uint32_t kIndexCount = params.maxIndex;
2104 const uint32_t kGroupCount =
2105 UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
2106 commandBuffer->dispatch(kGroupCount, 1, 1);
2107
2108 return angle::Result::Continue;
2109 }
2110
convertLineLoopIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * srcIndexBuffer,vk::BufferHelper * dstIndirectBuffer,vk::BufferHelper * dstIndexBuffer,const ConvertLineLoopIndexIndirectParameters & params)2111 angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
2112 ContextVk *contextVk,
2113 vk::BufferHelper *srcIndirectBuffer,
2114 vk::BufferHelper *srcIndexBuffer,
2115 vk::BufferHelper *dstIndirectBuffer,
2116 vk::BufferHelper *dstIndexBuffer,
2117 const ConvertLineLoopIndexIndirectParameters ¶ms)
2118 {
2119 ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk));
2120
2121 vk::CommandBufferAccess access;
2122 access.onBufferComputeShaderRead(srcIndirectBuffer);
2123 access.onBufferComputeShaderRead(srcIndexBuffer);
2124 access.onBufferComputeShaderWrite(dstIndirectBuffer);
2125 access.onBufferComputeShaderWrite(dstIndexBuffer);
2126
2127 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2128 vk::OutsideRenderPassCommandBuffer *commandBuffer;
2129 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2130 commandBuffer = &commandBufferHelper->getCommandBuffer();
2131
2132 VkDescriptorSet descriptorSet;
2133 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
2134 Function::ConvertIndexIndirectLineLoopBuffer, &descriptorSet));
2135
2136 std::array<VkDescriptorBufferInfo, 4> buffers = {{
2137 {dstIndexBuffer->getBuffer().getHandle(), dstIndexBuffer->getOffset(),
2138 dstIndexBuffer->getSize()},
2139 {srcIndexBuffer->getBuffer().getHandle(), srcIndexBuffer->getOffset(),
2140 srcIndexBuffer->getSize()},
2141 {srcIndirectBuffer->getBuffer().getHandle(), srcIndirectBuffer->getOffset(),
2142 srcIndirectBuffer->getSize()},
2143 {dstIndirectBuffer->getBuffer().getHandle(), dstIndirectBuffer->getOffset(),
2144 dstIndirectBuffer->getSize()},
2145 }};
2146
2147 VkWriteDescriptorSet writeInfo = {};
2148 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2149 writeInfo.dstSet = descriptorSet;
2150 writeInfo.dstBinding = kConvertIndexDestinationBinding;
2151 writeInfo.descriptorCount = 4;
2152 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2153 writeInfo.pBufferInfo = buffers.data();
2154
2155 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2156
2157 ConvertIndexIndirectLineLoopShaderParams shaderParams = {
2158 params.indirectBufferOffset >> 2, params.dstIndirectBufferOffset >> 2,
2159 params.srcIndexBufferOffset, params.dstIndexBufferOffset >> 2,
2160 contextVk->getState().isPrimitiveRestartEnabled()};
2161
2162 uint32_t flags = GetConvertIndexIndirectLineLoopFlag(params.indicesBitsWidth);
2163
2164 vk::ShaderModulePtr shader;
2165 ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndexIndirectLineLoop_comp(contextVk, flags,
2166 &shader));
2167
2168 ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader,
2169 &mConvertIndexIndirectLineLoop[flags], descriptorSet,
2170 &shaderParams, sizeof(ConvertIndexIndirectLineLoopShaderParams),
2171 commandBufferHelper));
2172
2173 commandBuffer->dispatch(1, 1, 1);
2174
2175 return angle::Result::Continue;
2176 }
2177
convertLineLoopArrayIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * dstIndirectBuffer,vk::BufferHelper * dstIndexBuffer,const ConvertLineLoopArrayIndirectParameters & params)2178 angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer(
2179 ContextVk *contextVk,
2180 vk::BufferHelper *srcIndirectBuffer,
2181 vk::BufferHelper *dstIndirectBuffer,
2182 vk::BufferHelper *dstIndexBuffer,
2183 const ConvertLineLoopArrayIndirectParameters ¶ms)
2184 {
2185 ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk));
2186
2187 vk::CommandBufferAccess access;
2188 access.onBufferComputeShaderRead(srcIndirectBuffer);
2189 access.onBufferComputeShaderWrite(dstIndirectBuffer);
2190 access.onBufferComputeShaderWrite(dstIndexBuffer);
2191
2192 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2193 vk::OutsideRenderPassCommandBuffer *commandBuffer;
2194 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2195 commandBuffer = &commandBufferHelper->getCommandBuffer();
2196
2197 VkDescriptorSet descriptorSet;
2198 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
2199 Function::ConvertIndirectLineLoopBuffer, &descriptorSet));
2200
2201 std::array<VkDescriptorBufferInfo, 3> buffers = {{
2202 {srcIndirectBuffer->getBuffer().getHandle(), srcIndirectBuffer->getOffset(),
2203 srcIndirectBuffer->getSize()},
2204 {dstIndirectBuffer->getBuffer().getHandle(), dstIndirectBuffer->getOffset(),
2205 dstIndirectBuffer->getSize()},
2206 {dstIndexBuffer->getBuffer().getHandle(), dstIndexBuffer->getOffset(),
2207 dstIndexBuffer->getSize()},
2208 }};
2209
2210 VkWriteDescriptorSet writeInfo = {};
2211 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2212 writeInfo.dstSet = descriptorSet;
2213 writeInfo.dstBinding = kConvertIndexDestinationBinding;
2214 writeInfo.descriptorCount = 3;
2215 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2216 writeInfo.pBufferInfo = buffers.data();
2217
2218 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2219
2220 ConvertIndirectLineLoopShaderParams shaderParams = {params.indirectBufferOffset >> 2,
2221 params.dstIndirectBufferOffset >> 2,
2222 params.dstIndexBufferOffset >> 2};
2223
2224 uint32_t flags = 0;
2225
2226 vk::ShaderModulePtr shader;
2227 ANGLE_TRY(
2228 contextVk->getShaderLibrary().getConvertIndirectLineLoop_comp(contextVk, flags, &shader));
2229
2230 ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertIndirectLineLoopBuffer, shader,
2231 &mConvertIndirectLineLoop[flags], descriptorSet, &shaderParams,
2232 sizeof(ConvertIndirectLineLoopShaderParams),
2233 commandBufferHelper));
2234
2235 commandBuffer->dispatch(1, 1, 1);
2236
2237 return angle::Result::Continue;
2238 }
2239
2240 // Used to clear a layer of a renderable texture in part or whole (EXT_clear_texture).
clearTexture(ContextVk * contextVk,vk::ImageHelper * dst,ClearTextureParameters & params)2241 angle::Result UtilsVk::clearTexture(ContextVk *contextVk,
2242 vk::ImageHelper *dst,
2243 ClearTextureParameters ¶ms)
2244 {
2245 const angle::Format &dstActualFormat = dst->getActualFormat();
2246 bool isDepthOrStencil = dstActualFormat.hasDepthOrStencilBits();
2247 bool isFormatDS = dstActualFormat.hasDepthAndStencilBits();
2248
2249 vk::DeviceScoped<vk::ImageView> destView(contextVk->getDevice());
2250 const gl::TextureType destViewType = vk::Get2DTextureType(1, dst->getSamples());
2251
2252 ANGLE_TRY(dst->initLayerImageView(contextVk, destViewType, params.aspectFlags,
2253 gl::SwizzleState(), &destView.get(), params.level, 1,
2254 params.layer, 1));
2255
2256 gl::Rectangle renderArea = {};
2257 renderArea.x = params.clearArea.x;
2258 renderArea.y = params.clearArea.y;
2259 renderArea.width = params.clearArea.width;
2260 renderArea.height = params.clearArea.height;
2261
2262 vk::RenderPassDesc renderPassDesc;
2263 renderPassDesc.setSamples(dst->getSamples());
2264
2265 if (!isDepthOrStencil)
2266 {
2267 renderPassDesc.packColorAttachment(0, dstActualFormat.id);
2268 }
2269 else
2270 {
2271 renderPassDesc.packDepthStencilAttachment(dstActualFormat.id);
2272 }
2273 vk::RenderPassCommandBuffer *commandBuffer;
2274 vk::ImageLayout imageLayout =
2275 isDepthOrStencil ? vk::ImageLayout::DepthWriteStencilWrite : vk::ImageLayout::ColorWrite;
2276
2277 ANGLE_TRY(startRenderPass(contextVk, dst, &destView.get(), renderPassDesc, renderArea,
2278 params.aspectFlags, ¶ms.clearValue,
2279 vk::RenderPassSource::InternalUtils, &commandBuffer));
2280
2281 // If the format contains both depth and stencil, the barrier aspect mask for the image should
2282 // include both bits.
2283 contextVk->onImageRenderPassWrite(
2284 dst->toGLLevel(params.level), params.layer, 1,
2285 isFormatDS ? VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT : params.aspectFlags,
2286 imageLayout, dst);
2287
2288 vk::ImageView destViewObject = destView.release();
2289 contextVk->addGarbage(&destViewObject);
2290
2291 // Close the render pass for this temporary framebuffer. If the render pass is not immediately
2292 // closed and the render area grows due to scissor change, the clear area unexpectedly changes.
2293 // This can be avoided if the scissor code takes LOAD_OP_CLEAR into account before deciding to
2294 // grow the render pass's render area.
2295 return contextVk->flushCommandsAndEndRenderPass(
2296 RenderPassClosureReason::TemporaryForClearTexture);
2297 }
2298
convertVertexBuffer(ContextVk * contextVk,vk::BufferHelper * dst,vk::BufferHelper * src,const ConvertVertexParameters & params,const OffsetAndVertexCounts & additionalOffsetVertexCounts)2299 angle::Result UtilsVk::convertVertexBuffer(
2300 ContextVk *contextVk,
2301 vk::BufferHelper *dst,
2302 vk::BufferHelper *src,
2303 const ConvertVertexParameters ¶ms,
2304 const OffsetAndVertexCounts &additionalOffsetVertexCounts)
2305 {
2306 vk::CommandBufferAccess access;
2307 access.onBufferComputeShaderRead(src);
2308 access.onBufferComputeShaderWrite(dst);
2309
2310 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
2311 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
2312
2313 ConvertVertexShaderParams shaderParams;
2314 shaderParams.Ns = params.srcFormat->channelCount;
2315 shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount;
2316 shaderParams.Ss = static_cast<uint32_t>(params.srcStride);
2317 shaderParams.Nd = params.dstFormat->channelCount;
2318 shaderParams.Bd = params.dstFormat->pixelBytes / params.dstFormat->channelCount;
2319 shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
2320 // The component size is expected to either be 1, 2 or 4 bytes.
2321 ASSERT(4 % shaderParams.Bs == 0);
2322 ASSERT(4 % shaderParams.Bd == 0);
2323 shaderParams.Es = 4 / shaderParams.Bs;
2324 shaderParams.Ed = 4 / shaderParams.Bd;
2325 // Total number of output components is simply the number of vertices by number of components in
2326 // each.
2327 shaderParams.componentCount = static_cast<uint32_t>(params.vertexCount * shaderParams.Nd);
2328 // Total number of 4-byte outputs is the number of components divided by how many components can
2329 // fit in a 4-byte value. Note that this value is also the invocation size of the shader.
2330 shaderParams.outputCount = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
2331 shaderParams.srcOffset = static_cast<uint32_t>(params.srcOffset);
2332 shaderParams.dstOffset = static_cast<uint32_t>(params.dstOffset);
2333
2334 bool isSrcA2BGR10 =
2335 params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt2101010 ||
2336 params.srcFormat->vertexAttribType == gl::VertexAttribType::Int2101010;
2337 bool isSrcRGB10A2 =
2338 params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt1010102 ||
2339 params.srcFormat->vertexAttribType == gl::VertexAttribType::Int1010102;
2340
2341 shaderParams.isSrcHDR = isSrcA2BGR10 || isSrcRGB10A2;
2342 shaderParams.isSrcA2BGR10 = isSrcA2BGR10;
2343
2344 uint32_t flags = GetConvertVertexFlags(params);
2345
2346 // See GLES3.0 section 2.9.1 Transferring Array Elements
2347 const uint32_t srcValueBits = shaderParams.isSrcHDR ? 2 : shaderParams.Bs * 8;
2348 const uint32_t srcValueMask =
2349 srcValueBits == 32 ? 0xFFFFFFFFu : angle::BitMask<uint32_t>(srcValueBits);
2350 switch (flags)
2351 {
2352 case ConvertVertex_comp::kSintToSint:
2353 case ConvertVertex_comp::kSintToFloat:
2354 case ConvertVertex_comp::kUintToFloat:
2355 // For integers, alpha should take a value of 1.
2356 shaderParams.srcEmulatedAlpha = 1;
2357 break;
2358
2359 case ConvertVertex_comp::kUintToUint:
2360 // For integers, alpha should take a value of 1. However, uint->uint is also used to
2361 // add channels to RGB snorm, unorm and half formats.
2362 if (params.dstFormat->isSnorm())
2363 {
2364 // See case ConvertVertex_comp::kSnormToFloat below.
2365 shaderParams.srcEmulatedAlpha = srcValueMask >> 1;
2366 }
2367 else if (params.dstFormat->isUnorm())
2368 {
2369 // See case ConvertVertex_comp::kUnormToFloat below.
2370 shaderParams.srcEmulatedAlpha = srcValueMask;
2371 }
2372 else if (params.dstFormat->isVertexTypeHalfFloat())
2373 {
2374 shaderParams.srcEmulatedAlpha = gl::Float16One;
2375 }
2376 else
2377 {
2378 shaderParams.srcEmulatedAlpha = 1;
2379 }
2380 break;
2381
2382 case ConvertVertex_comp::kSnormToFloat:
2383 // The largest signed number with as many bits as the alpha channel of the source is
2384 // 0b011...1 which is srcValueMask >> 1
2385 shaderParams.srcEmulatedAlpha = srcValueMask >> 1;
2386 break;
2387
2388 case ConvertVertex_comp::kUnormToFloat:
2389 // The largest unsigned number with as many bits as the alpha channel of the source is
2390 // 0b11...1 which is srcValueMask
2391 shaderParams.srcEmulatedAlpha = srcValueMask;
2392 break;
2393
2394 case ConvertVertex_comp::kFixedToFloat:
2395 // 1.0 in fixed point is 0x10000
2396 shaderParams.srcEmulatedAlpha = 0x10000;
2397 break;
2398
2399 case ConvertVertex_comp::kFloatToFloat:
2400 ASSERT(ValidateFloatOneAsUint());
2401 shaderParams.srcEmulatedAlpha = gl::Float32One;
2402 break;
2403
2404 default:
2405 UNREACHABLE();
2406 }
2407
2408 return convertVertexBufferImpl(contextVk, dst, src, flags, commandBufferHelper, shaderParams,
2409 additionalOffsetVertexCounts);
2410 }
2411
convertVertexBufferImpl(ContextVk * contextVk,vk::BufferHelper * dst,vk::BufferHelper * src,uint32_t flags,vk::OutsideRenderPassCommandBufferHelper * commandBufferHelper,const ConvertVertexShaderParams & shaderParams,const OffsetAndVertexCounts & additionalOffsetVertexCounts)2412 angle::Result UtilsVk::convertVertexBufferImpl(
2413 ContextVk *contextVk,
2414 vk::BufferHelper *dst,
2415 vk::BufferHelper *src,
2416 uint32_t flags,
2417 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper,
2418 const ConvertVertexShaderParams &shaderParams,
2419 const OffsetAndVertexCounts &additionalOffsetVertexCounts)
2420 {
2421 ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk));
2422
2423 vk::OutsideRenderPassCommandBuffer *commandBuffer;
2424 commandBuffer = &commandBufferHelper->getCommandBuffer();
2425
2426 VkDescriptorSet descriptorSet;
2427 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::ConvertVertexBuffer,
2428 &descriptorSet));
2429
2430 // ConvertVertexBuffer writes whole 4 bytes to dstOffset. Caller must ensure dstOffset is
2431 // aligned on 4 bytes boundary.
2432 ASSERT(dst->getOffset() % 4 == 0);
2433
2434 VkWriteDescriptorSet writeInfo = {};
2435 VkDescriptorBufferInfo buffers[2] = {
2436 {dst->getBuffer().getHandle(), dst->getOffset(), dst->getSize()},
2437 {src->getBuffer().getHandle(), src->getOffset(), src->getSize()},
2438 };
2439 static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
2440 "Update write info");
2441
2442 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2443 writeInfo.dstSet = descriptorSet;
2444 writeInfo.dstBinding = kConvertVertexDestinationBinding;
2445 writeInfo.descriptorCount = 2;
2446 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
2447 writeInfo.pBufferInfo = buffers;
2448
2449 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
2450
2451 vk::ShaderModulePtr shader;
2452 ANGLE_TRY(contextVk->getShaderLibrary().getConvertVertex_comp(contextVk, flags, &shader));
2453
2454 ANGLE_TRY(setupComputeProgram(contextVk, Function::ConvertVertexBuffer, shader,
2455 &mConvertVertex[flags], descriptorSet, &shaderParams,
2456 sizeof(shaderParams), commandBufferHelper));
2457
2458 commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
2459
2460 if (!additionalOffsetVertexCounts.empty())
2461 {
2462 ConvertVertexShaderParams constants = shaderParams;
2463
2464 for (const OffsetAndVertexCount &offsetAndVertexCount : additionalOffsetVertexCounts)
2465 {
2466 // Total number of output components is simply the number of vertices by number of
2467 // components in each.
2468 constants.componentCount =
2469 static_cast<uint32_t>(offsetAndVertexCount.vertexCount * shaderParams.Nd);
2470 // Total number of 4-byte outputs is the number of components divided by how many
2471 // components can fit in a 4-byte value. Note that this value is also the invocation
2472 // size of the shader.
2473 constants.outputCount = UnsignedCeilDivide(constants.componentCount, shaderParams.Ed);
2474 constants.srcOffset = static_cast<uint32_t>(offsetAndVertexCount.srcOffset);
2475 constants.dstOffset = static_cast<uint32_t>(offsetAndVertexCount.dstOffset);
2476
2477 commandBuffer->pushConstants(*mPipelineLayouts[Function::ConvertVertexBuffer],
2478 VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(constants),
2479 &constants);
2480 // Since multiple compute dispatch all convert from the same srcBuffer and write to the
2481 // same dstBuffer, even if the ranges overlap, they should end up with writing the same
2482 // values, thus no barrier is needed here.
2483 commandBuffer->dispatch(UnsignedCeilDivide(constants.outputCount, 64), 1, 1);
2484 }
2485 }
2486
2487 return angle::Result::Continue;
2488 }
2489
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)2490 angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
2491 vk::ImageHelper *image,
2492 const vk::ImageView *imageView,
2493 const vk::RenderPassDesc &renderPassDesc,
2494 const gl::Rectangle &renderArea,
2495 const VkImageAspectFlags aspectFlags,
2496 const VkClearValue *clearValue,
2497 vk::RenderPassSource renderPassSource,
2498 vk::RenderPassCommandBuffer **commandBufferOut)
2499 {
2500 ASSERT(aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT ||
2501 (aspectFlags & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0);
2502 vk::ImageLayout imageLayout = aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT
2503 ? vk::ImageLayout::ColorWrite
2504 : vk::ImageLayout::DepthWriteStencilWrite;
2505 vk::Framebuffer framebuffer;
2506 vk::Framebuffer framebufferHandle;
2507 vk::RenderPassFramebuffer renderPassFramebuffer;
2508
2509 const uint32_t framebufferWidth = renderArea.x + renderArea.width;
2510 const uint32_t framebufferHeight = renderArea.y + renderArea.height;
2511 const uint32_t framebufferLayers = 1;
2512 vk::ImagelessFramebuffer imageless = vk::ImagelessFramebuffer::Yes;
2513
2514 if (!contextVk->getFeatures().preferDynamicRendering.enabled)
2515 {
2516 imageless = vk::ImagelessFramebuffer::No;
2517
2518 const vk::RenderPass *compatibleRenderPass = nullptr;
2519 ANGLE_TRY(contextVk->getCompatibleRenderPass(renderPassDesc, &compatibleRenderPass));
2520
2521 VkFramebufferCreateInfo framebufferInfo = {};
2522
2523 // Minimize the framebuffer coverage to only cover up to the render area.
2524 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2525 framebufferInfo.flags = 0;
2526 framebufferInfo.renderPass = compatibleRenderPass->getHandle();
2527 framebufferInfo.attachmentCount = 1;
2528 framebufferInfo.pAttachments = imageView->ptr();
2529 framebufferInfo.width = framebufferWidth;
2530 framebufferInfo.height = framebufferHeight;
2531 framebufferInfo.layers = framebufferLayers;
2532
2533 ANGLE_VK_TRY(contextVk, framebuffer.init(contextVk->getDevice(), framebufferInfo));
2534
2535 framebufferHandle.setHandle(framebuffer.getHandle());
2536 }
2537
2538 renderPassFramebuffer.setFramebuffer(
2539 contextVk, std::move(framebufferHandle), {imageView->getHandle()}, framebufferWidth,
2540 framebufferHeight, framebufferLayers, imageless, renderPassSource);
2541
2542 // If a clear value has been provided, the load op is set to clear.
2543 vk::AttachmentOpsArray renderPassAttachmentOps;
2544 vk::PackedClearValuesArray clearValues;
2545 VkClearValue attachmentClearValue = {};
2546
2547 if (clearValue == nullptr)
2548 {
2549 renderPassAttachmentOps.initWithLoadStore(vk::kAttachmentIndexZero, imageLayout,
2550 imageLayout);
2551 }
2552 else
2553 {
2554 attachmentClearValue = *clearValue;
2555 renderPassAttachmentOps.setLayouts(vk::kAttachmentIndexZero, imageLayout, imageLayout);
2556 renderPassAttachmentOps.setClearOp(vk::kAttachmentIndexZero);
2557 renderPassAttachmentOps.setClearStencilOp(vk::kAttachmentIndexZero);
2558 }
2559
2560 if (aspectFlags == VK_IMAGE_ASPECT_COLOR_BIT)
2561 {
2562 clearValues.storeColor(vk::kAttachmentIndexZero, attachmentClearValue);
2563 }
2564 else
2565 {
2566 clearValues.storeDepthStencil(vk::kAttachmentIndexZero, attachmentClearValue);
2567 }
2568
2569 ANGLE_TRY(contextVk->beginNewRenderPass(
2570 std::move(renderPassFramebuffer), renderArea, renderPassDesc, renderPassAttachmentOps,
2571 vk::PackedAttachmentCount(1), vk::kAttachmentIndexInvalid, clearValues, commandBufferOut));
2572
2573 contextVk->addGarbage(&framebuffer);
2574
2575 return angle::Result::Continue;
2576 }
2577
clearFramebuffer(ContextVk * contextVk,FramebufferVk * framebuffer,const ClearFramebufferParameters & params)2578 angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
2579 FramebufferVk *framebuffer,
2580 const ClearFramebufferParameters ¶ms)
2581 {
2582 vk::Renderer *renderer = contextVk->getRenderer();
2583
2584 ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
2585
2586 const gl::Rectangle &scissoredRenderArea = params.clearArea;
2587 vk::RenderPassCommandBuffer *commandBuffer;
2588
2589 // Start a new render pass if not already started
2590 if (contextVk->hasActiveRenderPass() &&
2591 contextVk->hasStartedRenderPassWithQueueSerial(framebuffer->getLastRenderPassQueueSerial()))
2592 {
2593 vk::RenderPassCommandBufferHelper *renderPassCommands =
2594 &contextVk->getStartedRenderPassCommands();
2595 renderPassCommands->growRenderArea(contextVk, scissoredRenderArea);
2596
2597 commandBuffer = &renderPassCommands->getCommandBuffer();
2598 }
2599 else
2600 {
2601 // Deferred clears should be handled already.
2602 ASSERT(!framebuffer->hasDeferredClears());
2603 ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer, nullptr));
2604 }
2605
2606 UpdateColorAccess(contextVk, framebuffer->getState().getColorAttachmentsMask(),
2607 MakeColorBufferMask(params.colorAttachmentIndexGL));
2608 UpdateDepthStencilAccess(contextVk, params.clearDepth, params.clearStencil);
2609
2610 ImageClearShaderParams shaderParams;
2611 shaderParams.clearValue = params.colorClearValue;
2612 shaderParams.clearDepth = params.depthStencilClearValue.depth;
2613
2614 vk::GraphicsPipelineDesc pipelineDesc;
2615 pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
2616 contextVk->pipelineRobustness(),
2617 contextVk->pipelineProtectedAccess());
2618 pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
2619 pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags);
2620 pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
2621 pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
2622 // Clears can be done on a currently open render pass, so make sure the correct subpass index is
2623 // used.
2624 pipelineDesc.setSubpass(contextVk->getCurrentSubpassIndex());
2625
2626 // Clear depth by enabling depth clamping and setting the viewport depth range to the clear
2627 // value if possible. Otherwise use the shader to export depth.
2628 const bool supportsDepthClamp = renderer->getPhysicalDeviceFeatures().depthClamp == VK_TRUE;
2629 if (params.clearDepth)
2630 {
2631 SetDepthStateForWrite(renderer, &pipelineDesc);
2632 if (supportsDepthClamp)
2633 {
2634 // Note: this path requires the depthClamp Vulkan feature.
2635 pipelineDesc.setDepthClampEnabled(true);
2636 }
2637 }
2638
2639 // Clear stencil by enabling stencil write with the right mask.
2640 if (params.clearStencil)
2641 {
2642 SetStencilStateForWrite(renderer, &pipelineDesc);
2643 }
2644
2645 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
2646 vk::ShaderModulePtr vertexShader;
2647 vk::ShaderModulePtr fragmentShader;
2648 GraphicsShaderProgramAndPipelines *imageClearProgramAndPipelines = &mImageClearVSOnly;
2649
2650 ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
2651 if (params.clearColor)
2652 {
2653 const uint32_t flags =
2654 GetImageClearFlags(*params.colorFormat, params.colorAttachmentIndexGL,
2655 params.clearDepth && !supportsDepthClamp);
2656 ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
2657 imageClearProgramAndPipelines = &mImageClear[flags];
2658 }
2659
2660 // Make sure transform feedback is paused. Needs to be done before binding the pipeline as
2661 // that's not allowed in Vulkan.
2662 const bool isTransformFeedbackActiveUnpaused =
2663 contextVk->getStartedRenderPassCommands().isTransformFeedbackActiveUnpaused();
2664 contextVk->pauseTransformFeedbackIfActiveUnpaused();
2665
2666 ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageClear, vertexShader, fragmentShader,
2667 imageClearProgramAndPipelines, &pipelineDesc, VK_NULL_HANDLE,
2668 &shaderParams, sizeof(shaderParams), commandBuffer));
2669
2670 // Set dynamic state
2671 VkViewport viewport;
2672 gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
2673 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
2674 bool clipSpaceOriginUpperLeft =
2675 contextVk->getState().getClipOrigin() == gl::ClipOrigin::UpperLeft;
2676 // Set depth range to clear value. If clearing depth, the vertex shader depth output is clamped
2677 // to this value, thus clearing the depth buffer to the desired clear value.
2678 const float clearDepthValue = params.depthStencilClearValue.depth;
2679 gl_vk::GetViewport(completeRenderArea, clearDepthValue, clearDepthValue, invertViewport,
2680 clipSpaceOriginUpperLeft, completeRenderArea.height, &viewport);
2681 commandBuffer->setViewport(0, 1, &viewport);
2682
2683 const VkRect2D scissor = gl_vk::GetRect(params.clearArea);
2684 commandBuffer->setScissor(0, 1, &scissor);
2685
2686 if (params.clearDepth)
2687 {
2688 SetDepthDynamicStateForWrite(renderer, commandBuffer);
2689 }
2690 else
2691 {
2692 SetDepthDynamicStateForUnused(renderer, commandBuffer);
2693 }
2694
2695 if (params.clearStencil)
2696 {
2697 constexpr uint8_t kCompareMask = 0xFF;
2698 const uint8_t clearStencilValue =
2699 static_cast<uint8_t>(params.depthStencilClearValue.stencil);
2700
2701 commandBuffer->setStencilCompareMask(kCompareMask, kCompareMask);
2702 commandBuffer->setStencilWriteMask(params.stencilMask, params.stencilMask);
2703 commandBuffer->setStencilReference(clearStencilValue, clearStencilValue);
2704
2705 SetStencilDynamicStateForWrite(renderer, commandBuffer);
2706 }
2707 else
2708 {
2709 SetStencilDynamicStateForUnused(renderer, commandBuffer);
2710 }
2711
2712 ASSERT(contextVk->hasStartedRenderPassWithQueueSerial(
2713 framebuffer->getLastRenderPassQueueSerial()));
2714 // Make sure this draw call doesn't count towards occlusion query results.
2715 contextVk->pauseRenderPassQueriesIfActive();
2716 commandBuffer->draw(3, 0);
2717 ANGLE_TRY(contextVk->resumeRenderPassQueriesIfActive());
2718
2719 // If transform feedback was active, we can't pause and resume it in the same render pass
2720 // because we can't insert a memory barrier for the counter buffers. In that case, break the
2721 // render pass.
2722 if (isTransformFeedbackActiveUnpaused)
2723 {
2724 ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
2725 RenderPassClosureReason::XfbResumeAfterDrawBasedClear));
2726 }
2727
2728 return angle::Result::Continue;
2729 }
2730
clearImage(ContextVk * contextVk,vk::ImageHelper * dst,const ClearImageParameters & params)2731 angle::Result UtilsVk::clearImage(ContextVk *contextVk,
2732 vk::ImageHelper *dst,
2733 const ClearImageParameters ¶ms)
2734 {
2735 vk::Renderer *renderer = contextVk->getRenderer();
2736
2737 ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
2738
2739 const angle::Format &dstActualFormat = dst->getActualFormat();
2740
2741 // Currently, this function is only used to clear emulated channels of color images.
2742 ASSERT(!dstActualFormat.hasDepthOrStencilBits());
2743
2744 // TODO: currently this function is only implemented for images that are drawable. If needed,
2745 // for images that are not drawable, the following algorithm can be used.
2746 //
2747 // - Copy image to temp buffer
2748 // - Use convertVertexBufferImpl to overwrite the alpha channel
2749 // - Copy the result back to the image
2750 //
2751 // Note that the following check is not enough; if the image is AHB-imported, then the draw path
2752 // cannot be taken if AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER hasn't been specified, even if the
2753 // format is renderable.
2754 //
2755 // http://anglebug.com/42264676
2756 if (!vk::FormatHasNecessaryFeature(renderer, dstActualFormat.id, dst->getTilingMode(),
2757 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
2758 {
2759 UNIMPLEMENTED();
2760 return angle::Result::Continue;
2761 }
2762
2763 vk::DeviceScoped<vk::ImageView> destView(contextVk->getDevice());
2764 const gl::TextureType destViewType = vk::Get2DTextureType(1, dst->getSamples());
2765
2766 ANGLE_TRY(dst->initLayerImageView(contextVk, destViewType, VK_IMAGE_ASPECT_COLOR_BIT,
2767 gl::SwizzleState(), &destView.get(), params.dstMip, 1,
2768 params.dstLayer, 1));
2769
2770 const gl::Rectangle &renderArea = params.clearArea;
2771
2772 ImageClearShaderParams shaderParams;
2773 shaderParams.clearValue = params.colorClearValue;
2774 shaderParams.clearDepth = 0;
2775
2776 vk::RenderPassDesc renderPassDesc;
2777 renderPassDesc.setSamples(dst->getSamples());
2778 renderPassDesc.packColorAttachment(0, dstActualFormat.id);
2779
2780 vk::GraphicsPipelineDesc pipelineDesc;
2781 pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
2782 contextVk->pipelineRobustness(),
2783 contextVk->pipelineProtectedAccess());
2784 pipelineDesc.setSingleColorWriteMask(0, params.colorMaskFlags);
2785 pipelineDesc.setRasterizationSamples(dst->getSamples());
2786 pipelineDesc.setRenderPassDesc(renderPassDesc);
2787
2788 vk::RenderPassCommandBuffer *commandBuffer;
2789 ANGLE_TRY(startRenderPass(contextVk, dst, &destView.get(), renderPassDesc, renderArea,
2790 VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
2791 vk::RenderPassSource::InternalUtils, &commandBuffer));
2792
2793 UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
2794
2795 contextVk->onImageRenderPassWrite(dst->toGLLevel(params.dstMip), params.dstLayer, 1,
2796 VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorWrite, dst);
2797
2798 const uint32_t flags = GetImageClearFlags(dstActualFormat, 0, false);
2799
2800 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
2801 vk::ShaderModulePtr vertexShader;
2802 vk::ShaderModulePtr fragmentShader;
2803 ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
2804 ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
2805
2806 ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageClear, vertexShader, fragmentShader,
2807 &mImageClear[flags], &pipelineDesc, VK_NULL_HANDLE,
2808 &shaderParams, sizeof(shaderParams), commandBuffer));
2809
2810 // Set dynamic state
2811 VkViewport viewport;
2812 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dst->getExtents().height, &viewport);
2813 commandBuffer->setViewport(0, 1, &viewport);
2814
2815 VkRect2D scissor = gl_vk::GetRect(renderArea);
2816 commandBuffer->setScissor(0, 1, &scissor);
2817
2818 SetDepthDynamicStateForUnused(renderer, commandBuffer);
2819 SetStencilDynamicStateForUnused(renderer, commandBuffer);
2820
2821 // Note: this utility creates its own framebuffer, thus bypassing ContextVk::startRenderPass.
2822 // As such, occlusion queries are not enabled.
2823 commandBuffer->draw(3, 0);
2824
2825 vk::ImageView destViewObject = destView.release();
2826 contextVk->addGarbage(&destViewObject);
2827
2828 // Close the render pass for this temporary framebuffer.
2829 return contextVk->flushCommandsAndEndRenderPass(
2830 RenderPassClosureReason::TemporaryForImageClear);
2831 }
2832
colorBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcView,const BlitResolveParameters & params)2833 angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk,
2834 FramebufferVk *framebuffer,
2835 vk::ImageHelper *src,
2836 const vk::ImageView *srcView,
2837 const BlitResolveParameters ¶ms)
2838 {
2839 // The views passed to this function are already retained, so a render pass cannot be already
2840 // open. Otherwise, this function closes the render pass, which may incur a vkQueueSubmit and
2841 // then the views are used in a new command buffer without having been retained for it.
2842 // http://crbug.com/1272266#c22
2843 //
2844 // Note that depth/stencil views for blit are not derived from a |Resource| class and are
2845 // retained differently.
2846 ASSERT(!contextVk->hasActiveRenderPass());
2847
2848 return blitResolveImpl(contextVk, framebuffer, src, srcView, nullptr, nullptr, params);
2849 }
2850
depthStencilBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)2851 angle::Result UtilsVk::depthStencilBlitResolve(ContextVk *contextVk,
2852 FramebufferVk *framebuffer,
2853 vk::ImageHelper *src,
2854 const vk::ImageView *srcDepthView,
2855 const vk::ImageView *srcStencilView,
2856 const BlitResolveParameters ¶ms)
2857 {
2858 return blitResolveImpl(contextVk, framebuffer, src, nullptr, srcDepthView, srcStencilView,
2859 params);
2860 }
2861
blitResolveImpl(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcColorView,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)2862 angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
2863 FramebufferVk *framebuffer,
2864 vk::ImageHelper *src,
2865 const vk::ImageView *srcColorView,
2866 const vk::ImageView *srcDepthView,
2867 const vk::ImageView *srcStencilView,
2868 const BlitResolveParameters ¶ms)
2869 {
2870 // Possible ways to resolve color are:
2871 //
2872 // - vkCmdResolveImage: This is by far the easiest method, but lacks the ability to flip
2873 // images during resolve.
2874 // - Manual resolve: A shader can read all samples from input, average them and output.
2875 // - Using subpass resolve attachment: A shader can transform the sample colors from source to
2876 // destination coordinates and the subpass resolve would finish the job.
2877 //
2878 // The first method is unable to handle flipping, so it's not generally applicable. The last
2879 // method would have been great were we able to modify the last render pass that rendered into
2880 // source, but still wouldn't be able to handle flipping. The second method is implemented in
2881 // this function for complete control.
2882
2883 // Possible ways to resolve depth/stencil are:
2884 //
2885 // - Manual resolve: A shader can read a samples from input and choose that for output.
2886 // - Using subpass resolve attachment through VkSubpassDescriptionDepthStencilResolveKHR: This
2887 // requires an extension that's not very well supported.
2888 //
2889 // The first method is implemented in this function.
2890
2891 // Possible ways to blit color, depth or stencil are:
2892 //
2893 // - vkCmdBlitImage: This function works if the source and destination formats have the blit
2894 // feature.
2895 // - Manual blit: A shader can sample from the source image and write it to the destination.
2896 //
2897 // The first method has a serious shortcoming. GLES allows blit parameters to exceed the
2898 // source or destination boundaries. The actual blit is clipped to these limits, but the
2899 // scaling applied is determined solely by the input areas. Vulkan requires the blit parameters
2900 // to be within the source and destination bounds. This makes it hard to keep the scaling
2901 // constant.
2902 //
2903 // The second method is implemented in this function, which shares code with the resolve method.
2904 vk::Renderer *renderer = contextVk->getRenderer();
2905
2906 ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
2907
2908 bool isResolve = src->getSamples() > 1;
2909
2910 BlitResolveShaderParams shaderParams;
2911 // Note: adjustments made for pre-rotatation in FramebufferVk::blit() affect these
2912 // Calculate*Offset() functions.
2913 if (isResolve)
2914 {
2915 CalculateResolveOffset(params, shaderParams.offset.resolve);
2916 }
2917 else
2918 {
2919 CalculateBlitOffset(params, shaderParams.offset.blit);
2920 }
2921 shaderParams.stretch[0] = params.stretch[0];
2922 shaderParams.stretch[1] = params.stretch[1];
2923 shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
2924 shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
2925 shaderParams.srcLayer = params.srcLayer;
2926 shaderParams.samples = src->getSamples();
2927 shaderParams.invSamples = 1.0f / shaderParams.samples;
2928 shaderParams.outputMask = framebuffer->getState().getEnabledDrawBuffers().bits();
2929 shaderParams.flipX = params.flipX;
2930 shaderParams.flipY = params.flipY;
2931 shaderParams.rotateXY = 0;
2932
2933 // Potentially make adjustments for pre-rotation. Depending on the angle some of the
2934 // shaderParams need to be adjusted.
2935 switch (params.rotation)
2936 {
2937 case SurfaceRotation::Identity:
2938 case SurfaceRotation::Rotated90Degrees:
2939 break;
2940 case SurfaceRotation::Rotated180Degrees:
2941 case SurfaceRotation::Rotated270Degrees:
2942 if (isResolve)
2943 {
2944 // Align the offset with minus 1, or the sample position near the edge will be
2945 // wrong.
2946 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0] - 1;
2947 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1] - 1;
2948 }
2949 else
2950 {
2951 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0];
2952 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1];
2953 }
2954 break;
2955 default:
2956 UNREACHABLE();
2957 break;
2958 }
2959
2960 shaderParams.rotateXY = IsRotatedAspectRatio(params.rotation);
2961
2962 bool blitColor = srcColorView != nullptr;
2963 bool blitDepth = srcDepthView != nullptr;
2964 bool blitStencil = srcStencilView != nullptr;
2965
2966 // Either color is blitted/resolved or depth/stencil, but not both.
2967 ASSERT(blitColor != (blitDepth || blitStencil));
2968
2969 // Linear sampling is only valid with color blitting.
2970 ASSERT((blitColor && !isResolve) || !params.linear);
2971
2972 uint32_t flags =
2973 GetBlitResolveFlags(blitColor, blitDepth, blitStencil, src->getIntendedFormat());
2974 flags |= src->getLayerCount() > 1 ? BlitResolve_frag::kSrcIsArray : 0;
2975 flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
2976 Function function = Function::BlitResolve;
2977
2978 // Note: a different shader is used for 3D color blits, but otherwise the desc sets, parameters
2979 // etc are identical.
2980 const bool isSrc3D = src->getType() == VK_IMAGE_TYPE_3D;
2981 ASSERT(!isSrc3D || (blitColor && !isResolve));
2982 if (isSrc3D)
2983 {
2984 flags = GetFormatFlags(src->getIntendedFormat(), Blit3DSrc_frag::kBlitInt,
2985 Blit3DSrc_frag::kBlitUint, Blit3DSrc_frag::kBlitFloat);
2986 }
2987
2988 vk::GraphicsPipelineDesc pipelineDesc;
2989 pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
2990 contextVk->pipelineRobustness(),
2991 contextVk->pipelineProtectedAccess());
2992 if (blitColor)
2993 {
2994 constexpr VkColorComponentFlags kAllColorComponents =
2995 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
2996 VK_COLOR_COMPONENT_A_BIT;
2997
2998 pipelineDesc.setColorWriteMasks(
2999 gl::BlendStateExt::ColorMaskStorage::GetReplicatedValue(
3000 kAllColorComponents, gl::BlendStateExt::ColorMaskStorage::GetMask(
3001 framebuffer->getRenderPassDesc().colorAttachmentRange())),
3002 framebuffer->getEmulatedAlphaAttachmentMask(), ~gl::DrawBufferMask());
3003 }
3004 else
3005 {
3006 pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
3007 }
3008 pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
3009 if (blitDepth)
3010 {
3011 SetDepthStateForWrite(renderer, &pipelineDesc);
3012 }
3013
3014 if (blitStencil)
3015 {
3016 SetStencilStateForWrite(renderer, &pipelineDesc);
3017 }
3018
3019 // All deferred clear must have been flushed, otherwise it will conflict with params.blitArea.
3020 ASSERT(!framebuffer->hasDeferredClears());
3021 vk::RenderPassCommandBuffer *commandBuffer;
3022 ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer, nullptr));
3023
3024 VkDescriptorSet descriptorSet;
3025 ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
3026 Function::BlitResolve, &descriptorSet));
3027
3028 // Pick layout consistent with GetImageReadLayout() to avoid unnecessary layout change.
3029 vk::ImageLayout srcImagelayout = src->isDepthOrStencil()
3030 ? vk::ImageLayout::DepthReadStencilReadFragmentShaderRead
3031 : vk::ImageLayout::FragmentShaderReadOnly;
3032 contextVk->onImageRenderPassRead(src->getAspectFlags(), srcImagelayout, src);
3033
3034 UpdateColorAccess(contextVk, framebuffer->getState().getColorAttachmentsMask(),
3035 framebuffer->getState().getEnabledDrawBuffers());
3036 UpdateDepthStencilAccess(contextVk, blitDepth, blitStencil);
3037
3038 VkDescriptorImageInfo imageInfos[2] = {};
3039
3040 if (blitColor)
3041 {
3042 imageInfos[0].imageView = srcColorView->getHandle();
3043 imageInfos[0].imageLayout = src->getCurrentLayout();
3044 }
3045 if (blitDepth)
3046 {
3047 imageInfos[0].imageView = srcDepthView->getHandle();
3048 imageInfos[0].imageLayout = src->getCurrentLayout();
3049 }
3050 if (blitStencil)
3051 {
3052 imageInfos[1].imageView = srcStencilView->getHandle();
3053 imageInfos[1].imageLayout = src->getCurrentLayout();
3054 }
3055
3056 VkDescriptorImageInfo samplerInfo = {};
3057 samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
3058
3059 VkWriteDescriptorSet writeInfos[3] = {};
3060 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3061 writeInfos[0].dstSet = descriptorSet;
3062 writeInfos[0].dstBinding = kBlitResolveColorOrDepthBinding;
3063 writeInfos[0].descriptorCount = 1;
3064 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3065 writeInfos[0].pImageInfo = &imageInfos[0];
3066
3067 writeInfos[1] = writeInfos[0];
3068 writeInfos[1].dstBinding = kBlitResolveStencilBinding;
3069 writeInfos[1].pImageInfo = &imageInfos[1];
3070
3071 writeInfos[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3072 writeInfos[2].dstSet = descriptorSet;
3073 writeInfos[2].dstBinding = kBlitResolveSamplerBinding;
3074 writeInfos[2].descriptorCount = 1;
3075 writeInfos[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
3076 writeInfos[2].pImageInfo = &samplerInfo;
3077
3078 // If resolving color, there's one write info; index 0
3079 // If resolving depth, write info index 0 must be written
3080 // If resolving stencil, write info index 1 must also be written
3081 //
3082 // Note again that resolving color and depth/stencil are mutually exclusive here.
3083 uint32_t writeInfoOffset = blitDepth || blitColor ? 0 : 1;
3084 uint32_t writeInfoCount = blitColor + blitDepth + blitStencil;
3085
3086 vkUpdateDescriptorSets(contextVk->getDevice(), writeInfoCount, writeInfos + writeInfoOffset, 0,
3087 nullptr);
3088 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfos[2], 0, nullptr);
3089
3090 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
3091 vk::ShaderModulePtr vertexShader;
3092 vk::ShaderModulePtr fragmentShader;
3093 ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
3094 if (isSrc3D)
3095 {
3096 ANGLE_TRY(shaderLibrary.getBlit3DSrc_frag(contextVk, flags, &fragmentShader));
3097 }
3098 else
3099 {
3100 ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
3101 }
3102
3103 ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
3104 isSrc3D ? &mBlit3DSrc[flags] : &mBlitResolve[flags],
3105 &pipelineDesc, descriptorSet, &shaderParams,
3106 sizeof(shaderParams), commandBuffer));
3107
3108 // Set dynamic state
3109 VkViewport viewport;
3110 gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
3111 gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, false, completeRenderArea.height,
3112 &viewport);
3113 commandBuffer->setViewport(0, 1, &viewport);
3114
3115 VkRect2D scissor = gl_vk::GetRect(params.blitArea);
3116 commandBuffer->setScissor(0, 1, &scissor);
3117
3118 if (blitDepth)
3119 {
3120 SetDepthDynamicStateForWrite(renderer, commandBuffer);
3121 }
3122 else
3123 {
3124 SetDepthDynamicStateForUnused(renderer, commandBuffer);
3125 }
3126
3127 if (blitStencil)
3128 {
3129 constexpr uint8_t kCompleteMask = 0xFF;
3130 constexpr uint8_t kUnusedReference = 0x00;
3131
3132 commandBuffer->setStencilCompareMask(kCompleteMask, kCompleteMask);
3133 commandBuffer->setStencilWriteMask(kCompleteMask, kCompleteMask);
3134 commandBuffer->setStencilReference(kUnusedReference, kUnusedReference);
3135
3136 SetStencilDynamicStateForWrite(renderer, commandBuffer);
3137 }
3138 else
3139 {
3140 SetStencilDynamicStateForUnused(renderer, commandBuffer);
3141 }
3142
3143 // Note: this utility starts the render pass directly, thus bypassing
3144 // ContextVk::startRenderPass. As such, occlusion queries are not enabled.
3145 commandBuffer->draw(3, 0);
3146
3147 // Don't allow this render pass to be reactivated by the user's draw call due to test flakiness
3148 // on win/intel bot.
3149 contextVk->disableRenderPassReactivation();
3150
3151 return angle::Result::Continue;
3152 }
3153
stencilBlitResolveNoShaderExport(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)3154 angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
3155 FramebufferVk *framebuffer,
3156 vk::ImageHelper *src,
3157 const vk::ImageView *srcStencilView,
3158 const BlitResolveParameters ¶ms)
3159 {
3160 vk::Renderer *renderer = contextVk->getRenderer();
3161
3162 // When VK_EXT_shader_stencil_export is not available, stencil is blitted/resolved into a
3163 // temporary buffer which is then copied into the stencil aspect of the image.
3164 ANGLE_TRY(ensureBlitResolveStencilNoExportResourcesInitialized(contextVk));
3165
3166 bool isResolve = src->getSamples() > 1;
3167
3168 // Create a temporary buffer to blit/resolve stencil into.
3169 vk::RendererScoped<vk::BufferHelper> blitBuffer(renderer);
3170
3171 uint32_t bufferRowLengthInUints = UnsignedCeilDivide(params.blitArea.width, sizeof(uint32_t));
3172 VkDeviceSize bufferSize = bufferRowLengthInUints * sizeof(uint32_t) * params.blitArea.height;
3173
3174 ANGLE_TRY(contextVk->initBufferAllocation(
3175 &blitBuffer.get(), renderer->getDeviceLocalMemoryTypeIndex(),
3176 static_cast<size_t>(bufferSize), renderer->getDefaultBufferAlignment(),
3177 BufferUsageType::Static));
3178
3179 BlitResolveStencilNoExportShaderParams shaderParams;
3180 // Note: adjustments made for pre-rotatation in FramebufferVk::blit() affect these
3181 // Calculate*Offset() functions.
3182 if (isResolve)
3183 {
3184 CalculateResolveOffset(params, shaderParams.offset.resolve);
3185 }
3186 else
3187 {
3188 CalculateBlitOffset(params, shaderParams.offset.blit);
3189 }
3190 shaderParams.stretch[0] = params.stretch[0];
3191 shaderParams.stretch[1] = params.stretch[1];
3192 shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
3193 shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
3194 shaderParams.srcLayer = params.srcLayer;
3195 shaderParams.srcWidth = params.srcExtents[0];
3196 shaderParams.srcHeight = params.srcExtents[1];
3197 shaderParams.dstPitch = bufferRowLengthInUints;
3198 shaderParams.blitArea[0] = params.blitArea.x;
3199 shaderParams.blitArea[1] = params.blitArea.y;
3200 shaderParams.blitArea[2] = params.blitArea.width;
3201 shaderParams.blitArea[3] = params.blitArea.height;
3202 shaderParams.flipX = params.flipX;
3203 shaderParams.flipY = params.flipY;
3204 shaderParams.rotateXY = 0;
3205
3206 // Potentially make adjustments for pre-rotatation. Depending on the angle some of the
3207 // shaderParams need to be adjusted.
3208 switch (params.rotation)
3209 {
3210 case SurfaceRotation::Identity:
3211 case SurfaceRotation::Rotated90Degrees:
3212 break;
3213 case SurfaceRotation::Rotated180Degrees:
3214 case SurfaceRotation::Rotated270Degrees:
3215 if (isResolve)
3216 {
3217 // Align the offset with minus 1, or the sample position near the edge will be
3218 // wrong.
3219 shaderParams.offset.resolve[0] += params.rotatedOffsetFactor[0] - 1;
3220 shaderParams.offset.resolve[1] += params.rotatedOffsetFactor[1] - 1;
3221 }
3222 else
3223 {
3224 shaderParams.offset.blit[0] += params.rotatedOffsetFactor[0];
3225 shaderParams.offset.blit[1] += params.rotatedOffsetFactor[1];
3226 }
3227 break;
3228 default:
3229 UNREACHABLE();
3230 break;
3231 }
3232
3233 shaderParams.rotateXY = IsRotatedAspectRatio(params.rotation);
3234
3235 // Linear sampling is only valid with color blitting.
3236 ASSERT(!params.linear);
3237
3238 uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0;
3239 flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
3240
3241 RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
3242 ASSERT(depthStencilRenderTarget != nullptr);
3243 vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImageForWrite();
3244
3245 // Change layouts prior to computation.
3246 vk::CommandBufferAccess access;
3247 access.onImageComputeShaderRead(src->getAspectFlags(), src);
3248 access.onImageTransferWrite(depthStencilRenderTarget->getLevelIndex(), 1,
3249 depthStencilRenderTarget->getLayerIndex(), 1,
3250 depthStencilImage->getAspectFlags(), depthStencilImage);
3251 access.onBufferComputeShaderWrite(&blitBuffer.get());
3252
3253 VkDescriptorSet descriptorSet;
3254 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3255 vk::OutsideRenderPassCommandBuffer *commandBuffer;
3256 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3257 commandBuffer = &commandBufferHelper->getCommandBuffer();
3258 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
3259 Function::BlitResolveStencilNoExport, &descriptorSet));
3260
3261 // Blit/resolve stencil into the buffer.
3262 VkDescriptorImageInfo imageInfo = {};
3263 imageInfo.imageView = srcStencilView->getHandle();
3264 imageInfo.imageLayout = src->getCurrentLayout();
3265
3266 VkDescriptorBufferInfo bufferInfo = {};
3267 bufferInfo.buffer = blitBuffer.get().getBuffer().getHandle();
3268 bufferInfo.offset = blitBuffer.get().getOffset();
3269 bufferInfo.range = blitBuffer.get().getSize();
3270
3271 VkDescriptorImageInfo samplerInfo = {};
3272 samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
3273
3274 VkWriteDescriptorSet writeInfos[3] = {};
3275 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3276 writeInfos[0].dstSet = descriptorSet;
3277 writeInfos[0].dstBinding = kBlitResolveStencilNoExportDestBinding;
3278 writeInfos[0].descriptorCount = 1;
3279 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3280 writeInfos[0].pBufferInfo = &bufferInfo;
3281
3282 writeInfos[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3283 writeInfos[1].dstSet = descriptorSet;
3284 writeInfos[1].dstBinding = kBlitResolveStencilNoExportSrcBinding;
3285 writeInfos[1].descriptorCount = 1;
3286 writeInfos[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3287 writeInfos[1].pImageInfo = &imageInfo;
3288
3289 writeInfos[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3290 writeInfos[2].dstSet = descriptorSet;
3291 writeInfos[2].dstBinding = kBlitResolveStencilNoExportSamplerBinding;
3292 writeInfos[2].descriptorCount = 1;
3293 writeInfos[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
3294 writeInfos[2].pImageInfo = &samplerInfo;
3295
3296 vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
3297
3298 vk::ShaderModulePtr shader;
3299 ANGLE_TRY(contextVk->getShaderLibrary().getBlitResolveStencilNoExport_comp(contextVk, flags,
3300 &shader));
3301
3302 ANGLE_TRY(setupComputeProgram(contextVk, Function::BlitResolveStencilNoExport, shader,
3303 &mBlitResolveStencilNoExport[flags], descriptorSet, &shaderParams,
3304 sizeof(shaderParams), commandBufferHelper));
3305 commandBuffer->dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
3306 UnsignedCeilDivide(params.blitArea.height, 8), 1);
3307
3308 // Add a barrier prior to copy.
3309 VkMemoryBarrier memoryBarrier = {};
3310 memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
3311 memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
3312 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
3313
3314 commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3315 VK_PIPELINE_STAGE_TRANSFER_BIT, memoryBarrier);
3316
3317 // Copy the resulting buffer into dst.
3318 VkBufferImageCopy region = {};
3319 region.bufferOffset = blitBuffer.get().getOffset();
3320 region.bufferRowLength = bufferRowLengthInUints * sizeof(uint32_t);
3321 region.bufferImageHeight = params.blitArea.height;
3322 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
3323 region.imageSubresource.mipLevel =
3324 depthStencilImage->toVkLevel(depthStencilRenderTarget->getLevelIndex()).get();
3325 region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex();
3326 region.imageSubresource.layerCount = 1;
3327 region.imageOffset.x = params.blitArea.x;
3328 region.imageOffset.y = params.blitArea.y;
3329 region.imageOffset.z = 0;
3330 region.imageExtent.width = params.blitArea.width;
3331 region.imageExtent.height = params.blitArea.height;
3332 region.imageExtent.depth = 1;
3333
3334 commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(),
3335 depthStencilImage->getImage(),
3336 depthStencilImage->getCurrentLayout(), 1, ®ion);
3337
3338 return angle::Result::Continue;
3339 }
3340
copyImage(ContextVk * contextVk,vk::ImageHelper * dst,const vk::ImageView * destView,vk::ImageHelper * src,const vk::ImageView * srcView,const CopyImageParameters & params)3341 angle::Result UtilsVk::copyImage(ContextVk *contextVk,
3342 vk::ImageHelper *dst,
3343 const vk::ImageView *destView,
3344 vk::ImageHelper *src,
3345 const vk::ImageView *srcView,
3346 const CopyImageParameters ¶ms)
3347 {
3348 vk::Renderer *renderer = contextVk->getRenderer();
3349
3350 // The views passed to this function are already retained, so a render pass cannot be already
3351 // open. Otherwise, this function closes the render pass, which may incur a vkQueueSubmit and
3352 // then the views are used in a new command buffer without having been retained for it.
3353 // http://crbug.com/1272266#c22
3354 ASSERT(!contextVk->hasActiveRenderPass());
3355
3356 const angle::Format &srcIntendedFormat = src->getIntendedFormat();
3357 const angle::Format &dstIntendedFormat = dst->getIntendedFormat();
3358
3359 const bool isYUV = src->getYcbcrConversionDesc().valid();
3360 const bool isSrcMultisampled = params.srcSampleCount > 1;
3361
3362 vk::SamplerDesc samplerDesc;
3363 if (isYUV)
3364 {
3365 samplerDesc = vk::SamplerDesc(contextVk, gl::SamplerState(), false,
3366 &src->getYcbcrConversionDesc(), srcIntendedFormat.id);
3367
3368 ANGLE_TRY(ensureImageCopyResourcesInitializedWithSampler(contextVk, samplerDesc));
3369 }
3370 else
3371 {
3372 ANGLE_TRY(ensureImageCopyResourcesInitialized(contextVk));
3373 }
3374
3375 ImageCopyShaderParams shaderParams;
3376 shaderParams.flipX = 0;
3377 shaderParams.flipY = params.srcFlipY || params.dstFlipY;
3378 shaderParams.premultiplyAlpha = params.srcPremultiplyAlpha;
3379 shaderParams.unmultiplyAlpha = params.srcUnmultiplyAlpha;
3380 shaderParams.dstHasLuminance = dstIntendedFormat.luminanceBits > 0;
3381 shaderParams.dstIsAlpha = dstIntendedFormat.isLUMA() && dstIntendedFormat.alphaBits > 0;
3382 shaderParams.dstDefaultChannelsMask =
3383 GetFormatDefaultChannelMask(dst->getIntendedFormat(), dst->getActualFormat());
3384 shaderParams.srcMip = params.srcMip;
3385 shaderParams.srcLayer = params.srcLayer;
3386 shaderParams.srcSampleCount = params.srcSampleCount;
3387 shaderParams.srcOffset[0] = params.srcOffset[0];
3388 shaderParams.srcOffset[1] = params.srcOffset[1];
3389 shaderParams.dstOffset[0] = params.dstOffset[0];
3390 shaderParams.dstOffset[1] = params.dstOffset[1];
3391 shaderParams.rotateXY = 0;
3392
3393 shaderParams.srcIsSRGB = params.srcColorEncoding == GL_SRGB;
3394 shaderParams.dstIsSRGB = params.dstColorEncoding == GL_SRGB;
3395
3396 // If both src and dst are sRGB, and there is no alpha multiplication/division necessary, then
3397 // the shader can work with sRGB data and pretend they are linear.
3398 if (shaderParams.srcIsSRGB && shaderParams.dstIsSRGB && !shaderParams.premultiplyAlpha &&
3399 !shaderParams.unmultiplyAlpha)
3400 {
3401 shaderParams.srcIsSRGB = false;
3402 shaderParams.dstIsSRGB = false;
3403 }
3404
3405 ASSERT(!(params.srcFlipY && params.dstFlipY));
3406 if (params.srcFlipY)
3407 {
3408 // If viewport is flipped, the shader expects srcOffset[1] to have the
3409 // last row's index instead of the first's.
3410 shaderParams.srcOffset[1] = params.srcHeight - params.srcOffset[1] - 1;
3411 }
3412 else if (params.dstFlipY)
3413 {
3414 // If image is flipped during copy, the shader uses the same code path as above,
3415 // with srcOffset being set to the last row's index instead of the first's.
3416 shaderParams.srcOffset[1] = params.srcOffset[1] + params.srcExtents[1] - 1;
3417 }
3418
3419 switch (params.srcRotation)
3420 {
3421 case SurfaceRotation::Identity:
3422 break;
3423 case SurfaceRotation::Rotated90Degrees:
3424 shaderParams.rotateXY = 1;
3425 break;
3426 case SurfaceRotation::Rotated180Degrees:
3427 shaderParams.flipX = true;
3428 ASSERT(shaderParams.flipY);
3429 shaderParams.flipY = false;
3430 shaderParams.srcOffset[0] += params.srcExtents[0];
3431 shaderParams.srcOffset[1] -= params.srcExtents[1];
3432 break;
3433 case SurfaceRotation::Rotated270Degrees:
3434 shaderParams.flipX = true;
3435 ASSERT(!shaderParams.flipY);
3436 shaderParams.flipY = true;
3437 shaderParams.srcOffset[0] += params.srcExtents[0];
3438 shaderParams.srcOffset[1] += params.srcExtents[1];
3439 shaderParams.rotateXY = 1;
3440 break;
3441 default:
3442 UNREACHABLE();
3443 break;
3444 }
3445
3446 vk::RenderPassDesc renderPassDesc;
3447 renderPassDesc.setSamples(dst->getSamples());
3448 renderPassDesc.packColorAttachment(0, dst->getActualFormatID());
3449
3450 vk::GraphicsPipelineDesc pipelineDesc;
3451 pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
3452 contextVk->pipelineRobustness(),
3453 contextVk->pipelineProtectedAccess());
3454 pipelineDesc.setRenderPassDesc(renderPassDesc);
3455 pipelineDesc.setRasterizationSamples(dst->getSamples());
3456
3457 gl::Rectangle renderArea;
3458 renderArea.x = params.dstOffset[0];
3459 renderArea.y = params.dstOffset[1];
3460 renderArea.width = params.srcExtents[0];
3461 renderArea.height = params.srcExtents[1];
3462 if ((params.srcRotation == SurfaceRotation::Rotated90Degrees) ||
3463 (params.srcRotation == SurfaceRotation::Rotated270Degrees))
3464 {
3465 // The surface is rotated 90/270 degrees. This changes the aspect ratio of the surface.
3466 std::swap(renderArea.width, renderArea.height);
3467 }
3468
3469 vk::RenderPassCommandBuffer *commandBuffer;
3470 ANGLE_TRY(startRenderPass(contextVk, dst, destView, renderPassDesc, renderArea,
3471 VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
3472 vk::RenderPassSource::InternalUtils, &commandBuffer));
3473
3474 VkDescriptorSet descriptorSet;
3475 if (isYUV)
3476 {
3477 ANGLE_TRY(allocateDescriptorSetForImageCopyWithSampler(
3478 contextVk, &contextVk->getStartedRenderPassCommands(), samplerDesc, &descriptorSet));
3479 }
3480 else
3481 {
3482 ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
3483 Function::ImageCopy, &descriptorSet));
3484 }
3485
3486 UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
3487
3488 // Change source layout inside render pass.
3489 contextVk->onImageRenderPassRead(VK_IMAGE_ASPECT_COLOR_BIT,
3490 vk::ImageLayout::FragmentShaderReadOnly, src);
3491 contextVk->onImageRenderPassWrite(params.dstMip, params.dstLayer, 1, VK_IMAGE_ASPECT_COLOR_BIT,
3492 vk::ImageLayout::ColorWrite, dst);
3493
3494 VkDescriptorImageInfo imageInfo = {};
3495 imageInfo.imageView = srcView->getHandle();
3496 imageInfo.imageLayout = src->getCurrentLayout();
3497
3498 VkWriteDescriptorSet writeInfo = {};
3499 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3500 writeInfo.dstSet = descriptorSet;
3501 writeInfo.dstBinding = kImageCopySourceBinding;
3502 writeInfo.descriptorCount = 1;
3503 writeInfo.descriptorType =
3504 isYUV ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3505 writeInfo.pImageInfo = &imageInfo;
3506
3507 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
3508
3509 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
3510 vk::ShaderModulePtr vertexShader;
3511 vk::ShaderModulePtr fragmentShader;
3512 ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
3513
3514 if (isYUV)
3515 {
3516 ASSERT(src->getType() == VK_IMAGE_TYPE_2D);
3517 ANGLE_TRY(shaderLibrary.getImageCopyFloat_frag(contextVk, ImageCopyFloat_frag::kSrcIsYUV,
3518 &fragmentShader));
3519 ANGLE_TRY(setupGraphicsProgramWithLayout(
3520 contextVk, *mImageCopyWithSamplerPipelineLayouts[samplerDesc], vertexShader,
3521 fragmentShader, &mImageCopyWithSampler[samplerDesc], &pipelineDesc, descriptorSet,
3522 &shaderParams, sizeof(shaderParams), commandBuffer));
3523 }
3524 else if (isSrcMultisampled)
3525 {
3526 ANGLE_TRY(shaderLibrary.getImageCopyFloat_frag(contextVk, ImageCopyFloat_frag::kSrcIs2DMS,
3527 &fragmentShader));
3528 ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageCopy, vertexShader, fragmentShader,
3529 &mImageCopyFloat, &pipelineDesc, descriptorSet,
3530 &shaderParams, sizeof(shaderParams), commandBuffer));
3531 }
3532 else
3533 {
3534 uint32_t flags = GetImageCopyFlags(srcIntendedFormat, dstIntendedFormat);
3535 if (src->getType() == VK_IMAGE_TYPE_3D)
3536 {
3537 flags |= ImageCopy_frag::kSrcIs3D;
3538 }
3539 else if (src->getLayerCount() > 1)
3540 {
3541 flags |= ImageCopy_frag::kSrcIs2DArray;
3542 }
3543 else
3544 {
3545 ASSERT(src->getType() == VK_IMAGE_TYPE_2D);
3546 flags |= ImageCopy_frag::kSrcIs2D;
3547 }
3548
3549 ANGLE_TRY(shaderLibrary.getImageCopy_frag(contextVk, flags, &fragmentShader));
3550 ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ImageCopy, vertexShader, fragmentShader,
3551 &mImageCopy[flags], &pipelineDesc, descriptorSet,
3552 &shaderParams, sizeof(shaderParams), commandBuffer));
3553 }
3554
3555 // Set dynamic state
3556 VkViewport viewport;
3557 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dst->getExtents().height, &viewport);
3558 commandBuffer->setViewport(0, 1, &viewport);
3559
3560 VkRect2D scissor = gl_vk::GetRect(renderArea);
3561 commandBuffer->setScissor(0, 1, &scissor);
3562
3563 SetDepthDynamicStateForUnused(renderer, commandBuffer);
3564 SetStencilDynamicStateForUnused(renderer, commandBuffer);
3565
3566 // Note: this utility creates its own framebuffer, thus bypassing ContextVk::startRenderPass.
3567 // As such, occlusion queries are not enabled.
3568 commandBuffer->draw(3, 0);
3569
3570 // Close the render pass for this temporary framebuffer.
3571 return contextVk->flushCommandsAndEndRenderPass(RenderPassClosureReason::TemporaryForImageCopy);
3572 }
3573
copyImageBits(ContextVk * contextVk,vk::ImageHelper * dst,vk::ImageHelper * src,const CopyImageBitsParameters & params)3574 angle::Result UtilsVk::copyImageBits(ContextVk *contextVk,
3575 vk::ImageHelper *dst,
3576 vk::ImageHelper *src,
3577 const CopyImageBitsParameters ¶ms)
3578 {
3579 vk::Renderer *renderer = contextVk->getRenderer();
3580
3581 // This function is used to copy the bit representation of an image to another, and is used to
3582 // support EXT_copy_image when a format is emulated. Currently, only RGB->RGBA emulation is
3583 // possible, and so this function is tailored to this specific kind of emulation.
3584 //
3585 // The copy can be done with various degrees of efficiency:
3586 //
3587 // - If the UINT reinterpretation format for src supports SAMPLED usage, texels can be read
3588 // directly from that. Otherwise vkCmdCopyImageToBuffer can be used and data then read from
3589 // the buffer.
3590 // - If the UINT reinterpretation format for dst supports STORAGE usage, texels can be written
3591 // directly to that. Otherwise conversion can be done to a buffer and then
3592 // vkCmdCopyBufferToImage used.
3593 //
3594 // This requires four different shaders. For simplicity, this function unconditionally copies
3595 // src to a temp buffer, transforms to another temp buffer and copies to the dst. No known
3596 // applications use EXT_copy_image on RGB formats, so no further optimization is currently
3597 // necessary.
3598 //
3599 // The conversion between buffers can be done with ConvertVertex.comp in UintToUint mode, so no
3600 // new shader is necessary. The srcEmulatedAlpha parameter is used to make sure the destination
3601 // alpha value is correct, if dst is RGBA.
3602
3603 // This path should only be necessary for when RGBA is used as fallback for RGB. No other
3604 // format which can be used with EXT_copy_image has a fallback.
3605 ASSERT(src->getIntendedFormat().blueBits > 0 && src->getIntendedFormat().alphaBits == 0);
3606 ASSERT(dst->getIntendedFormat().blueBits > 0 && dst->getIntendedFormat().alphaBits == 0);
3607
3608 const angle::Format &srcImageFormat = src->getActualFormat();
3609 const angle::Format &dstImageFormat = dst->getActualFormat();
3610
3611 // Create temporary buffers.
3612 vk::RendererScoped<vk::BufferHelper> srcBuffer(renderer);
3613 vk::RendererScoped<vk::BufferHelper> dstBuffer(renderer);
3614
3615 const uint32_t srcPixelBytes = srcImageFormat.pixelBytes;
3616 const uint32_t dstPixelBytes = dstImageFormat.pixelBytes;
3617
3618 const uint32_t totalPixelCount =
3619 params.copyExtents[0] * params.copyExtents[1] * params.copyExtents[2];
3620 // Note that buffer sizes are rounded up a multiple of uint size, as that the granularity in
3621 // which the compute shader accesses these buffers.
3622 const VkDeviceSize srcBufferSize =
3623 roundUpPow2<uint32_t>(srcPixelBytes * totalPixelCount, sizeof(uint32_t));
3624 const VkDeviceSize dstBufferSize =
3625 roundUpPow2<uint32_t>(dstPixelBytes * totalPixelCount, sizeof(uint32_t));
3626
3627 VkBufferCreateInfo bufferInfo = {};
3628 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
3629 bufferInfo.flags = 0;
3630 bufferInfo.size = srcBufferSize;
3631 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
3632 bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
3633 bufferInfo.queueFamilyIndexCount = 0;
3634 bufferInfo.pQueueFamilyIndices = nullptr;
3635
3636 ANGLE_TRY(srcBuffer.get().init(contextVk, bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
3637
3638 bufferInfo.size = dstBufferSize;
3639 bufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
3640
3641 ANGLE_TRY(dstBuffer.get().init(contextVk, bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
3642
3643 bool isSrc3D = src->getType() == VK_IMAGE_TYPE_3D;
3644 bool isDst3D = dst->getType() == VK_IMAGE_TYPE_3D;
3645
3646 // Change layouts prior to computation.
3647 vk::CommandBufferAccess access;
3648 access.onImageTransferRead(src->getAspectFlags(), src);
3649 access.onImageTransferWrite(params.dstLevel, 1, isDst3D ? 0 : params.dstOffset[2],
3650 isDst3D ? 1 : params.copyExtents[2], VK_IMAGE_ASPECT_COLOR_BIT,
3651 dst);
3652
3653 // srcBuffer is the destination of copyImageToBuffer() below.
3654 access.onBufferTransferWrite(&srcBuffer.get());
3655 access.onBufferComputeShaderWrite(&dstBuffer.get());
3656
3657 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3658 vk::OutsideRenderPassCommandBuffer *commandBuffer;
3659 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3660 commandBuffer = &commandBufferHelper->getCommandBuffer();
3661
3662 // Copy src into buffer, completely packed.
3663 VkBufferImageCopy srcRegion = {};
3664 srcRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3665 srcRegion.imageSubresource.mipLevel = src->toVkLevel(params.srcLevel).get();
3666 srcRegion.imageSubresource.baseArrayLayer = isSrc3D ? 0 : params.srcOffset[2];
3667 srcRegion.imageSubresource.layerCount = isSrc3D ? 1 : params.copyExtents[2];
3668 srcRegion.imageOffset.x = params.srcOffset[0];
3669 srcRegion.imageOffset.y = params.srcOffset[1];
3670 srcRegion.imageOffset.z = isSrc3D ? params.srcOffset[2] : 0;
3671 srcRegion.imageExtent.width = params.copyExtents[0];
3672 srcRegion.imageExtent.height = params.copyExtents[1];
3673 srcRegion.imageExtent.depth = isSrc3D ? params.copyExtents[2] : 1;
3674
3675 commandBuffer->copyImageToBuffer(src->getImage(), src->getCurrentLayout(),
3676 srcBuffer.get().getBuffer().getHandle(), 1, &srcRegion);
3677
3678 // Add a barrier prior to dispatch call.
3679 VkMemoryBarrier memoryBarrier = {};
3680 memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
3681 memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
3682 memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
3683
3684 commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
3685 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, memoryBarrier);
3686
3687 // Set up ConvertVertex shader to convert between the formats. Only the following three cases
3688 // are possible:
3689 //
3690 // - RGB -> RGBA: Ns = 3, Ss = src.pixelBytes,
3691 // Nd = 4, Sd = dst.pixelBytes, use srcEmulatedAlpha
3692 //
3693 // - RGBA -> RGBA: Ns = 3, Ss = src.pixelBytes,
3694 // Nd = 4, Sd = dst.pixelBytes, use srcEmulatedAlpha
3695 //
3696 // - RGBA -> RGB: Ns = 3, Ss = src.pixelBytes,
3697 // Nd = 3, Sd = dst.pixelBytes
3698 //
3699 // The trick here is with RGBA -> RGBA, where Ns is specified as 3, so that the emulated alpha
3700 // from source is not taken (as uint), but rather one is provided such that the destination
3701 // alpha would contain the correct emulated alpha.
3702 //
3703 ConvertVertexShaderParams shaderParams;
3704 shaderParams.Ns = 3;
3705 shaderParams.Bs = srcImageFormat.pixelBytes / srcImageFormat.channelCount;
3706 shaderParams.Ss = srcImageFormat.pixelBytes;
3707 shaderParams.Nd = dstImageFormat.channelCount;
3708 shaderParams.Bd = dstImageFormat.pixelBytes / dstImageFormat.channelCount;
3709 shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
3710 // The component size is expected to either be 1, 2 or 4 bytes.
3711 ASSERT(4 % shaderParams.Bs == 0);
3712 ASSERT(4 % shaderParams.Bd == 0);
3713 shaderParams.Es = 4 / shaderParams.Bs;
3714 shaderParams.Ed = 4 / shaderParams.Bd;
3715 // Total number of output components is simply the number of pixels by number of components in
3716 // each.
3717 shaderParams.componentCount = totalPixelCount * shaderParams.Nd;
3718 // Total number of 4-byte outputs is the number of components divided by how many components can
3719 // fit in a 4-byte value. Note that this value is also the invocation size of the shader.
3720 shaderParams.outputCount = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
3721 shaderParams.srcOffset = 0;
3722 shaderParams.dstOffset = 0;
3723 shaderParams.isSrcHDR = 0;
3724 shaderParams.isSrcA2BGR10 = 0;
3725
3726 // Due to the requirements of EXT_copy_image, the channel size of src and dst must be
3727 // identical. Usage of srcEmulatedAlpha relies on this as it's used to output an alpha value in
3728 // dst through the source.
3729 ASSERT(shaderParams.Bs == shaderParams.Bd);
3730
3731 // The following RGB formats are allowed in EXT_copy_image:
3732 //
3733 // - RGB32F, RGB32UI, RGB32I
3734 // - RGB16F, RGB16UI, RGB16I
3735 // - RGB8, RGB8_SNORM, SRGB8, RGB8UI, RGB8I
3736 //
3737 // The value of emulated alpha is:
3738 //
3739 // - 1 for all RGB*I and RGB*UI formats
3740 // - bit representation of 1.0f for RGB32F
3741 // - bit representation of half-float 1.0f for RGB16F
3742 // - 0xFF for RGB8 and SRGB8
3743 // - 0x7F for RGB8_SNORM
3744 if (dstImageFormat.isInt())
3745 {
3746 shaderParams.srcEmulatedAlpha = 1;
3747 }
3748 else if (dstImageFormat.isUnorm())
3749 {
3750 ASSERT(shaderParams.Bd == 1);
3751 shaderParams.srcEmulatedAlpha = 0xFF;
3752 }
3753 else if (dstImageFormat.isSnorm())
3754 {
3755 ASSERT(shaderParams.Bd == 1);
3756 shaderParams.srcEmulatedAlpha = 0x7F;
3757 }
3758 else if (shaderParams.Bd == 2)
3759 {
3760 ASSERT(dstImageFormat.isFloat());
3761 shaderParams.srcEmulatedAlpha = gl::Float16One;
3762 }
3763 else if (shaderParams.Bd == 4)
3764 {
3765 ASSERT(dstImageFormat.isFloat());
3766 ASSERT(ValidateFloatOneAsUint());
3767 shaderParams.srcEmulatedAlpha = gl::Float32One;
3768 }
3769 else
3770 {
3771 UNREACHABLE();
3772 }
3773
3774 // Use UintToUint conversion to preserve the bit pattern during transfer.
3775 const uint32_t flags = ConvertVertex_comp::kUintToUint;
3776 ANGLE_TRY(convertVertexBufferImpl(contextVk, &dstBuffer.get(), &srcBuffer.get(), flags,
3777 commandBufferHelper, shaderParams, {}));
3778
3779 // Add a barrier prior to copy.
3780 memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
3781 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
3782
3783 commandBuffer->memoryBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
3784 VK_PIPELINE_STAGE_TRANSFER_BIT, memoryBarrier);
3785
3786 // Copy buffer into dst. It's completely packed.
3787 VkBufferImageCopy dstRegion = {};
3788 dstRegion.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3789 dstRegion.imageSubresource.mipLevel = dst->toVkLevel(params.dstLevel).get();
3790 dstRegion.imageSubresource.baseArrayLayer = isDst3D ? 0 : params.dstOffset[2];
3791 dstRegion.imageSubresource.layerCount = isDst3D ? 1 : params.copyExtents[2];
3792 dstRegion.imageOffset.x = params.dstOffset[0];
3793 dstRegion.imageOffset.y = params.dstOffset[1];
3794 dstRegion.imageOffset.z = isDst3D ? params.dstOffset[2] : 0;
3795 dstRegion.imageExtent.width = params.copyExtents[0];
3796 dstRegion.imageExtent.height = params.copyExtents[1];
3797 dstRegion.imageExtent.depth = isDst3D ? params.copyExtents[2] : 1;
3798
3799 commandBuffer->copyBufferToImage(dstBuffer.get().getBuffer().getHandle(), dst->getImage(),
3800 dst->getCurrentLayout(), 1, &dstRegion);
3801
3802 return angle::Result::Continue;
3803 }
3804
copyImageToBuffer(ContextVk * contextVk,vk::BufferHelper * dst,vk::ImageHelper * src,const CopyImageToBufferParameters & params)3805 angle::Result UtilsVk::copyImageToBuffer(ContextVk *contextVk,
3806 vk::BufferHelper *dst,
3807 vk::ImageHelper *src,
3808 const CopyImageToBufferParameters ¶ms)
3809 {
3810 ANGLE_TRY(ensureCopyImageToBufferResourcesInitialized(contextVk));
3811
3812 const angle::Format &srcFormat = src->getActualFormat();
3813
3814 ASSERT(params.outputOffset % sizeof(uint32_t) == 0);
3815 ASSERT(params.outputPitch % sizeof(uint32_t) == 0);
3816
3817 CopyImageToBufferShaderParams shaderParams;
3818 shaderParams.srcOffset[0] = params.srcOffset[0];
3819 shaderParams.srcOffset[1] = params.srcOffset[1];
3820 shaderParams.srcDepth = params.srcLayer;
3821 shaderParams.reverseRowOrder = params.reverseRowOrder;
3822 shaderParams.size[0] = params.size[0];
3823 shaderParams.size[1] = params.size[1];
3824 shaderParams.outputOffset = static_cast<uint32_t>(params.outputOffset / sizeof(uint32_t));
3825 shaderParams.outputPitch = params.outputPitch / sizeof(uint32_t);
3826 shaderParams.isDstSnorm = params.outputFormat->isSnorm();
3827
3828 gl::SwizzleState swizzle;
3829 if (params.outputFormat->isBGRA())
3830 {
3831 swizzle.swizzleRed = GL_BLUE;
3832 swizzle.swizzleBlue = GL_RED;
3833 }
3834
3835 uint32_t flags = GetCopyImageToBufferFlags(srcFormat);
3836 gl::TextureType textureType;
3837 if (src->getType() == VK_IMAGE_TYPE_3D)
3838 {
3839 flags |= CopyImageToBuffer_comp::kSrcIs3D;
3840 textureType = gl::TextureType::_3D;
3841 }
3842 else
3843 {
3844 flags |= CopyImageToBuffer_comp::kSrcIs2D;
3845 textureType = gl::TextureType::_2D;
3846 }
3847
3848 // Don't decode to linear colorspace when copying an image
3849 angle::FormatID imageFormat = src->getActualFormatID();
3850 angle::FormatID linearFormat =
3851 src->getActualFormat().isSRGB ? ConvertToLinear(imageFormat) : imageFormat;
3852 ASSERT(linearFormat != angle::FormatID::NONE);
3853
3854 vk::DeviceScoped<vk::ImageView> srcView(contextVk->getDevice());
3855 ANGLE_TRY(src->initReinterpretedLayerImageView(
3856 contextVk, textureType, src->getAspectFlags(), swizzle, &srcView.get(), params.srcMip, 1,
3857 textureType == gl::TextureType::_2D ? params.srcLayer : 0, 1, VK_IMAGE_USAGE_SAMPLED_BIT,
3858 linearFormat));
3859
3860 vk::CommandBufferAccess access;
3861 access.onImageComputeShaderRead(src->getAspectFlags(), src);
3862 access.onBufferComputeShaderWrite(dst);
3863
3864 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3865 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3866
3867 vk::OutsideRenderPassCommandBuffer *commandBuffer;
3868 commandBuffer = &commandBufferHelper->getCommandBuffer();
3869
3870 VkDescriptorSet descriptorSet;
3871 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::CopyImageToBuffer,
3872 &descriptorSet));
3873
3874 VkDescriptorImageInfo imageInfo = {};
3875 imageInfo.imageView = srcView.get().getHandle();
3876 imageInfo.imageLayout = src->getCurrentLayout();
3877
3878 VkDescriptorBufferInfo bufferInfo = {};
3879 bufferInfo.buffer = dst->getBuffer().getHandle();
3880 bufferInfo.offset = dst->getOffset();
3881 bufferInfo.range = dst->getSize();
3882
3883 VkWriteDescriptorSet writeInfo[2] = {};
3884
3885 writeInfo[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3886 writeInfo[0].dstSet = descriptorSet;
3887 writeInfo[0].dstBinding = kCopyImageToBufferSourceBinding;
3888 writeInfo[0].descriptorCount = 1;
3889 writeInfo[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3890 writeInfo[0].pImageInfo = &imageInfo;
3891
3892 writeInfo[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
3893 writeInfo[1].dstSet = descriptorSet;
3894 writeInfo[1].dstBinding = kCopyImageToBufferDestinationBinding;
3895 writeInfo[1].descriptorCount = 1;
3896 writeInfo[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
3897 writeInfo[1].pBufferInfo = &bufferInfo;
3898
3899 vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfo, 0, nullptr);
3900
3901 vk::ShaderModulePtr shader;
3902 ANGLE_TRY(contextVk->getShaderLibrary().getCopyImageToBuffer_comp(contextVk, flags, &shader));
3903
3904 ANGLE_TRY(setupComputeProgram(contextVk, Function::CopyImageToBuffer, shader,
3905 &mCopyImageToBuffer[flags], descriptorSet, &shaderParams,
3906 sizeof(shaderParams), commandBufferHelper));
3907
3908 commandBuffer->dispatch(UnsignedCeilDivide(params.size[0], 8),
3909 UnsignedCeilDivide(params.size[1], 8), 1);
3910
3911 vk::ImageView srcViewObject = srcView.release();
3912 contextVk->addGarbage(&srcViewObject);
3913
3914 return angle::Result::Continue;
3915 }
3916
copyRgbToRgba(ContextVk * contextVk,const angle::Format & srcFormat,vk::BufferHelper * srcBuffer,uint32_t srcOffset,uint32_t pixelCount,vk::BufferHelper * dstBuffer)3917 angle::Result UtilsVk::copyRgbToRgba(ContextVk *contextVk,
3918 const angle::Format &srcFormat,
3919 vk::BufferHelper *srcBuffer,
3920 uint32_t srcOffset,
3921 uint32_t pixelCount,
3922 vk::BufferHelper *dstBuffer)
3923 {
3924 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
3925
3926 vk::CommandBufferAccess access;
3927 access.onBufferComputeShaderRead(srcBuffer);
3928 access.onBufferComputeShaderWrite(dstBuffer);
3929
3930 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
3931
3932 rx::UtilsVk::ConvertVertexShaderParams shaderParams;
3933 shaderParams.Ns = 3; // src channels
3934 shaderParams.Bs = 4; // src bytes per channel
3935 shaderParams.Ss = 12; // src stride
3936 shaderParams.Nd = 4; // dest channels
3937 shaderParams.Bd = 4; // dest bytes per channel
3938 shaderParams.Sd = 16; // dest stride
3939 shaderParams.Es = 4 / shaderParams.Bs;
3940 shaderParams.Ed = 4 / shaderParams.Bd;
3941 // Total number of output components is simply the number of pixels by number of components in
3942 // each.
3943 shaderParams.componentCount = pixelCount * shaderParams.Nd;
3944 // Total number of 4-byte outputs is the number of components divided by how many components can
3945 // fit in a 4-byte value. Note that this value is also the invocation size of the shader.
3946 shaderParams.outputCount = UnsignedCeilDivide(shaderParams.componentCount, shaderParams.Ed);
3947 shaderParams.srcOffset = srcOffset;
3948 shaderParams.dstOffset = 0;
3949 shaderParams.isSrcHDR = 0;
3950 shaderParams.isSrcA2BGR10 = 0;
3951
3952 uint32_t flags = 0;
3953 switch (srcFormat.id)
3954 {
3955 case angle::FormatID::R32G32B32_UINT:
3956 flags = ConvertVertex_comp::kUintToUint;
3957 shaderParams.srcEmulatedAlpha = 1;
3958 break;
3959 case angle::FormatID::R32G32B32_SINT:
3960 flags = ConvertVertex_comp::kSintToSint;
3961 shaderParams.srcEmulatedAlpha = 1;
3962 break;
3963 case angle::FormatID::R32G32B32_FLOAT:
3964 flags = ConvertVertex_comp::kFloatToFloat;
3965 shaderParams.srcEmulatedAlpha = gl::Float32One;
3966 break;
3967 default:
3968 UNREACHABLE();
3969 }
3970
3971 return convertVertexBufferImpl(contextVk, dstBuffer, srcBuffer, flags, commandBufferHelper,
3972 shaderParams, {});
3973 }
3974
GetEtcToBcFlags(const angle::Format & format)3975 uint32_t GetEtcToBcFlags(const angle::Format &format)
3976 {
3977 switch (format.id)
3978 {
3979 case angle::FormatID::ETC1_R8G8B8_UNORM_BLOCK:
3980 case angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK:
3981 case angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK:
3982 case angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK:
3983 case angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK:
3984 case angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK:
3985 case angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK:
3986 case angle::FormatID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK:
3987 return EtcToBc_comp::kEtcRgba8ToBC3;
3988 case angle::FormatID::EAC_R11_SNORM_BLOCK:
3989 case angle::FormatID::EAC_R11_UNORM_BLOCK:
3990 case angle::FormatID::EAC_R11G11_SNORM_BLOCK:
3991 case angle::FormatID::EAC_R11G11_UNORM_BLOCK:
3992 return EtcToBc_comp::kEtcRg11ToBC5;
3993 default:
3994 UNREACHABLE();
3995 return EtcToBc_comp::kEtcRgba8ToBC3;
3996 }
3997 }
3998
GetCompactibleUINTFormat(const angle::Format & format)3999 angle::FormatID GetCompactibleUINTFormat(const angle::Format &format)
4000 {
4001 ASSERT(format.pixelBytes == 8 || format.pixelBytes == 16);
4002 return format.pixelBytes != 8 ? angle::FormatID::R32G32B32A32_UINT
4003 : angle::FormatID::R32G32_UINT;
4004 }
4005
transCodeEtcToBc(ContextVk * contextVk,vk::BufferHelper * srcBuffer,vk::ImageHelper * dstImage,const VkBufferImageCopy * copyRegion)4006 angle::Result UtilsVk::transCodeEtcToBc(ContextVk *contextVk,
4007 vk::BufferHelper *srcBuffer,
4008 vk::ImageHelper *dstImage,
4009 const VkBufferImageCopy *copyRegion)
4010 {
4011 ANGLE_TRY(ensureTransCodeEtcToBcResourcesInitialized(contextVk));
4012 vk::Renderer *renderer = contextVk->getRenderer();
4013 const angle::Format &intendedFormat = dstImage->getIntendedFormat();
4014 vk::ContextScoped<vk::BufferViewHelper> bufferViewHelper(contextVk);
4015 const gl::InternalFormat &info =
4016 gl::GetSizedInternalFormatInfo(intendedFormat.glInternalFormat);
4017
4018 // According to GLES spec. Etc texture don't support 3D texture type.
4019 ASSERT(copyRegion->bufferRowLength % info.compressedBlockWidth == 0 &&
4020 copyRegion->bufferImageHeight % info.compressedBlockHeight == 0 &&
4021 copyRegion->imageExtent.depth == 1);
4022
4023 ASSERT(dstImage->getType() != VK_IMAGE_TYPE_1D && dstImage->getType() != VK_IMAGE_TYPE_3D);
4024
4025 GLuint sliceTexels = (copyRegion->bufferRowLength / info.compressedBlockWidth) *
4026 (copyRegion->bufferImageHeight / info.compressedBlockHeight);
4027 GLuint sliceSize = sliceTexels * intendedFormat.pixelBytes;
4028 GLuint texBufferSize = sliceSize * copyRegion->imageSubresource.layerCount;
4029
4030 // Make sure the texture buffer size not out of limit.
4031 // Usually the limit is more than 128M.
4032 ASSERT(
4033 texBufferSize <
4034 static_cast<GLuint>(renderer->getPhysicalDeviceProperties().limits.maxTexelBufferElements));
4035 const vk::BufferView *srcBufferView = nullptr;
4036 bufferViewHelper.get().init(renderer, 0, texBufferSize);
4037 ANGLE_TRY(bufferViewHelper.get().getView(
4038 contextVk, *srcBuffer, copyRegion->bufferOffset,
4039 renderer->getFormat(GetCompactibleUINTFormat(intendedFormat)), &srcBufferView));
4040
4041 vk::LevelIndex dstLevel =
4042 gl::LevelIndexWrapper<uint32_t>(copyRegion->imageSubresource.mipLevel);
4043
4044 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
4045 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper({}, &commandBufferHelper));
4046 const angle::Format &format = dstImage->getIntendedFormat();
4047 uint32_t flags = GetEtcToBcFlags(format);
4048 vk::ShaderModulePtr shader;
4049 ANGLE_TRY(contextVk->getShaderLibrary().getEtcToBc_comp(contextVk, flags, &shader));
4050
4051 vk::OutsideRenderPassCommandBuffer *commandBuffer;
4052 commandBuffer = &commandBufferHelper->getCommandBuffer();
4053
4054 // For BC format, shader need width and height to be multiple of four.
4055 uint32_t width = rx::roundUpPow2(copyRegion->imageExtent.width, 4u);
4056 uint32_t height = rx::roundUpPow2(copyRegion->imageExtent.height, 4u);
4057
4058 // push constants data
4059 EtcToBcShaderParams shaderParams = {};
4060 shaderParams.offsetX = static_cast<uint32_t>(copyRegion->imageOffset.x);
4061 shaderParams.offsetY = static_cast<uint32_t>(copyRegion->imageOffset.y);
4062 shaderParams.texelOffset = 0;
4063 shaderParams.width = width;
4064 shaderParams.height = height;
4065 shaderParams.alphaBits = format.alphaBits;
4066 shaderParams.isSigned = format.isSnorm();
4067 shaderParams.isEacRg = format.channelCount == 2; // EAC_RG11
4068
4069 VkBufferView bufferView = srcBufferView->getHandle();
4070 VkWriteDescriptorSet writeDescriptorSet[2] = {};
4071 writeDescriptorSet[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4072 writeDescriptorSet[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
4073 writeDescriptorSet[0].dstBinding = 0;
4074 writeDescriptorSet[0].pBufferInfo = nullptr;
4075 writeDescriptorSet[0].descriptorCount = 1;
4076 writeDescriptorSet[0].pTexelBufferView = &bufferView;
4077
4078 VkDescriptorImageInfo imageInfo = {};
4079 imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
4080 writeDescriptorSet[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4081 writeDescriptorSet[1].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4082 writeDescriptorSet[1].dstBinding = 1;
4083 writeDescriptorSet[1].pImageInfo = &imageInfo;
4084 writeDescriptorSet[1].descriptorCount = 1;
4085 // Due to limitation VUID-VkImageViewCreateInfo-image-07072, we have to copy layer by layer.
4086 for (uint32_t i = 0; i < copyRegion->imageSubresource.layerCount; ++i)
4087 {
4088 vk::DeviceScoped<vk::ImageView> scopedImageView(contextVk->getDevice());
4089 ANGLE_TRY(dstImage->initReinterpretedLayerImageView(
4090 contextVk, gl::TextureType::_2D, VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
4091 &scopedImageView.get(), dstLevel, 1, copyRegion->imageSubresource.baseArrayLayer + i, 1,
4092 VK_IMAGE_USAGE_STORAGE_BIT, GetCompactibleUINTFormat(intendedFormat)));
4093 imageInfo.imageView = scopedImageView.get().getHandle();
4094
4095 VkDescriptorSet descriptorSet;
4096 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::TransCodeEtcToBc,
4097 &descriptorSet));
4098 writeDescriptorSet[0].dstSet = descriptorSet;
4099 writeDescriptorSet[1].dstSet = descriptorSet;
4100 vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeDescriptorSet, 0, nullptr);
4101
4102 ANGLE_TRY(setupComputeProgram(contextVk, Function::TransCodeEtcToBc, shader,
4103 &mEtcToBc[flags], descriptorSet, &shaderParams,
4104 sizeof(shaderParams), commandBufferHelper));
4105
4106 // Work group size is 8 x 8 x 1
4107 commandBuffer->dispatch(UnsignedCeilDivide(width, 8), UnsignedCeilDivide(height, 8), 1);
4108 // Release temporary views
4109 vk::ImageView imageView = scopedImageView.release();
4110 contextVk->addGarbage(&imageView);
4111
4112 shaderParams.texelOffset += sliceTexels;
4113 }
4114 // Retain buffer view
4115 commandBufferHelper->retainResource(&bufferViewHelper.get());
4116 return angle::Result::Continue;
4117 }
4118
generateMipmap(ContextVk * contextVk,vk::ImageHelper * src,const vk::ImageView * srcLevelZeroView,vk::ImageHelper * dst,const GenerateMipmapDestLevelViews & destLevelViews,const vk::Sampler & sampler,const GenerateMipmapParameters & params)4119 angle::Result UtilsVk::generateMipmap(ContextVk *contextVk,
4120 vk::ImageHelper *src,
4121 const vk::ImageView *srcLevelZeroView,
4122 vk::ImageHelper *dst,
4123 const GenerateMipmapDestLevelViews &destLevelViews,
4124 const vk::Sampler &sampler,
4125 const GenerateMipmapParameters ¶ms)
4126 {
4127 ANGLE_TRY(ensureGenerateMipmapResourcesInitialized(contextVk));
4128
4129 const gl::Extents &srcExtents = src->getLevelExtents(vk::LevelIndex(params.srcLevel));
4130 ASSERT(srcExtents.depth == 1);
4131
4132 // Each workgroup processes a 64x64 tile of the image.
4133 constexpr uint32_t kPixelWorkgroupRatio = 64;
4134 const uint32_t workGroupX = UnsignedCeilDivide(srcExtents.width, kPixelWorkgroupRatio);
4135 const uint32_t workGroupY = UnsignedCeilDivide(srcExtents.height, kPixelWorkgroupRatio);
4136
4137 GenerateMipmapShaderParams shaderParams;
4138 shaderParams.invSrcExtent[0] = 1.0f / srcExtents.width;
4139 shaderParams.invSrcExtent[1] = 1.0f / srcExtents.height;
4140 shaderParams.levelCount = params.dstLevelCount;
4141
4142 uint32_t flags = GetGenerateMipmapFlags(contextVk, src->getActualFormat());
4143
4144 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
4145 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper({}, &commandBufferHelper));
4146
4147 VkDescriptorSet descriptorSet;
4148 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::GenerateMipmap,
4149 &descriptorSet));
4150
4151 VkDescriptorImageInfo destImageInfos[kGenerateMipmapMaxLevels] = {};
4152 for (uint32_t level = 0; level < kGenerateMipmapMaxLevels; ++level)
4153 {
4154 destImageInfos[level].imageView = destLevelViews[level]->getHandle();
4155 destImageInfos[level].imageLayout = dst->getCurrentLayout();
4156 }
4157
4158 VkDescriptorImageInfo srcImageInfo = {};
4159 srcImageInfo.imageView = srcLevelZeroView->getHandle();
4160 srcImageInfo.imageLayout = src->getCurrentLayout();
4161 srcImageInfo.sampler = sampler.getHandle();
4162
4163 VkWriteDescriptorSet writeInfos[2] = {};
4164 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4165 writeInfos[0].dstSet = descriptorSet;
4166 writeInfos[0].dstBinding = kGenerateMipmapDestinationBinding;
4167 writeInfos[0].descriptorCount = GetGenerateMipmapMaxLevels(contextVk);
4168 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4169 writeInfos[0].pImageInfo = destImageInfos;
4170
4171 writeInfos[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4172 writeInfos[1].dstSet = descriptorSet;
4173 writeInfos[1].dstBinding = kGenerateMipmapSourceBinding;
4174 writeInfos[1].descriptorCount = 1;
4175 writeInfos[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
4176 writeInfos[1].pImageInfo = &srcImageInfo;
4177
4178 vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
4179
4180 vk::ShaderModulePtr shader;
4181 ANGLE_TRY(contextVk->getShaderLibrary().getGenerateMipmap_comp(contextVk, flags, &shader));
4182
4183 // Note: onImageRead/onImageWrite is expected to be called by the caller. This avoids inserting
4184 // barriers between calls for each layer of the image.
4185 vk::OutsideRenderPassCommandBuffer *commandBuffer;
4186 commandBuffer = &commandBufferHelper->getCommandBuffer();
4187
4188 ANGLE_TRY(setupComputeProgram(contextVk, Function::GenerateMipmap, shader,
4189 &mGenerateMipmap[flags], descriptorSet, &shaderParams,
4190 sizeof(shaderParams), commandBufferHelper));
4191
4192 commandBuffer->dispatch(workGroupX, workGroupY, 1);
4193
4194 return angle::Result::Continue;
4195 }
4196
generateMipmapWithDraw(ContextVk * contextVk,vk::ImageHelper * image,const angle::FormatID actualFormatID,const bool isMipmapFiltered)4197 angle::Result UtilsVk::generateMipmapWithDraw(ContextVk *contextVk,
4198 vk::ImageHelper *image,
4199 const angle::FormatID actualFormatID,
4200 const bool isMipmapFiltered)
4201 {
4202 // This function only supports -
4203 // 1. color formats that support color attachment feature
4204 // 2. image is of type VK_IMAGE_TYPE_2D and is not MSAA
4205 ASSERT(image);
4206 ASSERT(image->getType() == VK_IMAGE_TYPE_2D && image->getSamples() == 1);
4207 const angle::Format &actualFormat = angle::Format::Get(actualFormatID);
4208 ASSERT(!actualFormat.hasDepthOrStencilBits());
4209 // TODO: the following check is not enough; if the image is AHB-imported, then the draw path
4210 // cannot be taken if AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER hasn't been specified, even if the
4211 // format is renderable.
4212 vk::Renderer *renderer = contextVk->getRenderer();
4213 ASSERT(vk::FormatHasNecessaryFeature(renderer, actualFormat.id, image->getTilingMode(),
4214 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT));
4215
4216 // Ensure required resources are initialized
4217 ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
4218
4219 uint32_t layerCount = image->getLayerCount();
4220 uint32_t levelCount = image->getLevelCount();
4221 GLint sampleCount = image->getSamples();
4222 gl::LevelIndex baseLevelGL = image->getFirstAllocatedLevel();
4223 vk::LevelIndex baseLevelVK = image->toVkLevel(baseLevelGL);
4224 vk::LevelIndex maxLevelVK = baseLevelVK + (levelCount - 1);
4225
4226 // Transition entire image to color attachment layout
4227 vk::CommandBufferAccess access;
4228 access.onImageDrawMipmapGenerationWrite(baseLevelGL, levelCount, 0, layerCount,
4229 VK_IMAGE_ASPECT_COLOR_BIT, image);
4230 vk::OutsideRenderPassCommandBuffer *outsideCommandBuffer;
4231 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &outsideCommandBuffer));
4232
4233 gl::TextureType textureType = vk::Get2DTextureType(layerCount, sampleCount);
4234 gl::SwizzleState swizzle = {};
4235 VkImageUsageFlags imageUsageFlags = image->getUsage();
4236
4237 // Setup shaders for draw
4238 uint32_t flags = GetBlitResolveFlags(true, false, false, actualFormat);
4239 flags |= layerCount > 1 ? BlitResolve_frag::kSrcIsArray : 0;
4240 Function function = Function::BlitResolve;
4241
4242 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
4243 vk::ShaderModulePtr vertexShader;
4244 vk::ShaderModulePtr fragmentShader;
4245 ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
4246 ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
4247
4248 // Setup blit shader parameters
4249 BlitResolveShaderParams shaderParams;
4250 shaderParams.offset.blit[0] = 0.0f;
4251 shaderParams.offset.blit[1] = 0.0f;
4252 shaderParams.stretch[0] = 1.0f;
4253 shaderParams.stretch[1] = 1.0f;
4254 shaderParams.samples = 1;
4255 shaderParams.invSamples = 1.0f;
4256 shaderParams.outputMask = 1;
4257 shaderParams.flipX = 0;
4258 shaderParams.flipY = 0;
4259 shaderParams.rotateXY = 0;
4260
4261 // Setup pipeline for draw
4262 vk::RenderPassDesc renderPassDesc;
4263 renderPassDesc.setSamples(sampleCount);
4264 renderPassDesc.packColorAttachment(0, actualFormatID);
4265
4266 vk::GraphicsPipelineDesc pipelineDesc;
4267 pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
4268 contextVk->pipelineRobustness(),
4269 contextVk->pipelineProtectedAccess());
4270 pipelineDesc.setSingleColorWriteMask(0, (VkColorComponentFlagBits::VK_COLOR_COMPONENT_R_BIT |
4271 VkColorComponentFlagBits::VK_COLOR_COMPONENT_G_BIT |
4272 VkColorComponentFlagBits::VK_COLOR_COMPONENT_B_BIT |
4273 VkColorComponentFlagBits::VK_COLOR_COMPONENT_A_BIT));
4274 pipelineDesc.setRasterizationSamples(sampleCount);
4275 pipelineDesc.setRenderPassDesc(renderPassDesc);
4276
4277 // Setup write descriptors
4278 VkDescriptorImageInfo imageInfos = {};
4279 imageInfos.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4280
4281 VkDescriptorImageInfo samplerInfo = {};
4282 samplerInfo.sampler = isMipmapFiltered ? mLinearSampler.getHandle() : mPointSampler.getHandle();
4283
4284 VkWriteDescriptorSet writeInfos[2] = {};
4285 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4286 writeInfos[0].dstBinding = kBlitResolveColorOrDepthBinding;
4287 writeInfos[0].descriptorCount = 1;
4288 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
4289 writeInfos[0].pImageInfo = &imageInfos;
4290
4291 writeInfos[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4292 writeInfos[1].dstBinding = kBlitResolveSamplerBinding;
4293 writeInfos[1].descriptorCount = 1;
4294 writeInfos[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
4295 writeInfos[1].pImageInfo = &samplerInfo;
4296
4297 // Setup for read barrier
4298 VkImageMemoryBarrier barrier = {};
4299 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
4300 barrier.image = image->getImage().getHandle();
4301 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4302 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
4303 barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
4304 barrier.subresourceRange.baseArrayLayer = 0;
4305 barrier.subresourceRange.layerCount = layerCount;
4306 barrier.subresourceRange.baseMipLevel = baseLevelVK.get();
4307 barrier.subresourceRange.levelCount = 1;
4308 barrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
4309 barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
4310 barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4311 barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
4312
4313 // Sample from mipLevel N and draw to mipLevel N+1
4314 for (vk::LevelIndex srcLevelVk = baseLevelVK; srcLevelVk < maxLevelVK;)
4315 {
4316 // Transition "srcLevel" of all layers to shader read only optimal layout
4317 outsideCommandBuffer = nullptr;
4318 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &outsideCommandBuffer));
4319
4320 barrier.subresourceRange.baseMipLevel = srcLevelVk.get();
4321 outsideCommandBuffer->imageBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
4322 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier);
4323
4324 // Update render area
4325 vk::LevelIndex dstLevelVk = srcLevelVk + 1;
4326 ASSERT(dstLevelVk <= baseLevelVK + levelCount);
4327 gl::Extents extents = image->getLevelExtents(dstLevelVk);
4328 gl::Rectangle renderArea = gl::Rectangle(0, 0, extents.width, extents.height);
4329 VkViewport viewport;
4330 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, renderArea.height, &viewport);
4331 VkRect2D scissor = gl_vk::GetRect(renderArea);
4332
4333 shaderParams.invSrcExtent[0] = 1.0f / renderArea.width;
4334 shaderParams.invSrcExtent[1] = 1.0f / renderArea.height;
4335
4336 // mipLevel N --> mipLevel N+1 must be done for each layer
4337 for (uint32_t currentLayer = 0; currentLayer < layerCount; currentLayer++)
4338 {
4339 // Create image views for currentLayer's srcLevelVk and dstLevelVk
4340 vk::ImageView srcImageView;
4341 ANGLE_TRY(image->initReinterpretedLayerImageView(
4342 contextVk, textureType, image->getAspectFlags(), swizzle, &srcImageView, srcLevelVk,
4343 1, currentLayer, 1, imageUsageFlags, actualFormatID));
4344
4345 vk::ImageView dstImageView;
4346 ANGLE_TRY(image->initReinterpretedLayerImageView(
4347 contextVk, textureType, image->getAspectFlags(), swizzle, &dstImageView, dstLevelVk,
4348 1, currentLayer, 1, imageUsageFlags, actualFormatID));
4349
4350 vk::RenderPassCommandBuffer *commandBuffer = nullptr;
4351 ANGLE_TRY(startRenderPass(contextVk, image, &dstImageView, renderPassDesc, renderArea,
4352 VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
4353 vk::RenderPassSource::InternalUtils, &commandBuffer));
4354
4355 UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
4356
4357 VkDescriptorSet descriptorSet;
4358 ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
4359 Function::BlitResolve, &descriptorSet));
4360
4361 // Update write descriptor info
4362 writeInfos[0].dstSet = descriptorSet;
4363 writeInfos[1].dstSet = descriptorSet;
4364 imageInfos.imageView = srcImageView.getHandle();
4365 vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
4366
4367 // Update layer index and create pipeline
4368 shaderParams.srcLayer = currentLayer;
4369 ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
4370 &mBlitResolve[flags], &pipelineDesc, descriptorSet,
4371 &shaderParams, sizeof(shaderParams), commandBuffer));
4372
4373 // Set dynamic state
4374 commandBuffer->setViewport(0, 1, &viewport);
4375 commandBuffer->setScissor(0, 1, &scissor);
4376 SetDepthDynamicStateForUnused(renderer, commandBuffer);
4377 SetStencilDynamicStateForUnused(renderer, commandBuffer);
4378
4379 // Note: this utility creates its own framebuffer, thus bypassing
4380 // ContextVk::startRenderPass. As such, occlusion queries are not enabled.
4381 commandBuffer->draw(3, 0);
4382
4383 contextVk->addGarbage(&srcImageView);
4384 contextVk->addGarbage(&dstImageView);
4385 }
4386
4387 // Close the render pass for this temporary framebuffer.
4388 ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
4389 RenderPassClosureReason::GenerateMipmapWithDraw));
4390
4391 srcLevelVk = dstLevelVk;
4392 }
4393
4394 // Transition the last mipLevel to shader read only optimal layout
4395 outsideCommandBuffer = nullptr;
4396 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer({}, &outsideCommandBuffer));
4397
4398 barrier.subresourceRange.baseMipLevel = maxLevelVK.get();
4399 outsideCommandBuffer->imageBarrier(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
4400 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, barrier);
4401
4402 // Update image's layout related state to shader read only optimal layout
4403 image->setCurrentImageLayout(renderer, vk::ImageLayout::FragmentShaderReadOnly);
4404
4405 return angle::Result::Continue;
4406 }
4407
unresolve(ContextVk * contextVk,const FramebufferVk * framebuffer,const UnresolveParameters & params)4408 angle::Result UtilsVk::unresolve(ContextVk *contextVk,
4409 const FramebufferVk *framebuffer,
4410 const UnresolveParameters ¶ms)
4411 {
4412 vk::Renderer *renderer = contextVk->getRenderer();
4413
4414 // Get attachment count and pointers to resolve images and views.
4415 gl::DrawBuffersArray<vk::ImageHelper *> colorSrc = {};
4416 gl::DrawBuffersArray<const vk::ImageView *> colorSrcView = {};
4417
4418 const vk::ImageView *depthSrcView = nullptr;
4419 const vk::ImageView *stencilSrcView = nullptr;
4420
4421 // The subpass that initializes the multisampled-render-to-texture attachments packs the
4422 // attachments that need to be unresolved, so the attachment indices of this subpass are not the
4423 // same. See InitializeUnresolveSubpass for details.
4424 vk::PackedAttachmentIndex colorIndexVk(0);
4425 for (size_t colorIndexGL : params.unresolveColorMask)
4426 {
4427 RenderTargetVk *colorRenderTarget = framebuffer->getColorDrawRenderTarget(colorIndexGL);
4428
4429 ASSERT(colorRenderTarget->hasResolveAttachment());
4430 ASSERT(colorRenderTarget->isImageTransient());
4431
4432 colorSrc[colorIndexVk.get()] = &colorRenderTarget->getResolveImageForRenderPass();
4433 ANGLE_TRY(
4434 colorRenderTarget->getResolveImageView(contextVk, &colorSrcView[colorIndexVk.get()]));
4435
4436 ++colorIndexVk;
4437 }
4438
4439 if (params.unresolveDepth || params.unresolveStencil)
4440 {
4441 RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
4442
4443 ASSERT(depthStencilRenderTarget->hasResolveAttachment());
4444 ASSERT(depthStencilRenderTarget->isImageTransient());
4445
4446 if (params.unresolveDepth)
4447 {
4448 ANGLE_TRY(depthStencilRenderTarget->getResolveDepthOrStencilImageView(
4449 contextVk, VK_IMAGE_ASPECT_DEPTH_BIT, &depthSrcView));
4450 }
4451
4452 if (params.unresolveStencil)
4453 {
4454 ANGLE_TRY(depthStencilRenderTarget->getResolveDepthOrStencilImageView(
4455 contextVk, VK_IMAGE_ASPECT_STENCIL_BIT, &stencilSrcView));
4456 }
4457 }
4458
4459 vk::GraphicsPipelineDesc pipelineDesc;
4460 pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
4461 contextVk->pipelineRobustness(),
4462 contextVk->pipelineProtectedAccess());
4463 pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
4464 pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
4465
4466 vk::RenderPassCommandBuffer *commandBuffer =
4467 &contextVk->getStartedRenderPassCommands().getCommandBuffer();
4468
4469 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
4470 vk::ShaderModulePtr vertexShader;
4471 ANGLE_TRY(shaderLibrary.getFullScreenTri_vert(contextVk, 0, &vertexShader));
4472
4473 // Set dynamic state
4474 VkViewport viewport;
4475 gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
4476 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
4477 bool clipSpaceOriginUpperLeft =
4478 contextVk->getState().getClipOrigin() == gl::ClipOrigin::UpperLeft;
4479 gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, clipSpaceOriginUpperLeft,
4480 completeRenderArea.height, &viewport);
4481 commandBuffer->setViewport(0, 1, &viewport);
4482
4483 VkRect2D scissor = gl_vk::GetRect(completeRenderArea);
4484 commandBuffer->setScissor(0, 1, &scissor);
4485
4486 // When VK_EXT_shader_stencil_export is enabled, the draw call can directly read from the
4487 // stencil buffer and export it. When disabled, a special path is taken after the main
4488 // unresolve draw call.
4489 const bool unresolveStencilWithShaderExport =
4490 params.unresolveStencil && contextVk->getFeatures().supportsShaderStencilExport.enabled;
4491
4492 const uint32_t colorAttachmentCount = colorIndexVk.get();
4493 const uint32_t depthStencilBindingCount =
4494 (params.unresolveDepth ? 1 : 0) + (unresolveStencilWithShaderExport ? 1 : 0);
4495 const uint32_t totalBindingCount = colorAttachmentCount + depthStencilBindingCount;
4496
4497 if (totalBindingCount > 0)
4498 {
4499 const Function function = static_cast<Function>(
4500 static_cast<uint32_t>(Function::Unresolve1Attachment) + totalBindingCount - 1);
4501
4502 ANGLE_TRY(ensureUnresolveResourcesInitialized(contextVk, function, totalBindingCount));
4503
4504 if (params.unresolveDepth)
4505 {
4506 SetDepthStateForWrite(renderer, &pipelineDesc);
4507 }
4508
4509 if (unresolveStencilWithShaderExport)
4510 {
4511 SetStencilStateForWrite(renderer, &pipelineDesc);
4512 }
4513
4514 VkDescriptorSet descriptorSet;
4515 ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
4516 function, &descriptorSet));
4517
4518 vk::FramebufferAttachmentArray<VkDescriptorImageInfo> inputImageInfo = {};
4519 uint32_t inputBindingIndex = 0;
4520
4521 if (unresolveStencilWithShaderExport)
4522 {
4523 inputImageInfo[inputBindingIndex].imageView = stencilSrcView->getHandle();
4524 inputImageInfo[inputBindingIndex].imageLayout =
4525 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4526 ++inputBindingIndex;
4527 }
4528 if (params.unresolveDepth)
4529 {
4530 inputImageInfo[inputBindingIndex].imageView = depthSrcView->getHandle();
4531 inputImageInfo[inputBindingIndex].imageLayout =
4532 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4533 ++inputBindingIndex;
4534 }
4535
4536 for (uint32_t attachmentIndex = 0; attachmentIndex < colorAttachmentCount;
4537 ++attachmentIndex)
4538 {
4539 inputImageInfo[inputBindingIndex].imageView =
4540 colorSrcView[attachmentIndex]->getHandle();
4541 inputImageInfo[inputBindingIndex].imageLayout =
4542 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4543 ++inputBindingIndex;
4544 }
4545
4546 VkWriteDescriptorSet writeInfo = {};
4547 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4548 writeInfo.dstSet = descriptorSet;
4549 writeInfo.dstBinding = 0;
4550 writeInfo.descriptorCount = totalBindingCount;
4551 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
4552 writeInfo.pImageInfo = inputImageInfo.data();
4553
4554 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
4555
4556 gl::DrawBuffersArray<UnresolveColorAttachmentType> colorAttachmentTypes;
4557 uint32_t flags = GetUnresolveFlags(colorAttachmentCount, colorSrc, params.unresolveDepth,
4558 unresolveStencilWithShaderExport, &colorAttachmentTypes);
4559
4560 vk::ShaderModulePtr &fragmentShader = mUnresolveFragShaders[flags];
4561 ANGLE_TRY(GetUnresolveFrag(contextVk, colorAttachmentCount, colorAttachmentTypes,
4562 params.unresolveDepth, params.unresolveStencil,
4563 &fragmentShader));
4564
4565 ANGLE_TRY(setupGraphicsProgram(contextVk, function, vertexShader, fragmentShader,
4566 &mUnresolve[flags], &pipelineDesc, descriptorSet, nullptr, 0,
4567 commandBuffer));
4568
4569 if (params.unresolveDepth)
4570 {
4571 SetDepthDynamicStateForWrite(renderer, commandBuffer);
4572 }
4573 else
4574 {
4575 SetDepthDynamicStateForUnused(renderer, commandBuffer);
4576 }
4577
4578 if (unresolveStencilWithShaderExport)
4579 {
4580 constexpr uint8_t kCompleteMask = 0xFF;
4581 constexpr uint8_t kUnusedReference = 0x00;
4582
4583 commandBuffer->setStencilCompareMask(kCompleteMask, kCompleteMask);
4584 commandBuffer->setStencilWriteMask(kCompleteMask, kCompleteMask);
4585 commandBuffer->setStencilReference(kUnusedReference, kUnusedReference);
4586
4587 SetStencilDynamicStateForWrite(renderer, commandBuffer);
4588 }
4589 else
4590 {
4591 SetStencilDynamicStateForUnused(renderer, commandBuffer);
4592 }
4593
4594 // This draw call is made before ContextVk gets a chance to start the occlusion query. As
4595 // such, occlusion queries are not enabled.
4596 commandBuffer->draw(3, 0);
4597 }
4598
4599 // If stencil needs to be unresolved, but stencil export is not supported, set each bit of
4600 // stencil by adjusting the mask and controlling the output with `discard;` in the shader. This
4601 // requires that the stencil is cleared to 0 beforehand.
4602 if (params.unresolveStencil && !unresolveStencilWithShaderExport)
4603 {
4604 ANGLE_TRY(ensureExportStencilResourcesInitialized(contextVk));
4605
4606 // Disable color and depth output, and only let stencil through.
4607 pipelineDesc.setColorWriteMasks(0, gl::DrawBufferMask(), gl::DrawBufferMask());
4608
4609 SetDepthStateForUnused(renderer, &pipelineDesc);
4610 SetStencilStateForWrite(renderer, &pipelineDesc);
4611
4612 vk::ShaderModulePtr exportStencilShader;
4613 ANGLE_TRY(shaderLibrary.getExportStencil_frag(contextVk, 0, &exportStencilShader));
4614
4615 // A new descriptor set is needed to match the layout of the ExportStencil program.
4616 VkDescriptorSet exportStencilDescriptorSet;
4617 ANGLE_TRY(allocateDescriptorSet(contextVk, &contextVk->getStartedRenderPassCommands(),
4618 Function::ExportStencil, &exportStencilDescriptorSet));
4619
4620 VkDescriptorImageInfo stencilImageInfo = {};
4621 stencilImageInfo.imageView = stencilSrcView->getHandle();
4622 stencilImageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
4623
4624 VkWriteDescriptorSet stencilWriteInfo = {};
4625 stencilWriteInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4626 stencilWriteInfo.dstSet = exportStencilDescriptorSet;
4627 stencilWriteInfo.dstBinding = 0;
4628 stencilWriteInfo.descriptorCount = 1;
4629 stencilWriteInfo.descriptorType = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
4630 stencilWriteInfo.pImageInfo = &stencilImageInfo;
4631
4632 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &stencilWriteInfo, 0, nullptr);
4633
4634 ANGLE_TRY(setupGraphicsProgram(contextVk, Function::ExportStencil, vertexShader,
4635 exportStencilShader, &mExportStencil, &pipelineDesc,
4636 exportStencilDescriptorSet, nullptr, 0, commandBuffer));
4637
4638 SetDepthDynamicStateForUnused(renderer, commandBuffer);
4639 SetStencilDynamicStateForWrite(renderer, commandBuffer);
4640
4641 constexpr uint8_t kCompareMask = 0xFF;
4642 constexpr uint8_t kReference = 0xFF;
4643 commandBuffer->setStencilCompareMask(kCompareMask, kCompareMask);
4644 commandBuffer->setStencilReference(kReference, kReference);
4645
4646 // Set each bit in a different draw call. This is not terribly efficient, but manages to
4647 // keep the transient multisampled stencil data on tile and avoids having to write it back
4648 // to memory / allocate memory for it.
4649 for (uint32_t bit = 0; bit < 8; ++bit)
4650 {
4651 const uint32_t writeMask = 1u << bit;
4652 commandBuffer->setStencilWriteMask(writeMask, writeMask);
4653
4654 ExportStencilShaderParams shaderParams;
4655 shaderParams.bit = bit;
4656
4657 commandBuffer->pushConstants(
4658 *mPipelineLayouts[Function::ExportStencil], VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4659 /*static_cast<uint32_t>*/ (sizeof(shaderParams)), &shaderParams);
4660
4661 commandBuffer->draw(3, 0);
4662 }
4663 }
4664
4665 return angle::Result::Continue;
4666 }
4667
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)4668 angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
4669 vk::BufferHelper *textWidgetsBuffer,
4670 vk::BufferHelper *graphWidgetsBuffer,
4671 vk::ImageHelper *font,
4672 const vk::ImageView *fontView,
4673 vk::ImageHelper *dst,
4674 const vk::ImageView *destView,
4675 const OverlayDrawParameters ¶ms)
4676 {
4677 vk::Renderer *renderer = contextVk->getRenderer();
4678
4679 ANGLE_TRY(ensureOverlayDrawResourcesInitialized(contextVk));
4680
4681 OverlayDrawShaderParams shaderParams;
4682 shaderParams.viewportSize[0] = dst->getExtents().width;
4683 shaderParams.viewportSize[1] = dst->getExtents().height;
4684 shaderParams.isText = false;
4685 shaderParams.rotateXY = params.rotateXY;
4686 if (params.rotateXY)
4687 {
4688 std::swap(shaderParams.viewportSize[0], shaderParams.viewportSize[1]);
4689 }
4690
4691 ASSERT(dst->getLevelCount() == 1 && dst->getLayerCount() == 1 &&
4692 dst->getFirstAllocatedLevel() == gl::LevelIndex(0));
4693
4694 vk::RenderPassDesc renderPassDesc;
4695 renderPassDesc.setSamples(1);
4696 renderPassDesc.packColorAttachment(0, dst->getActualFormatID());
4697
4698 vk::GraphicsPipelineDesc pipelineDesc;
4699 pipelineDesc.initDefaults(contextVk, vk::GraphicsPipelineSubset::Complete,
4700 contextVk->pipelineRobustness(),
4701 contextVk->pipelineProtectedAccess());
4702 pipelineDesc.setRenderPassDesc(renderPassDesc);
4703 pipelineDesc.setTopology(gl::PrimitiveMode::TriangleStrip);
4704 pipelineDesc.setSingleBlend(0, true, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_SRC_ALPHA,
4705 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
4706
4707 gl::Rectangle renderArea;
4708 renderArea.x = 0;
4709 renderArea.y = 0;
4710 renderArea.width = shaderParams.viewportSize[0];
4711 renderArea.height = shaderParams.viewportSize[1];
4712
4713 // A potential optimization is to reuse the already open render pass if it belongs to the
4714 // swapchain.
4715 vk::RenderPassCommandBuffer *commandBuffer;
4716 ANGLE_TRY(startRenderPass(contextVk, dst, destView, renderPassDesc, renderArea,
4717 VK_IMAGE_ASPECT_COLOR_BIT, nullptr,
4718 vk::RenderPassSource::DefaultFramebuffer, &commandBuffer));
4719
4720 vk::RenderPassCommandBufferHelper *commandBufferHelper =
4721 &contextVk->getStartedRenderPassCommands();
4722
4723 VkDescriptorSet descriptorSet;
4724 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper, Function::OverlayDraw,
4725 &descriptorSet));
4726
4727 UpdateColorAccess(contextVk, MakeColorBufferMask(0), MakeColorBufferMask(0));
4728
4729 commandBufferHelper->retainResource(textWidgetsBuffer);
4730 commandBufferHelper->retainResource(graphWidgetsBuffer);
4731 contextVk->onImageRenderPassRead(VK_IMAGE_ASPECT_COLOR_BIT,
4732 vk::ImageLayout::FragmentShaderReadOnly, font);
4733 contextVk->onImageRenderPassWrite(gl::LevelIndex(0), 0, 1, VK_IMAGE_ASPECT_COLOR_BIT,
4734 vk::ImageLayout::ColorWrite, dst);
4735
4736 VkDescriptorImageInfo imageInfo = {};
4737 imageInfo.imageView = fontView->getHandle();
4738 imageInfo.imageLayout = font->getCurrentLayout();
4739
4740 VkDescriptorBufferInfo bufferInfos[2] = {};
4741 bufferInfos[0].buffer = textWidgetsBuffer->getBuffer().getHandle();
4742 bufferInfos[0].offset = textWidgetsBuffer->getOffset();
4743 bufferInfos[0].range = textWidgetsBuffer->getSize();
4744
4745 bufferInfos[1].buffer = graphWidgetsBuffer->getBuffer().getHandle();
4746 bufferInfos[1].offset = graphWidgetsBuffer->getOffset();
4747 bufferInfos[1].range = graphWidgetsBuffer->getSize();
4748
4749 VkWriteDescriptorSet writeInfos[3] = {};
4750 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4751 writeInfos[0].dstSet = descriptorSet;
4752 writeInfos[0].dstBinding = kOverlayDrawTextWidgetsBinding;
4753 writeInfos[0].descriptorCount = 1;
4754 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
4755 writeInfos[0].pBufferInfo = &bufferInfos[0];
4756
4757 writeInfos[1] = writeInfos[0];
4758 writeInfos[1].dstBinding = kOverlayDrawGraphWidgetsBinding;
4759 writeInfos[1].pBufferInfo = &bufferInfos[1];
4760
4761 writeInfos[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4762 writeInfos[2].dstSet = descriptorSet;
4763 writeInfos[2].dstBinding = kOverlayDrawFontBinding;
4764 writeInfos[2].descriptorCount = 1;
4765 writeInfos[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
4766 writeInfos[2].pImageInfo = &imageInfo;
4767
4768 vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
4769
4770 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
4771 vk::ShaderModulePtr vertexShader;
4772 vk::ShaderModulePtr fragmentShader;
4773 ANGLE_TRY(shaderLibrary.getOverlayDraw_vert(contextVk, 0, &vertexShader));
4774 ANGLE_TRY(shaderLibrary.getOverlayDraw_frag(contextVk, 0, &fragmentShader));
4775
4776 ANGLE_TRY(setupGraphicsProgram(contextVk, Function::OverlayDraw, vertexShader, fragmentShader,
4777 &mOverlayDraw, &pipelineDesc, descriptorSet, nullptr, 0,
4778 commandBuffer));
4779
4780 // Set dynamic state
4781 VkViewport viewport;
4782 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dst->getExtents().height, &viewport);
4783 commandBuffer->setViewport(0, 1, &viewport);
4784
4785 VkRect2D scissor = gl_vk::GetRect(renderArea);
4786 commandBuffer->setScissor(0, 1, &scissor);
4787
4788 SetDepthDynamicStateForUnused(renderer, commandBuffer);
4789 SetStencilDynamicStateForUnused(renderer, commandBuffer);
4790
4791 // Draw all the graph widgets.
4792 if (params.graphWidgetCount > 0)
4793 {
4794 shaderParams.isText = false;
4795 commandBuffer->pushConstants(*mPipelineLayouts[Function::OverlayDraw],
4796 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4797 sizeof(shaderParams), &shaderParams);
4798 commandBuffer->drawInstanced(4, params.graphWidgetCount, 0);
4799 }
4800 // Draw all the text widgets.
4801 if (params.textWidgetCount > 0)
4802 {
4803 shaderParams.isText = true;
4804 commandBuffer->pushConstants(*mPipelineLayouts[Function::OverlayDraw],
4805 VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0,
4806 sizeof(shaderParams), &shaderParams);
4807 commandBuffer->drawInstanced(4, params.textWidgetCount, 0);
4808 }
4809
4810 // Overlay is always drawn as the last render pass before present. Automatically move the
4811 // layout to PresentSrc.
4812 contextVk->onColorDraw(gl::LevelIndex(0), 0, 1, dst, nullptr, {}, vk::PackedAttachmentIndex(0));
4813 if (contextVk->getFeatures().supportsPresentation.enabled &&
4814 !contextVk->getFeatures().preferDynamicRendering.enabled)
4815 {
4816 contextVk->getStartedRenderPassCommands().setImageOptimizeForPresent(dst);
4817 contextVk->finalizeImageLayout(dst, {});
4818 }
4819
4820 // Close the render pass for this temporary framebuffer.
4821 return contextVk->flushCommandsAndEndRenderPass(
4822 RenderPassClosureReason::TemporaryForOverlayDraw);
4823 }
4824
generateFragmentShadingRate(ContextVk * contextVk,vk::ImageHelper * shadingRateAttachmentImageHelper,vk::ImageViewHelper * shadingRateAttachmentImageViewHelper,const GenerateFragmentShadingRateParameters & shadingRateParameters)4825 angle::Result UtilsVk::generateFragmentShadingRate(
4826 ContextVk *contextVk,
4827 vk::ImageHelper *shadingRateAttachmentImageHelper,
4828 vk::ImageViewHelper *shadingRateAttachmentImageViewHelper,
4829 const GenerateFragmentShadingRateParameters &shadingRateParameters)
4830 {
4831 ANGLE_TRY(ensureGenerateFragmentShadingRateResourcesInitialized(contextVk));
4832
4833 // Each workgroup processes an 8x8 tile of the image.
4834 constexpr uint32_t kPixelWorkgroupSize = 8;
4835 const uint32_t workGroupX =
4836 UnsignedCeilDivide(shadingRateParameters.attachmentWidth, kPixelWorkgroupSize);
4837 const uint32_t workGroupY =
4838 UnsignedCeilDivide(shadingRateParameters.attachmentHeight, kPixelWorkgroupSize);
4839
4840 // Setup compute shader
4841 vk::OutsideRenderPassCommandBufferHelper *commandBufferHelper;
4842 vk::CommandBufferAccess access = {};
4843
4844 // Fragment shading rate image will always have 1 layer.
4845 access.onImageComputeShaderWrite(shadingRateAttachmentImageHelper->getFirstAllocatedLevel(),
4846 shadingRateAttachmentImageHelper->getLevelCount(), 0,
4847 shadingRateAttachmentImageHelper->getLayerCount(),
4848 shadingRateAttachmentImageHelper->getAspectFlags(),
4849 shadingRateAttachmentImageHelper);
4850 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBufferHelper(access, &commandBufferHelper));
4851 VkDescriptorSet descriptorSet;
4852 ANGLE_TRY(allocateDescriptorSet(contextVk, commandBufferHelper,
4853 Function::GenerateFragmentShadingRate, &descriptorSet));
4854 VkDescriptorImageInfo destShadingRateImage = {};
4855 destShadingRateImage.imageView =
4856 shadingRateAttachmentImageViewHelper->getFragmentShadingRateImageView().getHandle();
4857 destShadingRateImage.imageLayout = shadingRateAttachmentImageHelper->getCurrentLayout();
4858 destShadingRateImage.sampler = mPointSampler.getHandle();
4859 VkWriteDescriptorSet writeInfos[1] = {};
4860 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
4861 writeInfos[0].dstSet = descriptorSet;
4862 writeInfos[0].dstBinding = kGenerateFragmentShadingRateAttachmentBinding;
4863 writeInfos[0].descriptorCount = 1;
4864 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
4865 writeInfos[0].pImageInfo = &destShadingRateImage;
4866
4867 vkUpdateDescriptorSets(contextVk->getDevice(), 1, writeInfos, 0, nullptr);
4868
4869 vk::ShaderModulePtr computeShader;
4870 ANGLE_TRY(contextVk->getShaderLibrary().getGenerateFragmentShadingRate_comp(contextVk, 0,
4871 &computeShader));
4872
4873 // Record the command
4874 vk::OutsideRenderPassCommandBuffer *commandBuffer;
4875 commandBuffer = &commandBufferHelper->getCommandBuffer();
4876 ANGLE_TRY(setupComputeProgram(contextVk, Function::GenerateFragmentShadingRate, computeShader,
4877 &mGenerateFragmentShadingRateAttachment, descriptorSet,
4878 &shadingRateParameters, sizeof(shadingRateParameters),
4879 commandBufferHelper));
4880 commandBuffer->dispatch(workGroupX, workGroupY, 1);
4881 return angle::Result::Continue;
4882 }
4883
allocateDescriptorSetWithLayout(ContextVk * contextVk,vk::CommandBufferHelperCommon * commandBufferHelper,vk::DynamicDescriptorPool & descriptorPool,const vk::DescriptorSetLayout & descriptorSetLayout,VkDescriptorSet * descriptorSetOut)4884 angle::Result UtilsVk::allocateDescriptorSetWithLayout(
4885 ContextVk *contextVk,
4886 vk::CommandBufferHelperCommon *commandBufferHelper,
4887 vk::DynamicDescriptorPool &descriptorPool,
4888 const vk::DescriptorSetLayout &descriptorSetLayout,
4889 VkDescriptorSet *descriptorSetOut)
4890 {
4891 vk::DescriptorSetPointer descriptorSet;
4892
4893 ANGLE_TRY(descriptorPool.allocateDescriptorSet(contextVk, descriptorSetLayout, &descriptorSet));
4894
4895 // Retain the individual descriptorSet to the command buffer.
4896 commandBufferHelper->retainResource(descriptorSet.get());
4897
4898 *descriptorSetOut = descriptorSet->getDescriptorSet();
4899
4900 return angle::Result::Continue;
4901 }
4902
allocateDescriptorSet(ContextVk * contextVk,vk::CommandBufferHelperCommon * commandBufferHelper,Function function,VkDescriptorSet * descriptorSetOut)4903 angle::Result UtilsVk::allocateDescriptorSet(ContextVk *contextVk,
4904 vk::CommandBufferHelperCommon *commandBufferHelper,
4905 Function function,
4906 VkDescriptorSet *descriptorSetOut)
4907 {
4908 return allocateDescriptorSetWithLayout(
4909 contextVk, commandBufferHelper, mDescriptorPools[function],
4910 *mDescriptorSetLayouts[function][DescriptorSetIndex::Internal], descriptorSetOut);
4911 }
4912
allocateDescriptorSetForImageCopyWithSampler(ContextVk * contextVk,vk::CommandBufferHelperCommon * commandBufferHelper,const vk::SamplerDesc & samplerDesc,VkDescriptorSet * descriptorSetOut)4913 angle::Result UtilsVk::allocateDescriptorSetForImageCopyWithSampler(
4914 ContextVk *contextVk,
4915 vk::CommandBufferHelperCommon *commandBufferHelper,
4916 const vk::SamplerDesc &samplerDesc,
4917 VkDescriptorSet *descriptorSetOut)
4918 {
4919 return allocateDescriptorSetWithLayout(
4920 contextVk, commandBufferHelper, mImageCopyWithSamplerDescriptorPools[samplerDesc],
4921 *mImageCopyWithSamplerDescriptorSetLayouts[samplerDesc][DescriptorSetIndex::Internal],
4922 descriptorSetOut);
4923 }
4924
ClearFramebufferParameters()4925 UtilsVk::ClearFramebufferParameters::ClearFramebufferParameters()
4926 : clearColor(false),
4927 clearDepth(false),
4928 clearStencil(false),
4929 stencilMask(0),
4930 colorMaskFlags(0),
4931 colorAttachmentIndexGL(0),
4932 colorFormat(nullptr),
4933 colorClearValue{},
4934 depthStencilClearValue{}
4935 {}
4936
4937 // LineLoopHelper implementation.
LineLoopHelper(vk::Renderer * renderer)4938 LineLoopHelper::LineLoopHelper(vk::Renderer *renderer) {}
4939 LineLoopHelper::~LineLoopHelper() = default;
4940
getIndexBufferForDrawArrays(ContextVk * contextVk,uint32_t clampedVertexCount,GLint firstVertex,vk::BufferHelper ** bufferOut)4941 angle::Result LineLoopHelper::getIndexBufferForDrawArrays(ContextVk *contextVk,
4942 uint32_t clampedVertexCount,
4943 GLint firstVertex,
4944 vk::BufferHelper **bufferOut)
4945 {
4946 size_t allocateBytes = sizeof(uint32_t) * (static_cast<size_t>(clampedVertexCount) + 1);
4947 ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
4948 vk::MemoryHostVisibility::Visible));
4949 vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer();
4950 uint32_t *indices = reinterpret_cast<uint32_t *>(indexBuffer->getMappedMemory());
4951
4952 // Note: there could be an overflow in this addition.
4953 uint32_t unsignedFirstVertex = static_cast<uint32_t>(firstVertex);
4954 uint32_t vertexCount = (clampedVertexCount + unsignedFirstVertex);
4955 for (uint32_t vertexIndex = unsignedFirstVertex; vertexIndex < vertexCount; vertexIndex++)
4956 {
4957 *indices++ = vertexIndex;
4958 }
4959 *indices = unsignedFirstVertex;
4960
4961 // Since we are not using the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT flag when creating the
4962 // device memory in the StreamingBuffer, we always need to make sure we flush it after
4963 // writing.
4964 ANGLE_TRY(indexBuffer->flush(contextVk->getRenderer()));
4965
4966 *bufferOut = indexBuffer;
4967
4968 return angle::Result::Continue;
4969 }
4970
getIndexBufferForElementArrayBuffer(ContextVk * contextVk,BufferVk * elementArrayBufferVk,gl::DrawElementsType glIndexType,int indexCount,intptr_t elementArrayOffset,vk::BufferHelper ** bufferOut,uint32_t * indexCountOut)4971 angle::Result LineLoopHelper::getIndexBufferForElementArrayBuffer(ContextVk *contextVk,
4972 BufferVk *elementArrayBufferVk,
4973 gl::DrawElementsType glIndexType,
4974 int indexCount,
4975 intptr_t elementArrayOffset,
4976 vk::BufferHelper **bufferOut,
4977 uint32_t *indexCountOut)
4978 {
4979 if (glIndexType == gl::DrawElementsType::UnsignedByte ||
4980 contextVk->getState().isPrimitiveRestartEnabled())
4981 {
4982 ANGLE_TRACE_EVENT0("gpu.angle", "LineLoopHelper::getIndexBufferForElementArrayBuffer");
4983
4984 void *srcDataMapping = nullptr;
4985 ANGLE_TRY(elementArrayBufferVk->mapImpl(contextVk, GL_MAP_READ_BIT, &srcDataMapping));
4986 ANGLE_TRY(streamIndices(contextVk, glIndexType, indexCount,
4987 static_cast<const uint8_t *>(srcDataMapping) + elementArrayOffset,
4988 bufferOut, indexCountOut));
4989 ANGLE_TRY(elementArrayBufferVk->unmapImpl(contextVk));
4990 return angle::Result::Continue;
4991 }
4992
4993 *indexCountOut = indexCount + 1;
4994
4995 size_t unitSize = contextVk->getVkIndexTypeSize(glIndexType);
4996
4997 size_t allocateBytes = unitSize * (indexCount + 1) + 1;
4998 ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
4999 vk::MemoryHostVisibility::Visible));
5000 vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer();
5001
5002 vk::BufferHelper *sourceBuffer = &elementArrayBufferVk->getBuffer();
5003 VkDeviceSize sourceOffset =
5004 static_cast<VkDeviceSize>(elementArrayOffset) + sourceBuffer->getOffset();
5005 uint64_t unitCount = static_cast<VkDeviceSize>(indexCount);
5006 angle::FixedVector<VkBufferCopy, 2> copies = {
5007 {sourceOffset, indexBuffer->getOffset(), unitCount * unitSize},
5008 {sourceOffset, indexBuffer->getOffset() + unitCount * unitSize, unitSize},
5009 };
5010
5011 vk::CommandBufferAccess access;
5012 access.onBufferTransferWrite(indexBuffer);
5013 access.onBufferTransferRead(sourceBuffer);
5014
5015 vk::OutsideRenderPassCommandBuffer *commandBuffer;
5016 ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
5017
5018 commandBuffer->copyBuffer(sourceBuffer->getBuffer(), indexBuffer->getBuffer(),
5019 static_cast<uint32_t>(copies.size()), copies.data());
5020
5021 ANGLE_TRY(indexBuffer->flush(contextVk->getRenderer()));
5022
5023 *bufferOut = indexBuffer;
5024
5025 return angle::Result::Continue;
5026 }
5027
streamIndices(ContextVk * contextVk,gl::DrawElementsType glIndexType,GLsizei indexCount,const uint8_t * srcPtr,vk::BufferHelper ** bufferOut,uint32_t * indexCountOut)5028 angle::Result LineLoopHelper::streamIndices(ContextVk *contextVk,
5029 gl::DrawElementsType glIndexType,
5030 GLsizei indexCount,
5031 const uint8_t *srcPtr,
5032 vk::BufferHelper **bufferOut,
5033 uint32_t *indexCountOut)
5034 {
5035 size_t unitSize = contextVk->getVkIndexTypeSize(glIndexType);
5036
5037 uint32_t numOutIndices = indexCount + 1;
5038 if (contextVk->getState().isPrimitiveRestartEnabled())
5039 {
5040 numOutIndices = GetLineLoopWithRestartIndexCount(glIndexType, indexCount, srcPtr);
5041 }
5042 *indexCountOut = numOutIndices;
5043
5044 ANGLE_TRY(contextVk->initBufferForVertexConversion(
5045 &mDynamicIndexBuffer, unitSize * numOutIndices, vk::MemoryHostVisibility::Visible));
5046 vk::BufferHelper *indexBuffer = mDynamicIndexBuffer.getBuffer();
5047 uint8_t *indices = indexBuffer->getMappedMemory();
5048
5049 if (contextVk->getState().isPrimitiveRestartEnabled())
5050 {
5051 HandlePrimitiveRestart(contextVk, glIndexType, indexCount, srcPtr, indices);
5052 }
5053 else
5054 {
5055 if (contextVk->shouldConvertUint8VkIndexType(glIndexType))
5056 {
5057 // If vulkan doesn't support uint8 index types, we need to emulate it.
5058 VkIndexType indexType = contextVk->getVkIndexType(glIndexType);
5059 ASSERT(indexType == VK_INDEX_TYPE_UINT16);
5060 uint16_t *indicesDst = reinterpret_cast<uint16_t *>(indices);
5061 for (int i = 0; i < indexCount; i++)
5062 {
5063 indicesDst[i] = srcPtr[i];
5064 }
5065
5066 indicesDst[indexCount] = srcPtr[0];
5067 }
5068 else
5069 {
5070 memcpy(indices, srcPtr, unitSize * indexCount);
5071 memcpy(indices + unitSize * indexCount, srcPtr, unitSize);
5072 }
5073 }
5074
5075 ANGLE_TRY(indexBuffer->flush(contextVk->getRenderer()));
5076
5077 *bufferOut = indexBuffer;
5078
5079 return angle::Result::Continue;
5080 }
5081
streamIndicesIndirect(ContextVk * contextVk,gl::DrawElementsType glIndexType,vk::BufferHelper * srcIndexBuffer,vk::BufferHelper * srcIndirectBuffer,VkDeviceSize indirectBufferOffset,vk::BufferHelper ** dstIndexBufferOut,vk::BufferHelper ** dstIndirectBufferOut)5082 angle::Result LineLoopHelper::streamIndicesIndirect(ContextVk *contextVk,
5083 gl::DrawElementsType glIndexType,
5084 vk::BufferHelper *srcIndexBuffer,
5085 vk::BufferHelper *srcIndirectBuffer,
5086 VkDeviceSize indirectBufferOffset,
5087 vk::BufferHelper **dstIndexBufferOut,
5088 vk::BufferHelper **dstIndirectBufferOut)
5089 {
5090 size_t unitSize = contextVk->getVkIndexTypeSize(glIndexType);
5091 size_t allocateBytes = static_cast<size_t>(srcIndexBuffer->getSize() + unitSize);
5092
5093 if (contextVk->getState().isPrimitiveRestartEnabled())
5094 {
5095 // If primitive restart, new index buffer is 135% the size of the original index buffer. The
5096 // smallest lineloop with primitive restart is 3 indices (point 1, point 2 and restart
5097 // value) when converted to linelist becomes 4 vertices. Expansion of 4/3. Any larger
5098 // lineloops would have less overhead and require less extra space. Any incomplete
5099 // primitives can be dropped or left incomplete and thus not increase the size of the
5100 // destination index buffer. Since we don't know the number of indices being used we'll use
5101 // the size of the index buffer as allocated as the index count.
5102 size_t numInputIndices = static_cast<size_t>(srcIndexBuffer->getSize() / unitSize);
5103 size_t numNewInputIndices = ((numInputIndices * 4) / 3) + 1;
5104 allocateBytes = static_cast<size_t>(numNewInputIndices * unitSize);
5105 }
5106
5107 // Allocate buffer for results
5108 ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
5109 vk::MemoryHostVisibility::Visible));
5110 ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndirectBuffer,
5111 sizeof(VkDrawIndexedIndirectCommand),
5112 vk::MemoryHostVisibility::Visible));
5113
5114 vk::BufferHelper *dstIndexBuffer = mDynamicIndexBuffer.getBuffer();
5115 vk::BufferHelper *dstIndirectBuffer = mDynamicIndirectBuffer.getBuffer();
5116
5117 // Copy relevant section of the source into destination at allocated offset. Note that the
5118 // offset returned by allocate() above is in bytes. As is the indices offset pointer.
5119 UtilsVk::ConvertLineLoopIndexIndirectParameters params = {};
5120 params.indirectBufferOffset = static_cast<uint32_t>(indirectBufferOffset);
5121 params.dstIndirectBufferOffset = 0;
5122 params.srcIndexBufferOffset = 0;
5123 params.dstIndexBufferOffset = 0;
5124 params.indicesBitsWidth = static_cast<uint32_t>(unitSize * 8);
5125
5126 ANGLE_TRY(contextVk->getUtils().convertLineLoopIndexIndirectBuffer(
5127 contextVk, srcIndirectBuffer, srcIndexBuffer, dstIndirectBuffer, dstIndexBuffer, params));
5128
5129 mDynamicIndexBuffer.clearDirty();
5130 mDynamicIndirectBuffer.clearDirty();
5131
5132 *dstIndexBufferOut = dstIndexBuffer;
5133 *dstIndirectBufferOut = dstIndirectBuffer;
5134
5135 return angle::Result::Continue;
5136 }
5137
streamArrayIndirect(ContextVk * contextVk,size_t vertexCount,vk::BufferHelper * arrayIndirectBuffer,VkDeviceSize arrayIndirectBufferOffset,vk::BufferHelper ** dstIndexBufferOut,vk::BufferHelper ** dstIndexIndirectBufferOut)5138 angle::Result LineLoopHelper::streamArrayIndirect(ContextVk *contextVk,
5139 size_t vertexCount,
5140 vk::BufferHelper *arrayIndirectBuffer,
5141 VkDeviceSize arrayIndirectBufferOffset,
5142 vk::BufferHelper **dstIndexBufferOut,
5143 vk::BufferHelper **dstIndexIndirectBufferOut)
5144 {
5145 auto unitSize = sizeof(uint32_t);
5146 size_t allocateBytes = static_cast<size_t>((vertexCount + 1) * unitSize);
5147
5148 ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndexBuffer, allocateBytes,
5149 vk::MemoryHostVisibility::Visible));
5150 ANGLE_TRY(contextVk->initBufferForVertexConversion(&mDynamicIndirectBuffer,
5151 sizeof(VkDrawIndexedIndirectCommand),
5152 vk::MemoryHostVisibility::Visible));
5153
5154 vk::BufferHelper *dstIndexBuffer = mDynamicIndexBuffer.getBuffer();
5155 vk::BufferHelper *dstIndirectBuffer = mDynamicIndirectBuffer.getBuffer();
5156
5157 // Copy relevant section of the source into destination at allocated offset. Note that the
5158 // offset returned by allocate() above is in bytes. As is the indices offset pointer.
5159 UtilsVk::ConvertLineLoopArrayIndirectParameters params = {};
5160 params.indirectBufferOffset = static_cast<uint32_t>(arrayIndirectBufferOffset);
5161 params.dstIndirectBufferOffset = 0;
5162 params.dstIndexBufferOffset = 0;
5163
5164 ANGLE_TRY(contextVk->getUtils().convertLineLoopArrayIndirectBuffer(
5165 contextVk, arrayIndirectBuffer, dstIndirectBuffer, dstIndexBuffer, params));
5166
5167 mDynamicIndexBuffer.clearDirty();
5168 mDynamicIndirectBuffer.clearDirty();
5169
5170 *dstIndexBufferOut = dstIndexBuffer;
5171 *dstIndexIndirectBufferOut = dstIndirectBuffer;
5172
5173 return angle::Result::Continue;
5174 }
5175
release(ContextVk * contextVk)5176 void LineLoopHelper::release(ContextVk *contextVk)
5177 {
5178 mDynamicIndexBuffer.release(contextVk);
5179 mDynamicIndirectBuffer.release(contextVk);
5180 }
5181
destroy(vk::Renderer * renderer)5182 void LineLoopHelper::destroy(vk::Renderer *renderer)
5183 {
5184 mDynamicIndexBuffer.destroy(renderer);
5185 mDynamicIndirectBuffer.destroy(renderer);
5186 }
5187 } // namespace rx
5188