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 "libANGLE/renderer/vulkan/ContextVk.h"
13 #include "libANGLE/renderer/vulkan/FramebufferVk.h"
14 #include "libANGLE/renderer/vulkan/RenderTargetVk.h"
15 #include "libANGLE/renderer/vulkan/RendererVk.h"
16
17 namespace rx
18 {
19
20 namespace BufferUtils_comp = vk::InternalShader::BufferUtils_comp;
21 namespace ConvertVertex_comp = vk::InternalShader::ConvertVertex_comp;
22 namespace ImageClear_frag = vk::InternalShader::ImageClear_frag;
23 namespace ImageCopy_frag = vk::InternalShader::ImageCopy_frag;
24 namespace BlitResolve_frag = vk::InternalShader::BlitResolve_frag;
25 namespace BlitResolveStencilNoExport_comp = vk::InternalShader::BlitResolveStencilNoExport_comp;
26 namespace OverlayCull_comp = vk::InternalShader::OverlayCull_comp;
27 namespace OverlayDraw_comp = vk::InternalShader::OverlayDraw_comp;
28 namespace ConvertIndexIndirectLineLoop_comp = vk::InternalShader::ConvertIndexIndirectLineLoop_comp;
29
30 namespace
31 {
32 // All internal shaders assume there is only one descriptor set, indexed at 0
33 constexpr uint32_t kSetIndex = 0;
34
35 constexpr uint32_t kBufferClearOutputBinding = 0;
36 constexpr uint32_t kConvertIndexDestinationBinding = 0;
37 constexpr uint32_t kConvertVertexDestinationBinding = 0;
38 constexpr uint32_t kConvertVertexSourceBinding = 1;
39 constexpr uint32_t kImageCopySourceBinding = 0;
40 constexpr uint32_t kBlitResolveColorOrDepthBinding = 0;
41 constexpr uint32_t kBlitResolveStencilBinding = 1;
42 constexpr uint32_t kBlitResolveSamplerBinding = 2;
43 constexpr uint32_t kBlitResolveStencilNoExportDestBinding = 0;
44 constexpr uint32_t kBlitResolveStencilNoExportSrcBinding = 1;
45 constexpr uint32_t kBlitResolveStencilNoExportSamplerBinding = 2;
46 constexpr uint32_t kOverlayCullCulledWidgetsBinding = 0;
47 constexpr uint32_t kOverlayCullWidgetCoordsBinding = 1;
48 constexpr uint32_t kOverlayDrawOutputBinding = 0;
49 constexpr uint32_t kOverlayDrawTextWidgetsBinding = 1;
50 constexpr uint32_t kOverlayDrawGraphWidgetsBinding = 2;
51 constexpr uint32_t kOverlayDrawCulledWidgetsBinding = 3;
52 constexpr uint32_t kOverlayDrawFontBinding = 4;
53
GetBufferUtilsFlags(size_t dispatchSize,const vk::Format & format)54 uint32_t GetBufferUtilsFlags(size_t dispatchSize, const vk::Format &format)
55 {
56 uint32_t flags = dispatchSize % 64 == 0 ? BufferUtils_comp::kIsAligned : 0;
57 const angle::Format &bufferFormat = format.actualBufferFormat();
58
59 if (bufferFormat.isSint())
60 {
61 flags |= BufferUtils_comp::kIsSint;
62 }
63 else if (bufferFormat.isUint())
64 {
65 flags |= BufferUtils_comp::kIsUint;
66 }
67 else
68 {
69 flags |= BufferUtils_comp::kIsFloat;
70 }
71
72 return flags;
73 }
74
GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters & params)75 uint32_t GetConvertVertexFlags(const UtilsVk::ConvertVertexParameters ¶ms)
76 {
77 bool srcIsSint = params.srcFormat->isSint();
78 bool srcIsUint = params.srcFormat->isUint();
79 bool srcIsSnorm = params.srcFormat->isSnorm();
80 bool srcIsUnorm = params.srcFormat->isUnorm();
81 bool srcIsFixed = params.srcFormat->isFixed;
82 bool srcIsFloat = params.srcFormat->isFloat();
83 bool srcIsA2BGR10 =
84 params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt2101010 ||
85 params.srcFormat->vertexAttribType == gl::VertexAttribType::Int2101010;
86 bool srcIsRGB10A2 =
87 params.srcFormat->vertexAttribType == gl::VertexAttribType::UnsignedInt1010102 ||
88 params.srcFormat->vertexAttribType == gl::VertexAttribType::Int1010102;
89 bool srcIsHalfFloat = params.srcFormat->isVertexTypeHalfFloat();
90
91 bool destIsSint = params.destFormat->isSint();
92 bool destIsUint = params.destFormat->isUint();
93 bool destIsFloat = params.destFormat->isFloat();
94 bool destIsHalfFloat = params.destFormat->isVertexTypeHalfFloat();
95
96 // Assert on the types to make sure the shader supports its. These are based on
97 // ConvertVertex_comp::Conversion values.
98 ASSERT(!destIsSint || srcIsSint); // If destination is sint, src must be sint too
99 ASSERT(!destIsUint || srcIsUint); // If destination is uint, src must be uint too
100 ASSERT(!srcIsFixed || destIsFloat); // If source is fixed, dest must be float
101 ASSERT(srcIsHalfFloat == destIsHalfFloat); // Both src and dest are half float or neither
102
103 // One of each bool set must be true
104 ASSERT(srcIsSint || srcIsUint || srcIsSnorm || srcIsUnorm || srcIsFixed || srcIsFloat);
105 ASSERT(destIsSint || destIsUint || destIsFloat);
106
107 // We currently don't have any big-endian devices in the list of supported platforms. The
108 // shader is capable of supporting big-endian architectures, but the relevant flag (IsBigEndian)
109 // is not added to the build configuration file (to reduce binary size). If necessary, add
110 // IsBigEndian to ConvertVertex.comp.json and select the appropriate flag based on the
111 // endian-ness test here.
112 ASSERT(IsLittleEndian());
113
114 uint32_t flags = 0;
115
116 if (srcIsA2BGR10)
117 {
118 if (srcIsSint && destIsSint)
119 {
120 flags |= ConvertVertex_comp::kA2BGR10SintToSint;
121 }
122 else if (srcIsUint && destIsUint)
123 {
124 flags |= ConvertVertex_comp::kA2BGR10UintToUint;
125 }
126 else if (srcIsSint)
127 {
128 flags |= ConvertVertex_comp::kA2BGR10SintToFloat;
129 }
130 else if (srcIsUint)
131 {
132 flags |= ConvertVertex_comp::kA2BGR10UintToFloat;
133 }
134 else if (srcIsSnorm)
135 {
136 flags |= ConvertVertex_comp::kA2BGR10SnormToFloat;
137 }
138 else
139 {
140 UNREACHABLE();
141 }
142 }
143 else if (srcIsRGB10A2)
144 {
145 if (srcIsSint)
146 {
147 flags |= ConvertVertex_comp::kRGB10A2SintToFloat;
148 }
149 else if (srcIsUint)
150 {
151 flags |= ConvertVertex_comp::kRGB10A2UintToFloat;
152 }
153 else if (srcIsSnorm)
154 {
155 flags |= ConvertVertex_comp::kRGB10A2SnormToFloat;
156 }
157 else if (srcIsUnorm)
158 {
159 flags |= ConvertVertex_comp::kRGB10A2UnormToFloat;
160 }
161 else
162 {
163 UNREACHABLE();
164 }
165 }
166 else if (srcIsHalfFloat && destIsHalfFloat)
167 {
168 // Note that HalfFloat conversion uses the same shader as Uint.
169 flags |= ConvertVertex_comp::kUintToUint;
170 }
171 else if (srcIsSint && destIsSint)
172 {
173 flags |= ConvertVertex_comp::kSintToSint;
174 }
175 else if (srcIsUint && destIsUint)
176 {
177 flags |= ConvertVertex_comp::kUintToUint;
178 }
179 else if (srcIsSint)
180 {
181 flags |= ConvertVertex_comp::kSintToFloat;
182 }
183 else if (srcIsUint)
184 {
185 flags |= ConvertVertex_comp::kUintToFloat;
186 }
187 else if (srcIsSnorm)
188 {
189 flags |= ConvertVertex_comp::kSnormToFloat;
190 }
191 else if (srcIsUnorm)
192 {
193 flags |= ConvertVertex_comp::kUnormToFloat;
194 }
195 else if (srcIsFixed)
196 {
197 flags |= ConvertVertex_comp::kFixedToFloat;
198 }
199 else if (srcIsFloat)
200 {
201 flags |= ConvertVertex_comp::kFloatToFloat;
202 }
203 else
204 {
205 UNREACHABLE();
206 }
207
208 return flags;
209 }
210
GetImageClearFlags(const angle::Format & format,uint32_t attachmentIndex)211 uint32_t GetImageClearFlags(const angle::Format &format, uint32_t attachmentIndex)
212 {
213 constexpr uint32_t kAttachmentFlagStep =
214 ImageClear_frag::kAttachment1 - ImageClear_frag::kAttachment0;
215
216 static_assert(gl::IMPLEMENTATION_MAX_DRAW_BUFFERS == 8,
217 "ImageClear shader assumes maximum 8 draw buffers");
218 static_assert(
219 ImageClear_frag::kAttachment0 + 7 * kAttachmentFlagStep == ImageClear_frag::kAttachment7,
220 "ImageClear AttachmentN flag calculation needs correction");
221
222 uint32_t flags = ImageClear_frag::kAttachment0 + attachmentIndex * kAttachmentFlagStep;
223
224 if (format.isSint())
225 {
226 flags |= ImageClear_frag::kIsSint;
227 }
228 else if (format.isUint())
229 {
230 flags |= ImageClear_frag::kIsUint;
231 }
232 else
233 {
234 flags |= ImageClear_frag::kIsFloat;
235 }
236
237 return flags;
238 }
239
GetFormatFlags(const angle::Format & format,uint32_t intFlag,uint32_t uintFlag,uint32_t floatFlag)240 uint32_t GetFormatFlags(const angle::Format &format,
241 uint32_t intFlag,
242 uint32_t uintFlag,
243 uint32_t floatFlag)
244 {
245 if (format.isSint())
246 {
247 return intFlag;
248 }
249 if (format.isUint())
250 {
251 return uintFlag;
252 }
253 return floatFlag;
254 }
255
GetImageCopyFlags(const vk::Format & srcFormat,const vk::Format & dstFormat)256 uint32_t GetImageCopyFlags(const vk::Format &srcFormat, const vk::Format &dstFormat)
257 {
258 const angle::Format &srcIntendedFormat = srcFormat.intendedFormat();
259 const angle::Format &dstIntendedFormat = dstFormat.intendedFormat();
260
261 uint32_t flags = 0;
262
263 flags |= GetFormatFlags(srcIntendedFormat, ImageCopy_frag::kSrcIsSint,
264 ImageCopy_frag::kSrcIsUint, ImageCopy_frag::kSrcIsFloat);
265 flags |= GetFormatFlags(dstIntendedFormat, ImageCopy_frag::kDestIsSint,
266 ImageCopy_frag::kDestIsUint, ImageCopy_frag::kDestIsFloat);
267
268 return flags;
269 }
270
GetBlitResolveFlags(bool blitColor,bool blitDepth,bool blitStencil,const vk::Format & format)271 uint32_t GetBlitResolveFlags(bool blitColor,
272 bool blitDepth,
273 bool blitStencil,
274 const vk::Format &format)
275 {
276 if (blitColor)
277 {
278 const angle::Format &intendedFormat = format.intendedFormat();
279
280 return GetFormatFlags(intendedFormat, BlitResolve_frag::kBlitColorInt,
281 BlitResolve_frag::kBlitColorUint, BlitResolve_frag::kBlitColorFloat);
282 }
283
284 if (blitDepth)
285 {
286 if (blitStencil)
287 {
288 return BlitResolve_frag::kBlitDepthStencil;
289 }
290 else
291 {
292 return BlitResolve_frag::kBlitDepth;
293 }
294 }
295 else
296 {
297 return BlitResolve_frag::kBlitStencil;
298 }
299 }
300
GetConvertIndexIndirectLineLoopFlag(uint32_t indicesBitsWidth)301 uint32_t GetConvertIndexIndirectLineLoopFlag(uint32_t indicesBitsWidth)
302 {
303 switch (indicesBitsWidth)
304 {
305 case 8:
306 return ConvertIndexIndirectLineLoop_comp::kIs8Bits;
307 case 16:
308 return ConvertIndexIndirectLineLoop_comp::kIs16Bits;
309 case 32:
310 return ConvertIndexIndirectLineLoop_comp::kIs32Bits;
311 default:
312 UNREACHABLE();
313 return 0;
314 }
315 }
316
GetFormatDefaultChannelMask(const vk::Format & format)317 uint32_t GetFormatDefaultChannelMask(const vk::Format &format)
318 {
319 uint32_t mask = 0;
320
321 const angle::Format &intendedFormat = format.intendedFormat();
322 const angle::Format &imageFormat = format.actualImageFormat();
323
324 // Red can never be introduced due to format emulation (except for luma which is handled
325 // especially)
326 ASSERT(((intendedFormat.redBits > 0) == (imageFormat.redBits > 0)) || intendedFormat.isLUMA());
327 mask |= intendedFormat.greenBits == 0 && imageFormat.greenBits > 0 ? 2 : 0;
328 mask |= intendedFormat.blueBits == 0 && imageFormat.blueBits > 0 ? 4 : 0;
329 mask |= intendedFormat.alphaBits == 0 && imageFormat.alphaBits > 0 ? 8 : 0;
330
331 return mask;
332 }
333
334 // Calculate the transformation offset for blit/resolve. See BlitResolve.frag for details on how
335 // these values are derived.
CalculateBlitOffset(const UtilsVk::BlitResolveParameters & params,float offset[2])336 void CalculateBlitOffset(const UtilsVk::BlitResolveParameters ¶ms, float offset[2])
337 {
338 int srcOffsetFactorX = params.flipX ? -1 : 1;
339 int srcOffsetFactorY = params.flipY ? -1 : 1;
340
341 offset[0] = params.destOffset[0] * params.stretch[0] - params.srcOffset[0] * srcOffsetFactorX;
342 offset[1] = params.destOffset[1] * params.stretch[1] - params.srcOffset[1] * srcOffsetFactorY;
343 }
344
CalculateResolveOffset(const UtilsVk::BlitResolveParameters & params,int32_t offset[2])345 void CalculateResolveOffset(const UtilsVk::BlitResolveParameters ¶ms, int32_t offset[2])
346 {
347 int srcOffsetFactorX = params.flipX ? -1 : 1;
348 int srcOffsetFactorY = params.flipY ? -1 : 1;
349
350 // There's no stretching in resolve.
351 offset[0] = params.destOffset[0] - params.srcOffset[0] * srcOffsetFactorX;
352 offset[1] = params.destOffset[1] - params.srcOffset[1] * srcOffsetFactorY;
353 }
354 } // namespace
355
356 UtilsVk::ConvertVertexShaderParams::ConvertVertexShaderParams() = default;
357
358 UtilsVk::ImageCopyShaderParams::ImageCopyShaderParams() = default;
359
360 UtilsVk::UtilsVk() = default;
361
362 UtilsVk::~UtilsVk() = default;
363
destroy(VkDevice device)364 void UtilsVk::destroy(VkDevice device)
365 {
366 for (Function f : angle::AllEnums<Function>())
367 {
368 for (auto &descriptorSetLayout : mDescriptorSetLayouts[f])
369 {
370 descriptorSetLayout.reset();
371 }
372 mPipelineLayouts[f].reset();
373 mDescriptorPools[f].destroy(device);
374 }
375
376 for (vk::ShaderProgramHelper &program : mBufferUtilsPrograms)
377 {
378 program.destroy(device);
379 }
380 for (vk::ShaderProgramHelper &program : mConvertIndexPrograms)
381 {
382 program.destroy(device);
383 }
384 for (vk::ShaderProgramHelper &program : mConvertIndirectLineLoopPrograms)
385 {
386 program.destroy(device);
387 }
388 for (vk::ShaderProgramHelper &program : mConvertIndexIndirectLineLoopPrograms)
389 {
390 program.destroy(device);
391 }
392 for (vk::ShaderProgramHelper &program : mConvertVertexPrograms)
393 {
394 program.destroy(device);
395 }
396 mImageClearProgramVSOnly.destroy(device);
397 for (vk::ShaderProgramHelper &program : mImageClearProgram)
398 {
399 program.destroy(device);
400 }
401 for (vk::ShaderProgramHelper &program : mImageCopyPrograms)
402 {
403 program.destroy(device);
404 }
405 for (vk::ShaderProgramHelper &program : mBlitResolvePrograms)
406 {
407 program.destroy(device);
408 }
409 for (vk::ShaderProgramHelper &program : mBlitResolveStencilNoExportPrograms)
410 {
411 program.destroy(device);
412 }
413 for (vk::ShaderProgramHelper &program : mOverlayCullPrograms)
414 {
415 program.destroy(device);
416 }
417 for (vk::ShaderProgramHelper &program : mOverlayDrawPrograms)
418 {
419 program.destroy(device);
420 }
421
422 mPointSampler.destroy(device);
423 mLinearSampler.destroy(device);
424 }
425
ensureResourcesInitialized(ContextVk * contextVk,Function function,VkDescriptorPoolSize * setSizes,size_t setSizesCount,size_t pushConstantsSize)426 angle::Result UtilsVk::ensureResourcesInitialized(ContextVk *contextVk,
427 Function function,
428 VkDescriptorPoolSize *setSizes,
429 size_t setSizesCount,
430 size_t pushConstantsSize)
431 {
432 RendererVk *renderer = contextVk->getRenderer();
433
434 vk::DescriptorSetLayoutDesc descriptorSetDesc;
435 bool isCompute = function >= Function::ComputeStartIndex;
436 const VkShaderStageFlags descStages =
437 isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
438
439 uint32_t currentBinding = 0;
440 for (size_t i = 0; i < setSizesCount; ++i)
441 {
442 descriptorSetDesc.update(currentBinding, setSizes[i].type, setSizes[i].descriptorCount,
443 descStages);
444 currentBinding += setSizes[i].descriptorCount;
445 }
446
447 ANGLE_TRY(renderer->getDescriptorSetLayout(contextVk, descriptorSetDesc,
448 &mDescriptorSetLayouts[function][kSetIndex]));
449
450 gl::ShaderType pushConstantsShaderStage =
451 isCompute ? gl::ShaderType::Compute : gl::ShaderType::Fragment;
452
453 // Corresponding pipeline layouts:
454 vk::PipelineLayoutDesc pipelineLayoutDesc;
455
456 pipelineLayoutDesc.updateDescriptorSetLayout(kSetIndex, descriptorSetDesc);
457 if (pushConstantsSize)
458 {
459 pipelineLayoutDesc.updatePushConstantRange(pushConstantsShaderStage, 0,
460 static_cast<uint32_t>(pushConstantsSize));
461 }
462
463 ANGLE_TRY(renderer->getPipelineLayout(contextVk, pipelineLayoutDesc,
464 mDescriptorSetLayouts[function],
465 &mPipelineLayouts[function]));
466
467 if (setSizesCount > 0)
468 {
469 ANGLE_TRY(mDescriptorPools[function].init(contextVk, setSizes,
470 static_cast<uint32_t>(setSizesCount)));
471 }
472
473 return angle::Result::Continue;
474 }
475
ensureBufferClearResourcesInitialized(ContextVk * contextVk)476 angle::Result UtilsVk::ensureBufferClearResourcesInitialized(ContextVk *contextVk)
477 {
478 if (mPipelineLayouts[Function::BufferClear].valid())
479 {
480 return angle::Result::Continue;
481 }
482
483 VkDescriptorPoolSize setSizes[1] = {
484 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1},
485 };
486
487 return ensureResourcesInitialized(contextVk, Function::BufferClear, setSizes,
488 ArraySize(setSizes), sizeof(BufferUtilsShaderParams));
489 }
490
ensureConvertIndexResourcesInitialized(ContextVk * contextVk)491 angle::Result UtilsVk::ensureConvertIndexResourcesInitialized(ContextVk *contextVk)
492 {
493 if (mPipelineLayouts[Function::ConvertIndexBuffer].valid())
494 {
495 return angle::Result::Continue;
496 }
497
498 VkDescriptorPoolSize setSizes[2] = {
499 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
500 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
501 };
502
503 return ensureResourcesInitialized(contextVk, Function::ConvertIndexBuffer, setSizes,
504 ArraySize(setSizes), sizeof(ConvertIndexShaderParams));
505 }
506
ensureConvertIndexIndirectResourcesInitialized(ContextVk * contextVk)507 angle::Result UtilsVk::ensureConvertIndexIndirectResourcesInitialized(ContextVk *contextVk)
508 {
509 if (mPipelineLayouts[Function::ConvertIndexIndirectBuffer].valid())
510 {
511 return angle::Result::Continue;
512 }
513
514 VkDescriptorPoolSize setSizes[4] = {
515 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dest index buffer
516 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // source index buffer
517 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // src indirect buffer
518 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dest indirect buffer
519 };
520
521 return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectBuffer, setSizes,
522 ArraySize(setSizes),
523 sizeof(ConvertIndexIndirectShaderParams));
524 }
525
ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk * contextVk)526 angle::Result UtilsVk::ensureConvertIndexIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
527 {
528 if (mPipelineLayouts[Function::ConvertIndexIndirectLineLoopBuffer].valid())
529 {
530 return angle::Result::Continue;
531 }
532
533 VkDescriptorPoolSize setSizes[4] = {
534 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // cmd buffer
535 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dest cmd buffer
536 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // source index buffer
537 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dest index buffer
538 };
539
540 return ensureResourcesInitialized(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
541 setSizes, ArraySize(setSizes),
542 sizeof(ConvertIndexIndirectLineLoopShaderParams));
543 }
544
ensureConvertIndirectLineLoopResourcesInitialized(ContextVk * contextVk)545 angle::Result UtilsVk::ensureConvertIndirectLineLoopResourcesInitialized(ContextVk *contextVk)
546 {
547 if (mPipelineLayouts[Function::ConvertIndirectLineLoopBuffer].valid())
548 {
549 return angle::Result::Continue;
550 }
551
552 VkDescriptorPoolSize setSizes[3] = {
553 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // cmd buffer
554 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dest cmd buffer
555 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}, // dest index buffer
556 };
557
558 return ensureResourcesInitialized(contextVk, Function::ConvertIndirectLineLoopBuffer, setSizes,
559 ArraySize(setSizes),
560 sizeof(ConvertIndirectLineLoopShaderParams));
561 }
562
ensureConvertVertexResourcesInitialized(ContextVk * contextVk)563 angle::Result UtilsVk::ensureConvertVertexResourcesInitialized(ContextVk *contextVk)
564 {
565 if (mPipelineLayouts[Function::ConvertVertexBuffer].valid())
566 {
567 return angle::Result::Continue;
568 }
569
570 VkDescriptorPoolSize setSizes[2] = {
571 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
572 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
573 };
574
575 return ensureResourcesInitialized(contextVk, Function::ConvertVertexBuffer, setSizes,
576 ArraySize(setSizes), sizeof(ConvertVertexShaderParams));
577 }
578
ensureImageClearResourcesInitialized(ContextVk * contextVk)579 angle::Result UtilsVk::ensureImageClearResourcesInitialized(ContextVk *contextVk)
580 {
581 if (mPipelineLayouts[Function::ImageClear].valid())
582 {
583 return angle::Result::Continue;
584 }
585
586 // The shader does not use any descriptor sets.
587 return ensureResourcesInitialized(contextVk, Function::ImageClear, nullptr, 0,
588 sizeof(ImageClearShaderParams));
589 }
590
ensureImageCopyResourcesInitialized(ContextVk * contextVk)591 angle::Result UtilsVk::ensureImageCopyResourcesInitialized(ContextVk *contextVk)
592 {
593 if (mPipelineLayouts[Function::ImageCopy].valid())
594 {
595 return angle::Result::Continue;
596 }
597
598 VkDescriptorPoolSize setSizes[1] = {
599 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
600 };
601
602 return ensureResourcesInitialized(contextVk, Function::ImageCopy, setSizes, ArraySize(setSizes),
603 sizeof(ImageCopyShaderParams));
604 }
605
ensureBlitResolveResourcesInitialized(ContextVk * contextVk)606 angle::Result UtilsVk::ensureBlitResolveResourcesInitialized(ContextVk *contextVk)
607 {
608 if (!mPipelineLayouts[Function::BlitResolve].valid())
609 {
610 VkDescriptorPoolSize setSizes[3] = {
611 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
612 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
613 {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
614 };
615
616 ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolve, setSizes,
617 ArraySize(setSizes), sizeof(BlitResolveShaderParams)));
618 }
619
620 return ensureSamplersInitialized(contextVk);
621 }
622
ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk * contextVk)623 angle::Result UtilsVk::ensureBlitResolveStencilNoExportResourcesInitialized(ContextVk *contextVk)
624 {
625 if (!mPipelineLayouts[Function::BlitResolveStencilNoExport].valid())
626 {
627 VkDescriptorPoolSize setSizes[3] = {
628 {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
629 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
630 {VK_DESCRIPTOR_TYPE_SAMPLER, 1},
631 };
632
633 ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::BlitResolveStencilNoExport,
634 setSizes, ArraySize(setSizes),
635 sizeof(BlitResolveStencilNoExportShaderParams)));
636 }
637
638 return ensureSamplersInitialized(contextVk);
639 }
640
ensureOverlayCullResourcesInitialized(ContextVk * contextVk)641 angle::Result UtilsVk::ensureOverlayCullResourcesInitialized(ContextVk *contextVk)
642 {
643 if (mPipelineLayouts[Function::OverlayCull].valid())
644 {
645 return angle::Result::Continue;
646 }
647
648 VkDescriptorPoolSize setSizes[2] = {
649 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1},
650 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
651 };
652
653 return ensureResourcesInitialized(contextVk, Function::OverlayCull, setSizes,
654 ArraySize(setSizes), 0);
655 }
656
ensureOverlayDrawResourcesInitialized(ContextVk * contextVk)657 angle::Result UtilsVk::ensureOverlayDrawResourcesInitialized(ContextVk *contextVk)
658 {
659 if (!mPipelineLayouts[Function::OverlayDraw].valid())
660 {
661 VkDescriptorPoolSize setSizes[5] = {
662 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1},
663 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1}, {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
664 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1},
665 };
666
667 ANGLE_TRY(ensureResourcesInitialized(contextVk, Function::OverlayDraw, setSizes,
668 ArraySize(setSizes), sizeof(OverlayDrawShaderParams)));
669 }
670
671 return ensureSamplersInitialized(contextVk);
672 }
673
ensureSamplersInitialized(ContextVk * contextVk)674 angle::Result UtilsVk::ensureSamplersInitialized(ContextVk *contextVk)
675 {
676 VkSamplerCreateInfo samplerInfo = {};
677 samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
678 samplerInfo.flags = 0;
679 samplerInfo.magFilter = VK_FILTER_NEAREST;
680 samplerInfo.minFilter = VK_FILTER_NEAREST;
681 samplerInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST;
682 samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
683 samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
684 samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
685 samplerInfo.mipLodBias = 0.0f;
686 samplerInfo.anisotropyEnable = VK_FALSE;
687 samplerInfo.maxAnisotropy = 1;
688 samplerInfo.compareEnable = VK_FALSE;
689 samplerInfo.compareOp = VK_COMPARE_OP_ALWAYS;
690 samplerInfo.minLod = 0;
691 samplerInfo.maxLod = 0;
692 samplerInfo.borderColor = VK_BORDER_COLOR_INT_TRANSPARENT_BLACK;
693 samplerInfo.unnormalizedCoordinates = VK_FALSE;
694
695 if (!mPointSampler.valid())
696 {
697 ANGLE_VK_TRY(contextVk, mPointSampler.init(contextVk->getDevice(), samplerInfo));
698 }
699
700 samplerInfo.magFilter = VK_FILTER_LINEAR;
701 samplerInfo.minFilter = VK_FILTER_LINEAR;
702
703 if (!mLinearSampler.valid())
704 {
705 ANGLE_VK_TRY(contextVk, mLinearSampler.init(contextVk->getDevice(), samplerInfo));
706 }
707
708 return angle::Result::Continue;
709 }
710
setupProgram(ContextVk * contextVk,Function function,vk::RefCounted<vk::ShaderAndSerial> * fsCsShader,vk::RefCounted<vk::ShaderAndSerial> * vsShader,vk::ShaderProgramHelper * program,const vk::GraphicsPipelineDesc * pipelineDesc,const VkDescriptorSet descriptorSet,const void * pushConstants,size_t pushConstantsSize,vk::CommandBuffer * commandBuffer)711 angle::Result UtilsVk::setupProgram(ContextVk *contextVk,
712 Function function,
713 vk::RefCounted<vk::ShaderAndSerial> *fsCsShader,
714 vk::RefCounted<vk::ShaderAndSerial> *vsShader,
715 vk::ShaderProgramHelper *program,
716 const vk::GraphicsPipelineDesc *pipelineDesc,
717 const VkDescriptorSet descriptorSet,
718 const void *pushConstants,
719 size_t pushConstantsSize,
720 vk::CommandBuffer *commandBuffer)
721 {
722 RendererVk *renderer = contextVk->getRenderer();
723
724 const bool isCompute = function >= Function::ComputeStartIndex;
725 const VkShaderStageFlags pushConstantsShaderStage =
726 isCompute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
727 const VkPipelineBindPoint pipelineBindPoint =
728 isCompute ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
729
730 // If compute, vsShader and pipelineDesc should be nullptr, and if not compute they shouldn't
731 // be.
732 ASSERT(isCompute != (vsShader && pipelineDesc));
733
734 const vk::BindingPointer<vk::PipelineLayout> &pipelineLayout = mPipelineLayouts[function];
735
736 Serial serial = contextVk->getCurrentQueueSerial();
737
738 if (isCompute)
739 {
740 vk::PipelineAndSerial *pipelineAndSerial;
741 program->setShader(gl::ShaderType::Compute, fsCsShader);
742 ANGLE_TRY(program->getComputePipeline(contextVk, pipelineLayout.get(), &pipelineAndSerial));
743 pipelineAndSerial->updateSerial(serial);
744 commandBuffer->bindComputePipeline(pipelineAndSerial->get());
745 }
746 else
747 {
748 program->setShader(gl::ShaderType::Vertex, vsShader);
749 if (fsCsShader)
750 {
751 program->setShader(gl::ShaderType::Fragment, fsCsShader);
752 }
753
754 // This value is not used but is passed to getGraphicsPipeline to avoid a nullptr check.
755 const vk::GraphicsPipelineDesc *descPtr;
756 vk::PipelineHelper *helper;
757 vk::PipelineCache *pipelineCache = nullptr;
758 ANGLE_TRY(renderer->getPipelineCache(&pipelineCache));
759 ANGLE_TRY(program->getGraphicsPipeline(contextVk, &contextVk->getRenderPassCache(),
760 *pipelineCache, serial, pipelineLayout.get(),
761 *pipelineDesc, gl::AttributesMask(),
762 gl::ComponentTypeMask(), &descPtr, &helper));
763 helper->updateSerial(serial);
764 commandBuffer->bindGraphicsPipeline(helper->getPipeline());
765 }
766
767 if (descriptorSet != VK_NULL_HANDLE)
768 {
769 commandBuffer->bindDescriptorSets(pipelineLayout.get(), pipelineBindPoint, 0, 1,
770 &descriptorSet, 0, nullptr);
771 if (isCompute)
772 {
773 contextVk->invalidateComputeDescriptorSet(0);
774 }
775 else
776 {
777 contextVk->invalidateGraphicsDescriptorSet(0);
778 }
779 }
780
781 if (pushConstants)
782 {
783 commandBuffer->pushConstants(pipelineLayout.get(), pushConstantsShaderStage, 0,
784 static_cast<uint32_t>(pushConstantsSize), pushConstants);
785 }
786
787 return angle::Result::Continue;
788 }
789
clearBuffer(ContextVk * contextVk,vk::BufferHelper * dest,const ClearParameters & params)790 angle::Result UtilsVk::clearBuffer(ContextVk *contextVk,
791 vk::BufferHelper *dest,
792 const ClearParameters ¶ms)
793 {
794 ANGLE_TRY(ensureBufferClearResourcesInitialized(contextVk));
795
796 vk::CommandBuffer *commandBuffer;
797 // Tell the context dest that we are writing to dest.
798 ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dest));
799 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
800
801 const vk::Format &destFormat = dest->getViewFormat();
802
803 uint32_t flags = BufferUtils_comp::kIsClear | GetBufferUtilsFlags(params.size, destFormat);
804
805 BufferUtilsShaderParams shaderParams;
806 shaderParams.destOffset = static_cast<uint32_t>(params.offset);
807 shaderParams.size = static_cast<uint32_t>(params.size);
808 shaderParams.clearValue = params.clearValue;
809
810 VkDescriptorSet descriptorSet;
811 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
812 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BufferClear, &descriptorPoolBinding,
813 &descriptorSet));
814
815 VkWriteDescriptorSet writeInfo = {};
816
817 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
818 writeInfo.dstSet = descriptorSet;
819 writeInfo.dstBinding = kBufferClearOutputBinding;
820 writeInfo.descriptorCount = 1;
821 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
822 writeInfo.pTexelBufferView = dest->getBufferView().ptr();
823
824 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
825
826 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
827 ANGLE_TRY(contextVk->getShaderLibrary().getBufferUtils_comp(contextVk, flags, &shader));
828
829 ANGLE_TRY(setupProgram(contextVk, Function::BufferClear, shader, nullptr,
830 &mBufferUtilsPrograms[flags], nullptr, descriptorSet, &shaderParams,
831 sizeof(shaderParams), commandBuffer));
832
833 commandBuffer->dispatch(UnsignedCeilDivide(static_cast<uint32_t>(params.size), 64), 1, 1);
834
835 descriptorPoolBinding.reset();
836
837 return angle::Result::Continue;
838 }
839
convertIndexBuffer(ContextVk * contextVk,vk::BufferHelper * dest,vk::BufferHelper * src,const ConvertIndexParameters & params)840 angle::Result UtilsVk::convertIndexBuffer(ContextVk *contextVk,
841 vk::BufferHelper *dest,
842 vk::BufferHelper *src,
843 const ConvertIndexParameters ¶ms)
844 {
845 ANGLE_TRY(ensureConvertIndexResourcesInitialized(contextVk));
846
847 vk::CommandBuffer *commandBuffer;
848 ANGLE_TRY(contextVk->onBufferComputeShaderRead(src));
849 ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dest));
850 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
851
852 VkDescriptorSet descriptorSet;
853 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
854 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexBuffer, &descriptorPoolBinding,
855 &descriptorSet));
856
857 std::array<VkDescriptorBufferInfo, 2> buffers = {{
858 {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
859 {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
860 }};
861
862 VkWriteDescriptorSet writeInfo = {};
863 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
864 writeInfo.dstSet = descriptorSet;
865 writeInfo.dstBinding = kConvertIndexDestinationBinding;
866 writeInfo.descriptorCount = 2;
867 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
868 writeInfo.pBufferInfo = buffers.data();
869
870 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
871
872 ConvertIndexShaderParams shaderParams = {params.srcOffset, params.dstOffset >> 2,
873 params.maxIndex, 0};
874
875 uint32_t flags = 0;
876 if (contextVk->getState().isPrimitiveRestartEnabled())
877 {
878 flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
879 }
880
881 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
882 ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
883
884 ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexBuffer, shader, nullptr,
885 &mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
886 sizeof(ConvertIndexShaderParams), commandBuffer));
887
888 constexpr uint32_t kInvocationsPerGroup = 64;
889 constexpr uint32_t kInvocationsPerIndex = 2;
890 const uint32_t kIndexCount = params.maxIndex - params.srcOffset;
891 const uint32_t kGroupCount =
892 UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
893 commandBuffer->dispatch(kGroupCount, 1, 1);
894
895 descriptorPoolBinding.reset();
896
897 return angle::Result::Continue;
898 }
899
convertIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuf,vk::BufferHelper * srcIndexBuf,vk::BufferHelper * dstIndirectBuf,vk::BufferHelper * dstIndexBuf,const ConvertIndexIndirectParameters & params)900 angle::Result UtilsVk::convertIndexIndirectBuffer(ContextVk *contextVk,
901 vk::BufferHelper *srcIndirectBuf,
902 vk::BufferHelper *srcIndexBuf,
903 vk::BufferHelper *dstIndirectBuf,
904 vk::BufferHelper *dstIndexBuf,
905 const ConvertIndexIndirectParameters ¶ms)
906 {
907 ANGLE_TRY(ensureConvertIndexIndirectResourcesInitialized(contextVk));
908
909 vk::CommandBuffer *commandBuffer;
910 ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndirectBuf));
911 ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndexBuf));
912 ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dstIndirectBuf));
913 ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dstIndexBuf));
914 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
915
916 VkDescriptorSet descriptorSet;
917 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
918 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexIndirectBuffer,
919 &descriptorPoolBinding, &descriptorSet));
920
921 std::array<VkDescriptorBufferInfo, 4> buffers = {{
922 {dstIndexBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
923 {srcIndexBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
924 {srcIndirectBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
925 {dstIndirectBuf->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
926 }};
927
928 VkWriteDescriptorSet writeInfo = {};
929 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
930 writeInfo.dstSet = descriptorSet;
931 writeInfo.dstBinding = kConvertIndexDestinationBinding;
932 writeInfo.descriptorCount = 4;
933 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
934 writeInfo.pBufferInfo = buffers.data();
935
936 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
937
938 ConvertIndexIndirectShaderParams shaderParams = {params.srcIndirectBufOffset >> 2,
939 params.dstIndexBufOffset >> 2, params.maxIndex,
940 params.dstIndirectBufOffset >> 2};
941
942 uint32_t flags = vk::InternalShader::ConvertIndex_comp::kIsIndirect;
943 if (contextVk->getState().isPrimitiveRestartEnabled())
944 {
945 flags |= vk::InternalShader::ConvertIndex_comp::kIsPrimitiveRestartEnabled;
946 }
947
948 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
949 ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndex_comp(contextVk, flags, &shader));
950
951 ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectBuffer, shader, nullptr,
952 &mConvertIndexPrograms[flags], nullptr, descriptorSet, &shaderParams,
953 sizeof(ConvertIndexIndirectShaderParams), commandBuffer));
954
955 constexpr uint32_t kInvocationsPerGroup = 64;
956 constexpr uint32_t kInvocationsPerIndex = 2;
957 const uint32_t kIndexCount = params.maxIndex;
958 const uint32_t kGroupCount =
959 UnsignedCeilDivide(kIndexCount * kInvocationsPerIndex, kInvocationsPerGroup);
960 commandBuffer->dispatch(kGroupCount, 1, 1);
961
962 descriptorPoolBinding.reset();
963
964 return angle::Result::Continue;
965 }
966
convertLineLoopIndexIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * dstIndirectBuffer,vk::BufferHelper * dstIndexBuffer,vk::BufferHelper * srcIndexBuffer,const ConvertLineLoopIndexIndirectParameters & params)967 angle::Result UtilsVk::convertLineLoopIndexIndirectBuffer(
968 ContextVk *contextVk,
969 vk::BufferHelper *srcIndirectBuffer,
970 vk::BufferHelper *dstIndirectBuffer,
971 vk::BufferHelper *dstIndexBuffer,
972 vk::BufferHelper *srcIndexBuffer,
973 const ConvertLineLoopIndexIndirectParameters ¶ms)
974 {
975 ANGLE_TRY(ensureConvertIndexIndirectLineLoopResourcesInitialized(contextVk));
976
977 vk::CommandBuffer *commandBuffer;
978 ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndirectBuffer));
979 ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndexBuffer));
980 ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dstIndirectBuffer));
981 ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dstIndexBuffer));
982 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
983
984 VkDescriptorSet descriptorSet;
985 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
986 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndexIndirectLineLoopBuffer,
987 &descriptorPoolBinding, &descriptorSet));
988
989 std::array<VkDescriptorBufferInfo, 4> buffers = {{
990 {dstIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
991 {srcIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
992 {srcIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
993 {dstIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
994 }};
995
996 VkWriteDescriptorSet writeInfo = {};
997 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
998 writeInfo.dstSet = descriptorSet;
999 writeInfo.dstBinding = kConvertIndexDestinationBinding;
1000 writeInfo.descriptorCount = 4;
1001 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1002 writeInfo.pBufferInfo = buffers.data();
1003
1004 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1005
1006 ConvertIndexIndirectLineLoopShaderParams shaderParams = {
1007 params.indirectBufferOffset >> 2, params.dstIndirectBufferOffset >> 2,
1008 params.dstIndexBufferOffset >> 2, contextVk->getState().isPrimitiveRestartEnabled()};
1009
1010 uint32_t flags = GetConvertIndexIndirectLineLoopFlag(params.indicesBitsWidth);
1011
1012 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1013 ANGLE_TRY(contextVk->getShaderLibrary().getConvertIndexIndirectLineLoop_comp(contextVk, flags,
1014 &shader));
1015
1016 ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndexIndirectLineLoopBuffer, shader, nullptr,
1017 &mConvertIndexIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
1018 &shaderParams, sizeof(ConvertIndexIndirectLineLoopShaderParams),
1019 commandBuffer));
1020
1021 commandBuffer->dispatch(1, 1, 1);
1022
1023 descriptorPoolBinding.reset();
1024
1025 return angle::Result::Continue;
1026 }
1027
convertLineLoopArrayIndirectBuffer(ContextVk * contextVk,vk::BufferHelper * srcIndirectBuffer,vk::BufferHelper * destIndirectBuffer,vk::BufferHelper * destIndexBuffer,const ConvertLineLoopArrayIndirectParameters & params)1028 angle::Result UtilsVk::convertLineLoopArrayIndirectBuffer(
1029 ContextVk *contextVk,
1030 vk::BufferHelper *srcIndirectBuffer,
1031 vk::BufferHelper *destIndirectBuffer,
1032 vk::BufferHelper *destIndexBuffer,
1033 const ConvertLineLoopArrayIndirectParameters ¶ms)
1034 {
1035 ANGLE_TRY(ensureConvertIndirectLineLoopResourcesInitialized(contextVk));
1036
1037 vk::CommandBuffer *commandBuffer;
1038 ANGLE_TRY(contextVk->onBufferComputeShaderRead(srcIndirectBuffer));
1039 ANGLE_TRY(contextVk->onBufferComputeShaderWrite(destIndirectBuffer));
1040 ANGLE_TRY(contextVk->onBufferComputeShaderWrite(destIndexBuffer));
1041 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1042
1043 VkDescriptorSet descriptorSet;
1044 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1045 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertIndirectLineLoopBuffer,
1046 &descriptorPoolBinding, &descriptorSet));
1047
1048 std::array<VkDescriptorBufferInfo, 3> buffers = {{
1049 {srcIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1050 {destIndirectBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1051 {destIndexBuffer->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1052 }};
1053
1054 VkWriteDescriptorSet writeInfo = {};
1055 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1056 writeInfo.dstSet = descriptorSet;
1057 writeInfo.dstBinding = kConvertIndexDestinationBinding;
1058 writeInfo.descriptorCount = 3;
1059 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1060 writeInfo.pBufferInfo = buffers.data();
1061
1062 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1063
1064 ConvertIndirectLineLoopShaderParams shaderParams = {params.indirectBufferOffset >> 2,
1065 params.dstIndirectBufferOffset >> 2,
1066 params.dstIndexBufferOffset >> 2};
1067
1068 uint32_t flags = 0;
1069
1070 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1071 ANGLE_TRY(
1072 contextVk->getShaderLibrary().getConvertIndirectLineLoop_comp(contextVk, flags, &shader));
1073
1074 ANGLE_TRY(setupProgram(contextVk, Function::ConvertIndirectLineLoopBuffer, shader, nullptr,
1075 &mConvertIndirectLineLoopPrograms[flags], nullptr, descriptorSet,
1076 &shaderParams, sizeof(ConvertIndirectLineLoopShaderParams),
1077 commandBuffer));
1078
1079 commandBuffer->dispatch(1, 1, 1);
1080
1081 descriptorPoolBinding.reset();
1082
1083 return angle::Result::Continue;
1084 }
1085
convertVertexBuffer(ContextVk * contextVk,vk::BufferHelper * dest,vk::BufferHelper * src,const ConvertVertexParameters & params)1086 angle::Result UtilsVk::convertVertexBuffer(ContextVk *contextVk,
1087 vk::BufferHelper *dest,
1088 vk::BufferHelper *src,
1089 const ConvertVertexParameters ¶ms)
1090 {
1091 ANGLE_TRY(ensureConvertVertexResourcesInitialized(contextVk));
1092
1093 vk::CommandBuffer *commandBuffer;
1094 ANGLE_TRY(contextVk->onBufferComputeShaderRead(src));
1095 ANGLE_TRY(contextVk->onBufferComputeShaderWrite(dest));
1096 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1097
1098 ConvertVertexShaderParams shaderParams;
1099 shaderParams.Ns = params.srcFormat->channelCount;
1100 shaderParams.Bs = params.srcFormat->pixelBytes / params.srcFormat->channelCount;
1101 shaderParams.Ss = static_cast<uint32_t>(params.srcStride);
1102 shaderParams.Nd = params.destFormat->channelCount;
1103 shaderParams.Bd = params.destFormat->pixelBytes / params.destFormat->channelCount;
1104 shaderParams.Sd = shaderParams.Nd * shaderParams.Bd;
1105 // The component size is expected to either be 1, 2 or 4 bytes.
1106 ASSERT(4 % shaderParams.Bs == 0);
1107 ASSERT(4 % shaderParams.Bd == 0);
1108 shaderParams.Es = 4 / shaderParams.Bs;
1109 shaderParams.Ed = 4 / shaderParams.Bd;
1110 // Total number of output components is simply the number of vertices by number of components in
1111 // each.
1112 shaderParams.componentCount = static_cast<uint32_t>(params.vertexCount * shaderParams.Nd);
1113 // Total number of 4-byte outputs is the number of components divided by how many components can
1114 // fit in a 4-byte value. Note that this value is also the invocation size of the shader.
1115 shaderParams.outputCount = shaderParams.componentCount / shaderParams.Ed;
1116 shaderParams.srcOffset = static_cast<uint32_t>(params.srcOffset);
1117 shaderParams.destOffset = static_cast<uint32_t>(params.destOffset);
1118
1119 uint32_t flags = GetConvertVertexFlags(params);
1120
1121 VkDescriptorSet descriptorSet;
1122 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1123 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ConvertVertexBuffer,
1124 &descriptorPoolBinding, &descriptorSet));
1125
1126 VkWriteDescriptorSet writeInfo = {};
1127 VkDescriptorBufferInfo buffers[2] = {
1128 {dest->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1129 {src->getBuffer().getHandle(), 0, VK_WHOLE_SIZE},
1130 };
1131 static_assert(kConvertVertexDestinationBinding + 1 == kConvertVertexSourceBinding,
1132 "Update write info");
1133
1134 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1135 writeInfo.dstSet = descriptorSet;
1136 writeInfo.dstBinding = kConvertVertexDestinationBinding;
1137 writeInfo.descriptorCount = 2;
1138 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1139 writeInfo.pBufferInfo = buffers;
1140
1141 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1142
1143 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1144 ANGLE_TRY(contextVk->getShaderLibrary().getConvertVertex_comp(contextVk, flags, &shader));
1145
1146 ANGLE_TRY(setupProgram(contextVk, Function::ConvertVertexBuffer, shader, nullptr,
1147 &mConvertVertexPrograms[flags], nullptr, descriptorSet, &shaderParams,
1148 sizeof(shaderParams), commandBuffer));
1149
1150 commandBuffer->dispatch(UnsignedCeilDivide(shaderParams.outputCount, 64), 1, 1);
1151
1152 descriptorPoolBinding.reset();
1153
1154 return angle::Result::Continue;
1155 }
1156
startRenderPass(ContextVk * contextVk,vk::ImageHelper * image,const vk::ImageView * imageView,const vk::RenderPassDesc & renderPassDesc,const gl::Rectangle & renderArea,vk::CommandBuffer ** commandBufferOut)1157 angle::Result UtilsVk::startRenderPass(ContextVk *contextVk,
1158 vk::ImageHelper *image,
1159 const vk::ImageView *imageView,
1160 const vk::RenderPassDesc &renderPassDesc,
1161 const gl::Rectangle &renderArea,
1162 vk::CommandBuffer **commandBufferOut)
1163 {
1164 vk::RenderPass *compatibleRenderPass = nullptr;
1165 ANGLE_TRY(contextVk->getCompatibleRenderPass(renderPassDesc, &compatibleRenderPass));
1166
1167 VkFramebufferCreateInfo framebufferInfo = {};
1168
1169 // Minimize the framebuffer coverage to only cover up to the render area.
1170 framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
1171 framebufferInfo.flags = 0;
1172 framebufferInfo.renderPass = compatibleRenderPass->getHandle();
1173 framebufferInfo.attachmentCount = 1;
1174 framebufferInfo.pAttachments = imageView->ptr();
1175 framebufferInfo.width = renderArea.x + renderArea.width;
1176 framebufferInfo.height = renderArea.y + renderArea.height;
1177 framebufferInfo.layers = 1;
1178 if (contextVk->isRotatedAspectRatioForDrawFBO())
1179 {
1180 // The surface is rotated 90/270 degrees. This changes the aspect ratio of
1181 // the surface. Swap the width and height of the framebuffer.
1182 std::swap(framebufferInfo.width, framebufferInfo.height);
1183 }
1184
1185 vk::Framebuffer framebuffer;
1186 ANGLE_VK_TRY(contextVk, framebuffer.init(contextVk->getDevice(), framebufferInfo));
1187
1188 vk::AttachmentOpsArray renderPassAttachmentOps;
1189 vk::ClearValuesArray clearValues;
1190 clearValues.store(0, VK_IMAGE_ASPECT_COLOR_BIT, {});
1191
1192 renderPassAttachmentOps.initWithLoadStore(0, vk::ImageLayout::ColorAttachment,
1193 vk::ImageLayout::ColorAttachment);
1194
1195 ANGLE_TRY(contextVk->flushAndBeginRenderPass(framebuffer, renderArea, renderPassDesc,
1196 renderPassAttachmentOps, clearValues,
1197 commandBufferOut));
1198
1199 contextVk->addGarbage(&framebuffer);
1200
1201 return angle::Result::Continue;
1202 }
1203
clearFramebuffer(ContextVk * contextVk,FramebufferVk * framebuffer,const ClearFramebufferParameters & params)1204 angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
1205 FramebufferVk *framebuffer,
1206 const ClearFramebufferParameters ¶ms)
1207 {
1208 ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
1209
1210 const gl::Rectangle &scissoredRenderArea = params.clearArea;
1211
1212 vk::CommandBuffer *commandBuffer;
1213 ANGLE_TRY(contextVk->startRenderPass(scissoredRenderArea, &commandBuffer));
1214
1215 ImageClearShaderParams shaderParams;
1216 shaderParams.clearValue = params.colorClearValue;
1217
1218 vk::GraphicsPipelineDesc pipelineDesc;
1219 pipelineDesc.initDefaults();
1220 pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
1221 pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask());
1222 pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags);
1223 pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
1224 pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
1225 // Note: depth test is disabled by default so this should be unnecessary, but works around an
1226 // Intel bug on windows. http://anglebug.com/3348
1227 pipelineDesc.setDepthWriteEnabled(false);
1228
1229 // Clear stencil by enabling stencil write with the right mask.
1230 if (params.clearStencil)
1231 {
1232 const uint8_t compareMask = 0xFF;
1233 const uint8_t clearStencilValue = params.stencilClearValue;
1234
1235 pipelineDesc.setStencilTestEnabled(true);
1236 pipelineDesc.setStencilFrontFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
1237 pipelineDesc.setStencilBackFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
1238 pipelineDesc.setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1239 VK_STENCIL_OP_REPLACE);
1240 pipelineDesc.setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1241 VK_STENCIL_OP_REPLACE);
1242 pipelineDesc.setStencilFrontWriteMask(params.stencilMask);
1243 pipelineDesc.setStencilBackWriteMask(params.stencilMask);
1244 }
1245
1246 VkViewport viewport;
1247 gl::Rectangle completeRenderArea = framebuffer->getCompleteRenderArea();
1248 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
1249 if (contextVk->isRotatedAspectRatioForDrawFBO())
1250 {
1251 // The surface is rotated 90/270 degrees. This changes the aspect ratio of the surface.
1252 std::swap(completeRenderArea.width, completeRenderArea.height);
1253 }
1254 gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, completeRenderArea.height,
1255 &viewport);
1256 pipelineDesc.setViewport(viewport);
1257
1258 pipelineDesc.setScissor(gl_vk::GetRect(params.clearArea));
1259
1260 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
1261 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
1262 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
1263 vk::ShaderProgramHelper *imageClearProgram = &mImageClearProgramVSOnly;
1264
1265 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
1266 if (params.clearColor)
1267 {
1268 uint32_t flags = GetImageClearFlags(*params.colorFormat, params.colorAttachmentIndexGL);
1269 ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
1270 imageClearProgram = &mImageClearProgram[flags];
1271 }
1272
1273 ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
1274 imageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
1275 sizeof(shaderParams), commandBuffer));
1276 commandBuffer->draw(6, 0);
1277 return angle::Result::Continue;
1278 }
1279
colorBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcView,const BlitResolveParameters & params)1280 angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk,
1281 FramebufferVk *framebuffer,
1282 vk::ImageHelper *src,
1283 const vk::ImageView *srcView,
1284 const BlitResolveParameters ¶ms)
1285 {
1286 return blitResolveImpl(contextVk, framebuffer, src, srcView, nullptr, nullptr, params);
1287 }
1288
depthStencilBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)1289 angle::Result UtilsVk::depthStencilBlitResolve(ContextVk *contextVk,
1290 FramebufferVk *framebuffer,
1291 vk::ImageHelper *src,
1292 const vk::ImageView *srcDepthView,
1293 const vk::ImageView *srcStencilView,
1294 const BlitResolveParameters ¶ms)
1295 {
1296 return blitResolveImpl(contextVk, framebuffer, src, nullptr, srcDepthView, srcStencilView,
1297 params);
1298 }
1299
blitResolveImpl(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcColorView,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)1300 angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
1301 FramebufferVk *framebuffer,
1302 vk::ImageHelper *src,
1303 const vk::ImageView *srcColorView,
1304 const vk::ImageView *srcDepthView,
1305 const vk::ImageView *srcStencilView,
1306 const BlitResolveParameters ¶ms)
1307 {
1308 // Possible ways to resolve color are:
1309 //
1310 // - vkCmdResolveImage: This is by far the easiest method, but lacks the ability to flip
1311 // images during resolve.
1312 // - Manual resolve: A shader can read all samples from input, average them and output.
1313 // - Using subpass resolve attachment: A shader can transform the sample colors from source to
1314 // destination coordinates and the subpass resolve would finish the job.
1315 //
1316 // The first method is unable to handle flipping, so it's not generally applicable. The last
1317 // method would have been great were we able to modify the last render pass that rendered into
1318 // source, but still wouldn't be able to handle flipping. The second method is implemented in
1319 // this function for complete control.
1320
1321 // Possible ways to resolve depth/stencil are:
1322 //
1323 // - Manual resolve: A shader can read a samples from input and choose that for output.
1324 // - Using subpass resolve attachment through VkSubpassDescriptionDepthStencilResolveKHR: This
1325 // requires an extension that's not very well supported.
1326 //
1327 // The first method is implemented in this function.
1328
1329 // Possible ways to blit color, depth or stencil are:
1330 //
1331 // - vkCmdBlitImage: This function works if the source and destination formats have the blit
1332 // feature.
1333 // - Manual blit: A shader can sample from the source image and write it to the destination.
1334 //
1335 // The first method has a serious shortcoming. GLES allows blit parameters to exceed the
1336 // source or destination boundaries. The actual blit is clipped to these limits, but the
1337 // scaling applied is determined solely by the input areas. Vulkan requires the blit parameters
1338 // to be within the source and destination bounds. This makes it hard to keep the scaling
1339 // constant.
1340 //
1341 // The second method is implemented in this function, which shares code with the resolve method.
1342
1343 ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
1344
1345 bool isResolve = src->getSamples() > 1;
1346
1347 BlitResolveShaderParams shaderParams;
1348 if (isResolve)
1349 {
1350 CalculateResolveOffset(params, shaderParams.offset.resolve);
1351 }
1352 else
1353 {
1354 CalculateBlitOffset(params, shaderParams.offset.blit);
1355 }
1356 shaderParams.stretch[0] = params.stretch[0];
1357 shaderParams.stretch[1] = params.stretch[1];
1358 shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
1359 shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
1360 shaderParams.srcLayer = params.srcLayer;
1361 shaderParams.samples = src->getSamples();
1362 shaderParams.invSamples = 1.0f / shaderParams.samples;
1363 shaderParams.outputMask =
1364 static_cast<uint32_t>(framebuffer->getState().getEnabledDrawBuffers().to_ulong());
1365 shaderParams.flipX = params.flipX;
1366 shaderParams.flipY = params.flipY;
1367
1368 bool blitColor = srcColorView != nullptr;
1369 bool blitDepth = srcDepthView != nullptr;
1370 bool blitStencil = srcStencilView != nullptr;
1371
1372 // Either color is blitted/resolved or depth/stencil, but not both.
1373 ASSERT(blitColor != (blitDepth || blitStencil));
1374
1375 // Linear sampling is only valid with color blitting.
1376 ASSERT((blitColor && !isResolve) || !params.linear);
1377
1378 uint32_t flags = GetBlitResolveFlags(blitColor, blitDepth, blitStencil, src->getFormat());
1379 flags |= src->getLayerCount() > 1 ? BlitResolve_frag::kSrcIsArray : 0;
1380 flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
1381
1382 VkDescriptorSet descriptorSet;
1383 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1384 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BlitResolve, &descriptorPoolBinding,
1385 &descriptorSet));
1386
1387 constexpr VkColorComponentFlags kAllColorComponents =
1388 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
1389 VK_COLOR_COMPONENT_A_BIT;
1390
1391 vk::GraphicsPipelineDesc pipelineDesc;
1392 pipelineDesc.initDefaults();
1393 if (blitColor)
1394 {
1395 pipelineDesc.setColorWriteMask(kAllColorComponents,
1396 framebuffer->getEmulatedAlphaAttachmentMask());
1397 }
1398 else
1399 {
1400 pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask());
1401 }
1402 pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
1403 pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
1404 pipelineDesc.setDepthTestEnabled(blitDepth);
1405 pipelineDesc.setDepthWriteEnabled(blitDepth);
1406 pipelineDesc.setDepthFunc(VK_COMPARE_OP_ALWAYS);
1407
1408 if (blitStencil)
1409 {
1410 ASSERT(contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled);
1411
1412 const uint8_t completeMask = 0xFF;
1413 const uint8_t unusedReference = 0x00;
1414
1415 pipelineDesc.setStencilTestEnabled(true);
1416 pipelineDesc.setStencilFrontFuncs(unusedReference, VK_COMPARE_OP_ALWAYS, completeMask);
1417 pipelineDesc.setStencilBackFuncs(unusedReference, VK_COMPARE_OP_ALWAYS, completeMask);
1418 pipelineDesc.setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1419 VK_STENCIL_OP_REPLACE);
1420 pipelineDesc.setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1421 VK_STENCIL_OP_REPLACE);
1422 pipelineDesc.setStencilFrontWriteMask(completeMask);
1423 pipelineDesc.setStencilBackWriteMask(completeMask);
1424 }
1425
1426 VkViewport viewport;
1427 gl::Rectangle completeRenderArea = framebuffer->getCompleteRenderArea();
1428 gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, completeRenderArea.height, &viewport);
1429 pipelineDesc.setViewport(viewport);
1430
1431 pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
1432
1433 // Change source layout outside render pass
1434 ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
1435 src));
1436
1437 vk::CommandBuffer *commandBuffer;
1438 ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer));
1439
1440 VkDescriptorImageInfo imageInfos[2] = {};
1441
1442 if (blitColor)
1443 {
1444 imageInfos[0].imageView = srcColorView->getHandle();
1445 imageInfos[0].imageLayout = src->getCurrentLayout();
1446 }
1447 if (blitDepth)
1448 {
1449 imageInfos[0].imageView = srcDepthView->getHandle();
1450 imageInfos[0].imageLayout = src->getCurrentLayout();
1451 }
1452 if (blitStencil)
1453 {
1454 imageInfos[1].imageView = srcStencilView->getHandle();
1455 imageInfos[1].imageLayout = src->getCurrentLayout();
1456 }
1457
1458 VkDescriptorImageInfo samplerInfo = {};
1459 samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
1460
1461 VkWriteDescriptorSet writeInfos[3] = {};
1462 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1463 writeInfos[0].dstSet = descriptorSet;
1464 writeInfos[0].dstBinding = kBlitResolveColorOrDepthBinding;
1465 writeInfos[0].descriptorCount = 1;
1466 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1467 writeInfos[0].pImageInfo = &imageInfos[0];
1468
1469 writeInfos[1] = writeInfos[0];
1470 writeInfos[1].dstBinding = kBlitResolveStencilBinding;
1471 writeInfos[1].pImageInfo = &imageInfos[1];
1472
1473 writeInfos[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1474 writeInfos[2].dstSet = descriptorSet;
1475 writeInfos[2].dstBinding = kBlitResolveSamplerBinding;
1476 writeInfos[2].descriptorCount = 1;
1477 writeInfos[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
1478 writeInfos[2].pImageInfo = &samplerInfo;
1479
1480 // If resolving color, there's one write info; index 0
1481 // If resolving depth, write info index 0 must be written
1482 // If resolving stencil, write info index 1 must also be written
1483 //
1484 // Note again that resolving color and depth/stencil are mutually exclusive here.
1485 uint32_t writeInfoOffset = blitDepth || blitColor ? 0 : 1;
1486 uint32_t writeInfoCount = blitColor + blitDepth + blitStencil;
1487
1488 vkUpdateDescriptorSets(contextVk->getDevice(), writeInfoCount, writeInfos + writeInfoOffset, 0,
1489 nullptr);
1490 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfos[2], 0, nullptr);
1491
1492 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
1493 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
1494 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
1495 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
1496 ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
1497
1498 ANGLE_TRY(setupProgram(contextVk, Function::BlitResolve, fragmentShader, vertexShader,
1499 &mBlitResolvePrograms[flags], &pipelineDesc, descriptorSet,
1500 &shaderParams, sizeof(shaderParams), commandBuffer));
1501 commandBuffer->draw(6, 0);
1502 descriptorPoolBinding.reset();
1503
1504 return angle::Result::Continue;
1505 }
1506
stencilBlitResolveNoShaderExport(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)1507 angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
1508 FramebufferVk *framebuffer,
1509 vk::ImageHelper *src,
1510 const vk::ImageView *srcStencilView,
1511 const BlitResolveParameters ¶ms)
1512 {
1513 // When VK_EXT_shader_stencil_export is not available, stencil is blitted/resolved into a
1514 // temporary buffer which is then copied into the stencil aspect of the image.
1515
1516 ANGLE_TRY(ensureBlitResolveStencilNoExportResourcesInitialized(contextVk));
1517
1518 bool isResolve = src->getSamples() > 1;
1519
1520 VkDescriptorSet descriptorSet;
1521 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1522 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BlitResolveStencilNoExport,
1523 &descriptorPoolBinding, &descriptorSet));
1524
1525 // Create a temporary buffer to blit/resolve stencil into.
1526 vk::RendererScoped<vk::BufferHelper> blitBuffer(contextVk->getRenderer());
1527
1528 uint32_t bufferRowLengthInUints = UnsignedCeilDivide(params.blitArea.width, sizeof(uint32_t));
1529 VkDeviceSize bufferSize = bufferRowLengthInUints * sizeof(uint32_t) * params.blitArea.height;
1530
1531 VkBufferCreateInfo blitBufferInfo = {};
1532 blitBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1533 blitBufferInfo.flags = 0;
1534 blitBufferInfo.size = bufferSize;
1535 blitBufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1536 blitBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1537 blitBufferInfo.queueFamilyIndexCount = 0;
1538 blitBufferInfo.pQueueFamilyIndices = nullptr;
1539
1540 ANGLE_TRY(
1541 blitBuffer.get().init(contextVk, blitBufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
1542 blitBuffer.get().retain(&contextVk->getResourceUseList());
1543
1544 BlitResolveStencilNoExportShaderParams shaderParams;
1545 if (isResolve)
1546 {
1547 CalculateResolveOffset(params, shaderParams.offset.resolve);
1548 }
1549 else
1550 {
1551 CalculateBlitOffset(params, shaderParams.offset.blit);
1552 }
1553 shaderParams.stretch[0] = params.stretch[0];
1554 shaderParams.stretch[1] = params.stretch[1];
1555 shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
1556 shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
1557 shaderParams.srcLayer = params.srcLayer;
1558 shaderParams.srcWidth = params.srcExtents[0];
1559 shaderParams.destPitch = bufferRowLengthInUints;
1560 shaderParams.blitArea[0] = params.blitArea.x;
1561 shaderParams.blitArea[1] = params.blitArea.y;
1562 shaderParams.blitArea[2] = params.blitArea.width;
1563 shaderParams.blitArea[3] = params.blitArea.height;
1564 shaderParams.flipX = params.flipX;
1565 shaderParams.flipY = params.flipY;
1566
1567 // Linear sampling is only valid with color blitting.
1568 ASSERT(!params.linear);
1569
1570 uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0;
1571 flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
1572
1573 RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
1574 ASSERT(depthStencilRenderTarget != nullptr);
1575 vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImage();
1576
1577 vk::CommandBuffer *commandBuffer;
1578 // Change source layout prior to computation.
1579 ANGLE_TRY(
1580 contextVk->onImageRead(src->getAspectFlags(), vk::ImageLayout::ComputeShaderReadOnly, src));
1581 ANGLE_TRY(contextVk->onImageWrite(depthStencilImage->getAspectFlags(),
1582 vk::ImageLayout::TransferDst, depthStencilImage));
1583 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1584
1585 // Blit/resolve stencil into the buffer.
1586 VkDescriptorImageInfo imageInfo = {};
1587 imageInfo.imageView = srcStencilView->getHandle();
1588 imageInfo.imageLayout = src->getCurrentLayout();
1589
1590 VkDescriptorBufferInfo bufferInfo = {};
1591 bufferInfo.buffer = blitBuffer.get().getBuffer().getHandle();
1592 bufferInfo.offset = 0;
1593 bufferInfo.range = VK_WHOLE_SIZE;
1594
1595 VkDescriptorImageInfo samplerInfo = {};
1596 samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
1597
1598 VkWriteDescriptorSet writeInfos[3] = {};
1599 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1600 writeInfos[0].dstSet = descriptorSet;
1601 writeInfos[0].dstBinding = kBlitResolveStencilNoExportDestBinding;
1602 writeInfos[0].descriptorCount = 1;
1603 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1604 writeInfos[0].pBufferInfo = &bufferInfo;
1605
1606 writeInfos[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1607 writeInfos[1].dstSet = descriptorSet;
1608 writeInfos[1].dstBinding = kBlitResolveStencilNoExportSrcBinding;
1609 writeInfos[1].descriptorCount = 1;
1610 writeInfos[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1611 writeInfos[1].pImageInfo = &imageInfo;
1612
1613 writeInfos[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1614 writeInfos[2].dstSet = descriptorSet;
1615 writeInfos[2].dstBinding = kBlitResolveStencilNoExportSamplerBinding;
1616 writeInfos[2].descriptorCount = 1;
1617 writeInfos[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
1618 writeInfos[2].pImageInfo = &samplerInfo;
1619
1620 vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
1621
1622 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1623 ANGLE_TRY(contextVk->getShaderLibrary().getBlitResolveStencilNoExport_comp(contextVk, flags,
1624 &shader));
1625
1626 ANGLE_TRY(setupProgram(contextVk, Function::BlitResolveStencilNoExport, shader, nullptr,
1627 &mBlitResolveStencilNoExportPrograms[flags], nullptr, descriptorSet,
1628 &shaderParams, sizeof(shaderParams), commandBuffer));
1629 commandBuffer->dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
1630 UnsignedCeilDivide(params.blitArea.height, 8), 1);
1631 descriptorPoolBinding.reset();
1632
1633 // Add a barrier prior to copy.
1634 VkMemoryBarrier memoryBarrier = {};
1635 memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
1636 memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1637 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1638
1639 // Use the all pipe stage to keep the state management simple.
1640 commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1641 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memoryBarrier, 0, nullptr,
1642 0, nullptr);
1643
1644 // Copy the resulting buffer into dest.
1645 VkBufferImageCopy region = {};
1646 region.bufferOffset = 0;
1647 region.bufferRowLength = bufferRowLengthInUints * sizeof(uint32_t);
1648 region.bufferImageHeight = params.blitArea.height;
1649 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
1650 region.imageSubresource.mipLevel = depthStencilRenderTarget->getLevelIndex();
1651 region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex();
1652 region.imageSubresource.layerCount = 1;
1653 region.imageOffset.x = params.blitArea.x;
1654 region.imageOffset.y = params.blitArea.y;
1655 region.imageOffset.z = 0;
1656 region.imageExtent.width = params.blitArea.width;
1657 region.imageExtent.height = params.blitArea.height;
1658 region.imageExtent.depth = 1;
1659
1660 commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(),
1661 depthStencilImage->getImage(),
1662 depthStencilImage->getCurrentLayout(), 1, ®ion);
1663
1664 return angle::Result::Continue;
1665 }
1666
copyImage(ContextVk * contextVk,vk::ImageHelper * dest,const vk::ImageView * destView,vk::ImageHelper * src,const vk::ImageView * srcView,const CopyImageParameters & params)1667 angle::Result UtilsVk::copyImage(ContextVk *contextVk,
1668 vk::ImageHelper *dest,
1669 const vk::ImageView *destView,
1670 vk::ImageHelper *src,
1671 const vk::ImageView *srcView,
1672 const CopyImageParameters ¶ms)
1673 {
1674 ANGLE_TRY(ensureImageCopyResourcesInitialized(contextVk));
1675
1676 const vk::Format &srcFormat = src->getFormat();
1677 const vk::Format &dstFormat = dest->getFormat();
1678 const angle::Format &dstIntendedFormat = dstFormat.intendedFormat();
1679
1680 ImageCopyShaderParams shaderParams;
1681 shaderParams.flipY = params.srcFlipY || params.destFlipY;
1682 shaderParams.premultiplyAlpha = params.srcPremultiplyAlpha;
1683 shaderParams.unmultiplyAlpha = params.srcUnmultiplyAlpha;
1684 shaderParams.destHasLuminance = dstIntendedFormat.luminanceBits > 0;
1685 shaderParams.destIsAlpha = dstIntendedFormat.isLUMA() && dstIntendedFormat.alphaBits > 0;
1686 shaderParams.destDefaultChannelsMask = GetFormatDefaultChannelMask(dstFormat);
1687 shaderParams.srcMip = params.srcMip;
1688 shaderParams.srcLayer = params.srcLayer;
1689 shaderParams.srcOffset[0] = params.srcOffset[0];
1690 shaderParams.srcOffset[1] = params.srcOffset[1];
1691 shaderParams.destOffset[0] = params.destOffset[0];
1692 shaderParams.destOffset[1] = params.destOffset[1];
1693
1694 ASSERT(!(params.srcFlipY && params.destFlipY));
1695 if (params.srcFlipY)
1696 {
1697 // If viewport is flipped, the shader expects srcOffset[1] to have the
1698 // last row's index instead of the first's.
1699 shaderParams.srcOffset[1] = params.srcHeight - params.srcOffset[1] - 1;
1700 }
1701 else if (params.destFlipY)
1702 {
1703 // If image is flipped during copy, the shader uses the same code path as above,
1704 // with srcOffset being set to the last row's index instead of the first's.
1705 shaderParams.srcOffset[1] = params.srcOffset[1] + params.srcExtents[1] - 1;
1706 }
1707
1708 uint32_t flags = GetImageCopyFlags(srcFormat, dstFormat);
1709 flags |= src->getLayerCount() > 1 ? ImageCopy_frag::kSrcIsArray : 0;
1710
1711 VkDescriptorSet descriptorSet;
1712 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1713 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ImageCopy, &descriptorPoolBinding,
1714 &descriptorSet));
1715
1716 vk::RenderPassDesc renderPassDesc;
1717 renderPassDesc.setSamples(dest->getSamples());
1718 renderPassDesc.packColorAttachment(0, dstFormat.intendedFormatID);
1719
1720 // Multisampled copy is not yet supported.
1721 ASSERT(src->getSamples() == 1 && dest->getSamples() == 1);
1722
1723 vk::GraphicsPipelineDesc pipelineDesc;
1724 pipelineDesc.initDefaults();
1725 pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
1726 pipelineDesc.setRenderPassDesc(renderPassDesc);
1727
1728 gl::Rectangle renderArea;
1729 renderArea.x = params.destOffset[0];
1730 renderArea.y = params.destOffset[1];
1731 renderArea.width = params.srcExtents[0];
1732 renderArea.height = params.srcExtents[1];
1733
1734 VkViewport viewport;
1735 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, dest->getExtents().height, &viewport);
1736 pipelineDesc.setViewport(viewport);
1737
1738 VkRect2D scissor = gl_vk::GetRect(renderArea);
1739 pipelineDesc.setScissor(scissor);
1740
1741 // Change source layout outside render pass
1742 ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
1743 vk::ImageLayout::FragmentShaderReadOnly, src));
1744 ANGLE_TRY(
1745 contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment, dest));
1746
1747 vk::CommandBuffer *commandBuffer;
1748 ANGLE_TRY(
1749 startRenderPass(contextVk, dest, destView, renderPassDesc, renderArea, &commandBuffer));
1750
1751 VkDescriptorImageInfo imageInfo = {};
1752 imageInfo.imageView = srcView->getHandle();
1753 imageInfo.imageLayout = src->getCurrentLayout();
1754
1755 VkWriteDescriptorSet writeInfo = {};
1756 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1757 writeInfo.dstSet = descriptorSet;
1758 writeInfo.dstBinding = kImageCopySourceBinding;
1759 writeInfo.descriptorCount = 1;
1760 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1761 writeInfo.pImageInfo = &imageInfo;
1762
1763 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1764
1765 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
1766 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
1767 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
1768 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
1769 ANGLE_TRY(shaderLibrary.getImageCopy_frag(contextVk, flags, &fragmentShader));
1770
1771 ANGLE_TRY(setupProgram(contextVk, Function::ImageCopy, fragmentShader, vertexShader,
1772 &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
1773 sizeof(shaderParams), commandBuffer));
1774 commandBuffer->draw(6, 0);
1775 descriptorPoolBinding.reset();
1776
1777 return angle::Result::Continue;
1778 }
1779
cullOverlayWidgets(ContextVk * contextVk,vk::BufferHelper * enabledWidgetsBuffer,vk::ImageHelper * dest,const vk::ImageView * destView,const OverlayCullParameters & params)1780 angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk,
1781 vk::BufferHelper *enabledWidgetsBuffer,
1782 vk::ImageHelper *dest,
1783 const vk::ImageView *destView,
1784 const OverlayCullParameters ¶ms)
1785 {
1786 ANGLE_TRY(ensureOverlayCullResourcesInitialized(contextVk));
1787
1788 ASSERT(params.subgroupSize[0] == 8 &&
1789 (params.subgroupSize[1] == 8 || params.subgroupSize[1] == 4));
1790 uint32_t flags =
1791 params.subgroupSize[1] == 8 ? OverlayCull_comp::kIs8x8 : OverlayCull_comp::kIs8x4;
1792 if (params.supportsSubgroupBallot)
1793 {
1794 flags |= OverlayCull_comp::kSupportsBallot;
1795 }
1796 else if (params.supportsSubgroupBallot)
1797 {
1798 flags |= OverlayCull_comp::kSupportsArithmetic;
1799 }
1800 else
1801 {
1802 flags |= OverlayCull_comp::kSupportsNone;
1803 }
1804
1805 VkDescriptorSet descriptorSet;
1806 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1807 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::OverlayCull, &descriptorPoolBinding,
1808 &descriptorSet));
1809
1810 vk::CommandBuffer *commandBuffer;
1811 ANGLE_TRY(contextVk->onBufferComputeShaderRead(enabledWidgetsBuffer));
1812 ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
1813 vk::ImageLayout::ComputeShaderWrite, dest));
1814 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1815
1816 VkDescriptorImageInfo imageInfo = {};
1817 imageInfo.imageView = destView->getHandle();
1818 imageInfo.imageLayout = dest->getCurrentLayout();
1819
1820 VkDescriptorBufferInfo bufferInfo = {};
1821 bufferInfo.buffer = enabledWidgetsBuffer->getBuffer().getHandle();
1822 bufferInfo.offset = 0;
1823 bufferInfo.range = VK_WHOLE_SIZE;
1824
1825 VkWriteDescriptorSet writeInfos[2] = {};
1826 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1827 writeInfos[0].dstSet = descriptorSet;
1828 writeInfos[0].dstBinding = kOverlayCullCulledWidgetsBinding;
1829 writeInfos[0].descriptorCount = 1;
1830 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1831 writeInfos[0].pImageInfo = &imageInfo;
1832
1833 writeInfos[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1834 writeInfos[1].dstSet = descriptorSet;
1835 writeInfos[1].dstBinding = kOverlayCullWidgetCoordsBinding;
1836 writeInfos[1].descriptorCount = 1;
1837 writeInfos[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1838 writeInfos[1].pBufferInfo = &bufferInfo;
1839
1840 vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
1841
1842 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1843 ANGLE_TRY(contextVk->getShaderLibrary().getOverlayCull_comp(contextVk, flags, &shader));
1844
1845 ANGLE_TRY(setupProgram(contextVk, Function::OverlayCull, shader, nullptr,
1846 &mOverlayCullPrograms[flags], nullptr, descriptorSet, nullptr, 0,
1847 commandBuffer));
1848 commandBuffer->dispatch(dest->getExtents().width, dest->getExtents().height, 1);
1849 descriptorPoolBinding.reset();
1850
1851 return angle::Result::Continue;
1852 }
1853
drawOverlay(ContextVk * contextVk,vk::BufferHelper * textWidgetsBuffer,vk::BufferHelper * graphWidgetsBuffer,vk::ImageHelper * font,const vk::ImageView * fontView,vk::ImageHelper * culledWidgets,const vk::ImageView * culledWidgetsView,vk::ImageHelper * dest,const vk::ImageView * destView,const OverlayDrawParameters & params)1854 angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
1855 vk::BufferHelper *textWidgetsBuffer,
1856 vk::BufferHelper *graphWidgetsBuffer,
1857 vk::ImageHelper *font,
1858 const vk::ImageView *fontView,
1859 vk::ImageHelper *culledWidgets,
1860 const vk::ImageView *culledWidgetsView,
1861 vk::ImageHelper *dest,
1862 const vk::ImageView *destView,
1863 const OverlayDrawParameters ¶ms)
1864 {
1865 ANGLE_TRY(ensureOverlayDrawResourcesInitialized(contextVk));
1866
1867 OverlayDrawShaderParams shaderParams;
1868 shaderParams.outputSize[0] = dest->getExtents().width;
1869 shaderParams.outputSize[1] = dest->getExtents().height;
1870
1871 ASSERT(params.subgroupSize[0] == 8 &&
1872 (params.subgroupSize[1] == 8 || params.subgroupSize[1] == 4));
1873 uint32_t flags =
1874 params.subgroupSize[1] == 8 ? OverlayDraw_comp::kIs8x8 : OverlayDraw_comp::kIs8x4;
1875
1876 VkDescriptorSet descriptorSet;
1877 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1878 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::OverlayDraw, &descriptorPoolBinding,
1879 &descriptorSet));
1880
1881 vk::CommandBuffer *commandBuffer;
1882 ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
1883 vk::ImageLayout::ComputeShaderWrite, dest));
1884 ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
1885 vk::ImageLayout::ComputeShaderReadOnly, culledWidgets));
1886 ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
1887 vk::ImageLayout::ComputeShaderReadOnly, font));
1888 ANGLE_TRY(contextVk->onBufferComputeShaderRead(textWidgetsBuffer));
1889 ANGLE_TRY(contextVk->onBufferComputeShaderRead(graphWidgetsBuffer));
1890
1891 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1892
1893 VkDescriptorImageInfo imageInfos[3] = {};
1894 imageInfos[0].imageView = destView->getHandle();
1895 imageInfos[0].imageLayout = dest->getCurrentLayout();
1896
1897 imageInfos[1].imageView = culledWidgetsView->getHandle();
1898 imageInfos[1].imageLayout = culledWidgets->getCurrentLayout();
1899
1900 imageInfos[2].imageView = fontView->getHandle();
1901 imageInfos[2].imageLayout = font->getCurrentLayout();
1902
1903 VkDescriptorBufferInfo bufferInfos[2] = {};
1904 bufferInfos[0].buffer = textWidgetsBuffer->getBuffer().getHandle();
1905 bufferInfos[0].offset = 0;
1906 bufferInfos[0].range = VK_WHOLE_SIZE;
1907
1908 bufferInfos[1].buffer = graphWidgetsBuffer->getBuffer().getHandle();
1909 bufferInfos[1].offset = 0;
1910 bufferInfos[1].range = VK_WHOLE_SIZE;
1911
1912 VkWriteDescriptorSet writeInfos[5] = {};
1913 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1914 writeInfos[0].dstSet = descriptorSet;
1915 writeInfos[0].dstBinding = kOverlayDrawOutputBinding;
1916 writeInfos[0].descriptorCount = 1;
1917 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1918 writeInfos[0].pImageInfo = &imageInfos[0];
1919
1920 writeInfos[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1921 writeInfos[1].dstSet = descriptorSet;
1922 writeInfos[1].dstBinding = kOverlayDrawCulledWidgetsBinding;
1923 writeInfos[1].descriptorCount = 1;
1924 writeInfos[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1925 writeInfos[1].pImageInfo = &imageInfos[1];
1926
1927 writeInfos[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1928 writeInfos[2].dstSet = descriptorSet;
1929 writeInfos[2].dstBinding = kOverlayDrawFontBinding;
1930 writeInfos[2].descriptorCount = 1;
1931 writeInfos[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1932 writeInfos[2].pImageInfo = &imageInfos[2];
1933
1934 writeInfos[3].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1935 writeInfos[3].dstSet = descriptorSet;
1936 writeInfos[3].dstBinding = kOverlayDrawTextWidgetsBinding;
1937 writeInfos[3].descriptorCount = 1;
1938 writeInfos[3].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1939 writeInfos[3].pBufferInfo = &bufferInfos[0];
1940
1941 writeInfos[4] = writeInfos[3];
1942 writeInfos[4].dstBinding = kOverlayDrawGraphWidgetsBinding;
1943 writeInfos[4].pBufferInfo = &bufferInfos[1];
1944
1945 vkUpdateDescriptorSets(contextVk->getDevice(), 5, writeInfos, 0, nullptr);
1946
1947 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1948 ANGLE_TRY(contextVk->getShaderLibrary().getOverlayDraw_comp(contextVk, flags, &shader));
1949
1950 ANGLE_TRY(setupProgram(contextVk, Function::OverlayDraw, shader, nullptr,
1951 &mOverlayDrawPrograms[flags], nullptr, descriptorSet, &shaderParams,
1952 sizeof(shaderParams), commandBuffer));
1953
1954 // Every pixel of culledWidgets corresponds to one workgroup, so we can use that as dispatch
1955 // size.
1956 commandBuffer->dispatch(culledWidgets->getExtents().width, culledWidgets->getExtents().height,
1957 1);
1958 descriptorPoolBinding.reset();
1959
1960 return angle::Result::Continue;
1961 }
1962
allocateDescriptorSet(ContextVk * contextVk,Function function,vk::RefCountedDescriptorPoolBinding * bindingOut,VkDescriptorSet * descriptorSetOut)1963 angle::Result UtilsVk::allocateDescriptorSet(ContextVk *contextVk,
1964 Function function,
1965 vk::RefCountedDescriptorPoolBinding *bindingOut,
1966 VkDescriptorSet *descriptorSetOut)
1967 {
1968 ANGLE_TRY(mDescriptorPools[function].allocateSets(
1969 contextVk, mDescriptorSetLayouts[function][kSetIndex].get().ptr(), 1, bindingOut,
1970 descriptorSetOut));
1971 bindingOut->get().updateSerial(contextVk->getCurrentQueueSerial());
1972 return angle::Result::Continue;
1973 }
1974
ClearFramebufferParameters()1975 UtilsVk::ClearFramebufferParameters::ClearFramebufferParameters()
1976 : clearColor(false),
1977 clearStencil(false),
1978 stencilMask(0),
1979 colorMaskFlags(0),
1980 colorAttachmentIndexGL(0),
1981 colorFormat(nullptr),
1982 colorClearValue{},
1983 stencilClearValue(0)
1984 {}
1985
1986 } // namespace rx
1987