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->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, 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->onBufferRead(VK_ACCESS_SHADER_READ_BIT, src));
849 ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, 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->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndirectBuf));
911 ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndexBuf));
912 ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndirectBuf));
913 ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, 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->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer));
979 ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndexBuffer));
980 ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, dstIndirectBuffer));
981 ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, 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->onBufferRead(VK_ACCESS_SHADER_READ_BIT, srcIndirectBuffer));
1039 ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, destIndirectBuffer));
1040 ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, 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->onBufferRead(VK_ACCESS_SHADER_READ_BIT, src));
1095 ANGLE_TRY(contextVk->onBufferWrite(VK_ACCESS_SHADER_WRITE_BIT, 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 std::vector<VkClearValue> clearValues = {{}};
1190 ASSERT(clearValues.size() == 1);
1191
1192 renderPassAttachmentOps.initWithStore(0, VK_ATTACHMENT_LOAD_OP_LOAD,
1193 vk::ImageLayout::ColorAttachment,
1194 vk::ImageLayout::ColorAttachment);
1195
1196 ANGLE_TRY(contextVk->flushAndBeginRenderPass(framebuffer, renderArea, renderPassDesc,
1197 renderPassAttachmentOps, clearValues,
1198 commandBufferOut));
1199
1200 contextVk->addGarbage(&framebuffer);
1201
1202 return angle::Result::Continue;
1203 }
1204
clearFramebuffer(ContextVk * contextVk,FramebufferVk * framebuffer,const ClearFramebufferParameters & params)1205 angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
1206 FramebufferVk *framebuffer,
1207 const ClearFramebufferParameters ¶ms)
1208 {
1209 ANGLE_TRY(ensureImageClearResourcesInitialized(contextVk));
1210
1211 const gl::Rectangle &scissoredRenderArea = params.clearArea;
1212
1213 vk::CommandBuffer *commandBuffer;
1214 ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, scissoredRenderArea, &commandBuffer));
1215
1216 ImageClearShaderParams shaderParams;
1217 shaderParams.clearValue = params.colorClearValue;
1218
1219 vk::GraphicsPipelineDesc pipelineDesc;
1220 pipelineDesc.initDefaults();
1221 pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
1222 pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask());
1223 pipelineDesc.setSingleColorWriteMask(params.colorAttachmentIndexGL, params.colorMaskFlags);
1224 pipelineDesc.setRasterizationSamples(framebuffer->getSamples());
1225 pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
1226 // Note: depth test is disabled by default so this should be unnecessary, but works around an
1227 // Intel bug on windows. http://anglebug.com/3348
1228 pipelineDesc.setDepthWriteEnabled(false);
1229
1230 // Clear stencil by enabling stencil write with the right mask.
1231 if (params.clearStencil)
1232 {
1233 const uint8_t compareMask = 0xFF;
1234 const uint8_t clearStencilValue = params.stencilClearValue;
1235
1236 pipelineDesc.setStencilTestEnabled(true);
1237 pipelineDesc.setStencilFrontFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
1238 pipelineDesc.setStencilBackFuncs(clearStencilValue, VK_COMPARE_OP_ALWAYS, compareMask);
1239 pipelineDesc.setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1240 VK_STENCIL_OP_REPLACE);
1241 pipelineDesc.setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1242 VK_STENCIL_OP_REPLACE);
1243 pipelineDesc.setStencilFrontWriteMask(params.stencilMask);
1244 pipelineDesc.setStencilBackWriteMask(params.stencilMask);
1245 }
1246
1247 VkViewport viewport;
1248 gl::Rectangle completeRenderArea = framebuffer->getCompleteRenderArea();
1249 bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
1250 gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, completeRenderArea.height,
1251 &viewport);
1252 pipelineDesc.setViewport(viewport);
1253
1254 pipelineDesc.setScissor(gl_vk::GetRect(params.clearArea));
1255
1256 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
1257 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
1258 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
1259 vk::ShaderProgramHelper *imageClearProgram = &mImageClearProgramVSOnly;
1260
1261 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
1262 if (params.clearColor)
1263 {
1264 uint32_t flags = GetImageClearFlags(*params.colorFormat, params.colorAttachmentIndexGL);
1265 ANGLE_TRY(shaderLibrary.getImageClear_frag(contextVk, flags, &fragmentShader));
1266 imageClearProgram = &mImageClearProgram[flags];
1267 }
1268
1269 ANGLE_TRY(setupProgram(contextVk, Function::ImageClear, fragmentShader, vertexShader,
1270 imageClearProgram, &pipelineDesc, VK_NULL_HANDLE, &shaderParams,
1271 sizeof(shaderParams), commandBuffer));
1272 commandBuffer->draw(6, 0);
1273 return angle::Result::Continue;
1274 }
1275
colorBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcView,const BlitResolveParameters & params)1276 angle::Result UtilsVk::colorBlitResolve(ContextVk *contextVk,
1277 FramebufferVk *framebuffer,
1278 vk::ImageHelper *src,
1279 const vk::ImageView *srcView,
1280 const BlitResolveParameters ¶ms)
1281 {
1282 return blitResolveImpl(contextVk, framebuffer, src, srcView, nullptr, nullptr, params);
1283 }
1284
depthStencilBlitResolve(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)1285 angle::Result UtilsVk::depthStencilBlitResolve(ContextVk *contextVk,
1286 FramebufferVk *framebuffer,
1287 vk::ImageHelper *src,
1288 const vk::ImageView *srcDepthView,
1289 const vk::ImageView *srcStencilView,
1290 const BlitResolveParameters ¶ms)
1291 {
1292 return blitResolveImpl(contextVk, framebuffer, src, nullptr, srcDepthView, srcStencilView,
1293 params);
1294 }
1295
blitResolveImpl(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcColorView,const vk::ImageView * srcDepthView,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)1296 angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
1297 FramebufferVk *framebuffer,
1298 vk::ImageHelper *src,
1299 const vk::ImageView *srcColorView,
1300 const vk::ImageView *srcDepthView,
1301 const vk::ImageView *srcStencilView,
1302 const BlitResolveParameters ¶ms)
1303 {
1304 // Possible ways to resolve color are:
1305 //
1306 // - vkCmdResolveImage: This is by far the easiest method, but lacks the ability to flip
1307 // images during resolve.
1308 // - Manual resolve: A shader can read all samples from input, average them and output.
1309 // - Using subpass resolve attachment: A shader can transform the sample colors from source to
1310 // destination coordinates and the subpass resolve would finish the job.
1311 //
1312 // The first method is unable to handle flipping, so it's not generally applicable. The last
1313 // method would have been great were we able to modify the last render pass that rendered into
1314 // source, but still wouldn't be able to handle flipping. The second method is implemented in
1315 // this function for complete control.
1316
1317 // Possible ways to resolve depth/stencil are:
1318 //
1319 // - Manual resolve: A shader can read a samples from input and choose that for output.
1320 // - Using subpass resolve attachment through VkSubpassDescriptionDepthStencilResolveKHR: This
1321 // requires an extension that's not very well supported.
1322 //
1323 // The first method is implemented in this function.
1324
1325 // Possible ways to blit color, depth or stencil are:
1326 //
1327 // - vkCmdBlitImage: This function works if the source and destination formats have the blit
1328 // feature.
1329 // - Manual blit: A shader can sample from the source image and write it to the destination.
1330 //
1331 // The first method has a serious shortcoming. GLES allows blit parameters to exceed the
1332 // source or destination boundaries. The actual blit is clipped to these limits, but the
1333 // scaling applied is determined solely by the input areas. Vulkan requires the blit parameters
1334 // to be within the source and destination bounds. This makes it hard to keep the scaling
1335 // constant.
1336 //
1337 // The second method is implemented in this function, which shares code with the resolve method.
1338
1339 ANGLE_TRY(ensureBlitResolveResourcesInitialized(contextVk));
1340
1341 bool isResolve = src->getSamples() > 1;
1342
1343 BlitResolveShaderParams shaderParams;
1344 if (isResolve)
1345 {
1346 CalculateResolveOffset(params, shaderParams.offset.resolve);
1347 }
1348 else
1349 {
1350 CalculateBlitOffset(params, shaderParams.offset.blit);
1351 }
1352 shaderParams.stretch[0] = params.stretch[0];
1353 shaderParams.stretch[1] = params.stretch[1];
1354 shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
1355 shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
1356 shaderParams.srcLayer = params.srcLayer;
1357 shaderParams.samples = src->getSamples();
1358 shaderParams.invSamples = 1.0f / shaderParams.samples;
1359 shaderParams.outputMask =
1360 static_cast<uint32_t>(framebuffer->getState().getEnabledDrawBuffers().to_ulong());
1361 shaderParams.flipX = params.flipX;
1362 shaderParams.flipY = params.flipY;
1363
1364 bool blitColor = srcColorView != nullptr;
1365 bool blitDepth = srcDepthView != nullptr;
1366 bool blitStencil = srcStencilView != nullptr;
1367
1368 // Either color is blitted/resolved or depth/stencil, but not both.
1369 ASSERT(blitColor != (blitDepth || blitStencil));
1370
1371 // Linear sampling is only valid with color blitting.
1372 ASSERT((blitColor && !isResolve) || !params.linear);
1373
1374 uint32_t flags = GetBlitResolveFlags(blitColor, blitDepth, blitStencil, src->getFormat());
1375 flags |= src->getLayerCount() > 1 ? BlitResolve_frag::kSrcIsArray : 0;
1376 flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
1377
1378 VkDescriptorSet descriptorSet;
1379 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1380 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BlitResolve, &descriptorPoolBinding,
1381 &descriptorSet));
1382
1383 constexpr VkColorComponentFlags kAllColorComponents =
1384 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT |
1385 VK_COLOR_COMPONENT_A_BIT;
1386
1387 vk::GraphicsPipelineDesc pipelineDesc;
1388 pipelineDesc.initDefaults();
1389 if (blitColor)
1390 {
1391 pipelineDesc.setColorWriteMask(kAllColorComponents,
1392 framebuffer->getEmulatedAlphaAttachmentMask());
1393 }
1394 else
1395 {
1396 pipelineDesc.setColorWriteMask(0, gl::DrawBufferMask());
1397 }
1398 pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
1399 pipelineDesc.setRenderPassDesc(framebuffer->getRenderPassDesc());
1400 pipelineDesc.setDepthTestEnabled(blitDepth);
1401 pipelineDesc.setDepthWriteEnabled(blitDepth);
1402 pipelineDesc.setDepthFunc(VK_COMPARE_OP_ALWAYS);
1403
1404 if (blitStencil)
1405 {
1406 ASSERT(contextVk->getRenderer()->getFeatures().supportsShaderStencilExport.enabled);
1407
1408 const uint8_t completeMask = 0xFF;
1409 const uint8_t unusedReference = 0x00;
1410
1411 pipelineDesc.setStencilTestEnabled(true);
1412 pipelineDesc.setStencilFrontFuncs(unusedReference, VK_COMPARE_OP_ALWAYS, completeMask);
1413 pipelineDesc.setStencilBackFuncs(unusedReference, VK_COMPARE_OP_ALWAYS, completeMask);
1414 pipelineDesc.setStencilFrontOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1415 VK_STENCIL_OP_REPLACE);
1416 pipelineDesc.setStencilBackOps(VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_REPLACE,
1417 VK_STENCIL_OP_REPLACE);
1418 pipelineDesc.setStencilFrontWriteMask(completeMask);
1419 pipelineDesc.setStencilBackWriteMask(completeMask);
1420 }
1421
1422 VkViewport viewport;
1423 gl::Rectangle completeRenderArea = framebuffer->getCompleteRenderArea();
1424 gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, completeRenderArea.height, &viewport);
1425 pipelineDesc.setViewport(viewport);
1426
1427 pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
1428
1429 // Change source layout outside render pass
1430 ANGLE_TRY(contextVk->onImageRead(src->getAspectFlags(), vk::ImageLayout::FragmentShaderReadOnly,
1431 src));
1432
1433 vk::CommandBuffer *commandBuffer;
1434 ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, params.blitArea, &commandBuffer));
1435
1436 VkDescriptorImageInfo imageInfos[2] = {};
1437
1438 if (blitColor)
1439 {
1440 imageInfos[0].imageView = srcColorView->getHandle();
1441 imageInfos[0].imageLayout = src->getCurrentLayout();
1442 }
1443 if (blitDepth)
1444 {
1445 imageInfos[0].imageView = srcDepthView->getHandle();
1446 imageInfos[0].imageLayout = src->getCurrentLayout();
1447 }
1448 if (blitStencil)
1449 {
1450 imageInfos[1].imageView = srcStencilView->getHandle();
1451 imageInfos[1].imageLayout = src->getCurrentLayout();
1452 }
1453
1454 VkDescriptorImageInfo samplerInfo = {};
1455 samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
1456
1457 VkWriteDescriptorSet writeInfos[3] = {};
1458 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1459 writeInfos[0].dstSet = descriptorSet;
1460 writeInfos[0].dstBinding = kBlitResolveColorOrDepthBinding;
1461 writeInfos[0].descriptorCount = 1;
1462 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1463 writeInfos[0].pImageInfo = &imageInfos[0];
1464
1465 writeInfos[1] = writeInfos[0];
1466 writeInfos[1].dstBinding = kBlitResolveStencilBinding;
1467 writeInfos[1].pImageInfo = &imageInfos[1];
1468
1469 writeInfos[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1470 writeInfos[2].dstSet = descriptorSet;
1471 writeInfos[2].dstBinding = kBlitResolveSamplerBinding;
1472 writeInfos[2].descriptorCount = 1;
1473 writeInfos[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
1474 writeInfos[2].pImageInfo = &samplerInfo;
1475
1476 // If resolving color, there's one write info; index 0
1477 // If resolving depth, write info index 0 must be written
1478 // If resolving stencil, write info index 1 must also be written
1479 //
1480 // Note again that resolving color and depth/stencil are mutually exclusive here.
1481 uint32_t writeInfoOffset = blitDepth || blitColor ? 0 : 1;
1482 uint32_t writeInfoCount = blitColor + blitDepth + blitStencil;
1483
1484 vkUpdateDescriptorSets(contextVk->getDevice(), writeInfoCount, writeInfos + writeInfoOffset, 0,
1485 nullptr);
1486 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfos[2], 0, nullptr);
1487
1488 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
1489 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
1490 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
1491 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
1492 ANGLE_TRY(shaderLibrary.getBlitResolve_frag(contextVk, flags, &fragmentShader));
1493
1494 ANGLE_TRY(setupProgram(contextVk, Function::BlitResolve, fragmentShader, vertexShader,
1495 &mBlitResolvePrograms[flags], &pipelineDesc, descriptorSet,
1496 &shaderParams, sizeof(shaderParams), commandBuffer));
1497 commandBuffer->draw(6, 0);
1498 descriptorPoolBinding.reset();
1499
1500 return angle::Result::Continue;
1501 }
1502
stencilBlitResolveNoShaderExport(ContextVk * contextVk,FramebufferVk * framebuffer,vk::ImageHelper * src,const vk::ImageView * srcStencilView,const BlitResolveParameters & params)1503 angle::Result UtilsVk::stencilBlitResolveNoShaderExport(ContextVk *contextVk,
1504 FramebufferVk *framebuffer,
1505 vk::ImageHelper *src,
1506 const vk::ImageView *srcStencilView,
1507 const BlitResolveParameters ¶ms)
1508 {
1509 // When VK_EXT_shader_stencil_export is not available, stencil is blitted/resolved into a
1510 // temporary buffer which is then copied into the stencil aspect of the image.
1511
1512 ANGLE_TRY(ensureBlitResolveStencilNoExportResourcesInitialized(contextVk));
1513
1514 bool isResolve = src->getSamples() > 1;
1515
1516 VkDescriptorSet descriptorSet;
1517 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1518 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::BlitResolveStencilNoExport,
1519 &descriptorPoolBinding, &descriptorSet));
1520
1521 // Create a temporary buffer to blit/resolve stencil into.
1522 vk::RendererScoped<vk::BufferHelper> blitBuffer(contextVk->getRenderer());
1523
1524 uint32_t bufferRowLengthInUints = UnsignedCeilDivide(params.blitArea.width, sizeof(uint32_t));
1525 VkDeviceSize bufferSize = bufferRowLengthInUints * sizeof(uint32_t) * params.blitArea.height;
1526
1527 VkBufferCreateInfo blitBufferInfo = {};
1528 blitBufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
1529 blitBufferInfo.flags = 0;
1530 blitBufferInfo.size = bufferSize;
1531 blitBufferInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
1532 blitBufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
1533 blitBufferInfo.queueFamilyIndexCount = 0;
1534 blitBufferInfo.pQueueFamilyIndices = nullptr;
1535
1536 ANGLE_TRY(
1537 blitBuffer.get().init(contextVk, blitBufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));
1538 blitBuffer.get().retain(&contextVk->getResourceUseList());
1539
1540 BlitResolveStencilNoExportShaderParams shaderParams;
1541 if (isResolve)
1542 {
1543 CalculateResolveOffset(params, shaderParams.offset.resolve);
1544 }
1545 else
1546 {
1547 CalculateBlitOffset(params, shaderParams.offset.blit);
1548 }
1549 shaderParams.stretch[0] = params.stretch[0];
1550 shaderParams.stretch[1] = params.stretch[1];
1551 shaderParams.invSrcExtent[0] = 1.0f / params.srcExtents[0];
1552 shaderParams.invSrcExtent[1] = 1.0f / params.srcExtents[1];
1553 shaderParams.srcLayer = params.srcLayer;
1554 shaderParams.srcWidth = params.srcExtents[0];
1555 shaderParams.destPitch = bufferRowLengthInUints;
1556 shaderParams.blitArea[0] = params.blitArea.x;
1557 shaderParams.blitArea[1] = params.blitArea.y;
1558 shaderParams.blitArea[2] = params.blitArea.width;
1559 shaderParams.blitArea[3] = params.blitArea.height;
1560 shaderParams.flipX = params.flipX;
1561 shaderParams.flipY = params.flipY;
1562
1563 // Linear sampling is only valid with color blitting.
1564 ASSERT(!params.linear);
1565
1566 uint32_t flags = src->getLayerCount() > 1 ? BlitResolveStencilNoExport_comp::kSrcIsArray : 0;
1567 flags |= isResolve ? BlitResolve_frag::kIsResolve : 0;
1568
1569 RenderTargetVk *depthStencilRenderTarget = framebuffer->getDepthStencilRenderTarget();
1570 ASSERT(depthStencilRenderTarget != nullptr);
1571 vk::ImageHelper *depthStencilImage = &depthStencilRenderTarget->getImage();
1572
1573 vk::CommandBuffer *commandBuffer;
1574 // Change source layout prior to computation.
1575 ANGLE_TRY(
1576 contextVk->onImageRead(src->getAspectFlags(), vk::ImageLayout::ComputeShaderReadOnly, src));
1577 ANGLE_TRY(contextVk->onImageWrite(depthStencilImage->getAspectFlags(),
1578 vk::ImageLayout::TransferDst, depthStencilImage));
1579 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1580
1581 // Blit/resolve stencil into the buffer.
1582 VkDescriptorImageInfo imageInfo = {};
1583 imageInfo.imageView = srcStencilView->getHandle();
1584 imageInfo.imageLayout = src->getCurrentLayout();
1585
1586 VkDescriptorBufferInfo bufferInfo = {};
1587 bufferInfo.buffer = blitBuffer.get().getBuffer().getHandle();
1588 bufferInfo.offset = 0;
1589 bufferInfo.range = VK_WHOLE_SIZE;
1590
1591 VkDescriptorImageInfo samplerInfo = {};
1592 samplerInfo.sampler = params.linear ? mLinearSampler.getHandle() : mPointSampler.getHandle();
1593
1594 VkWriteDescriptorSet writeInfos[3] = {};
1595 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1596 writeInfos[0].dstSet = descriptorSet;
1597 writeInfos[0].dstBinding = kBlitResolveStencilNoExportDestBinding;
1598 writeInfos[0].descriptorCount = 1;
1599 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
1600 writeInfos[0].pBufferInfo = &bufferInfo;
1601
1602 writeInfos[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1603 writeInfos[1].dstSet = descriptorSet;
1604 writeInfos[1].dstBinding = kBlitResolveStencilNoExportSrcBinding;
1605 writeInfos[1].descriptorCount = 1;
1606 writeInfos[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1607 writeInfos[1].pImageInfo = &imageInfo;
1608
1609 writeInfos[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1610 writeInfos[2].dstSet = descriptorSet;
1611 writeInfos[2].dstBinding = kBlitResolveStencilNoExportSamplerBinding;
1612 writeInfos[2].descriptorCount = 1;
1613 writeInfos[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
1614 writeInfos[2].pImageInfo = &samplerInfo;
1615
1616 vkUpdateDescriptorSets(contextVk->getDevice(), 3, writeInfos, 0, nullptr);
1617
1618 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1619 ANGLE_TRY(contextVk->getShaderLibrary().getBlitResolveStencilNoExport_comp(contextVk, flags,
1620 &shader));
1621
1622 ANGLE_TRY(setupProgram(contextVk, Function::BlitResolveStencilNoExport, shader, nullptr,
1623 &mBlitResolveStencilNoExportPrograms[flags], nullptr, descriptorSet,
1624 &shaderParams, sizeof(shaderParams), commandBuffer));
1625 commandBuffer->dispatch(UnsignedCeilDivide(bufferRowLengthInUints, 8),
1626 UnsignedCeilDivide(params.blitArea.height, 8), 1);
1627 descriptorPoolBinding.reset();
1628
1629 // Add a barrier prior to copy.
1630 VkMemoryBarrier memoryBarrier = {};
1631 memoryBarrier.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER;
1632 memoryBarrier.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT;
1633 memoryBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1634
1635 // Use the all pipe stage to keep the state management simple.
1636 commandBuffer->pipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
1637 VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 1, &memoryBarrier, 0, nullptr,
1638 0, nullptr);
1639
1640 // Copy the resulting buffer into dest.
1641 VkBufferImageCopy region = {};
1642 region.bufferOffset = 0;
1643 region.bufferRowLength = bufferRowLengthInUints * sizeof(uint32_t);
1644 region.bufferImageHeight = params.blitArea.height;
1645 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
1646 region.imageSubresource.mipLevel = depthStencilRenderTarget->getLevelIndex();
1647 region.imageSubresource.baseArrayLayer = depthStencilRenderTarget->getLayerIndex();
1648 region.imageSubresource.layerCount = 1;
1649 region.imageOffset.x = params.blitArea.x;
1650 region.imageOffset.y = params.blitArea.y;
1651 region.imageOffset.z = 0;
1652 region.imageExtent.width = params.blitArea.width;
1653 region.imageExtent.height = params.blitArea.height;
1654 region.imageExtent.depth = 1;
1655
1656 commandBuffer->copyBufferToImage(blitBuffer.get().getBuffer().getHandle(),
1657 depthStencilImage->getImage(),
1658 depthStencilImage->getCurrentLayout(), 1, ®ion);
1659
1660 return angle::Result::Continue;
1661 }
1662
copyImage(ContextVk * contextVk,vk::ImageHelper * dest,const vk::ImageView * destView,vk::ImageHelper * src,const vk::ImageView * srcView,const CopyImageParameters & params)1663 angle::Result UtilsVk::copyImage(ContextVk *contextVk,
1664 vk::ImageHelper *dest,
1665 const vk::ImageView *destView,
1666 vk::ImageHelper *src,
1667 const vk::ImageView *srcView,
1668 const CopyImageParameters ¶ms)
1669 {
1670 ANGLE_TRY(ensureImageCopyResourcesInitialized(contextVk));
1671
1672 const vk::Format &srcFormat = src->getFormat();
1673 const vk::Format &dstFormat = dest->getFormat();
1674 const angle::Format &dstIntendedFormat = dstFormat.intendedFormat();
1675
1676 ImageCopyShaderParams shaderParams;
1677 shaderParams.flipY = params.srcFlipY || params.destFlipY;
1678 shaderParams.premultiplyAlpha = params.srcPremultiplyAlpha;
1679 shaderParams.unmultiplyAlpha = params.srcUnmultiplyAlpha;
1680 shaderParams.destHasLuminance = dstIntendedFormat.luminanceBits > 0;
1681 shaderParams.destIsAlpha = dstIntendedFormat.isLUMA() && dstIntendedFormat.alphaBits > 0;
1682 shaderParams.destDefaultChannelsMask = GetFormatDefaultChannelMask(dstFormat);
1683 shaderParams.srcMip = params.srcMip;
1684 shaderParams.srcLayer = params.srcLayer;
1685 shaderParams.srcOffset[0] = params.srcOffset[0];
1686 shaderParams.srcOffset[1] = params.srcOffset[1];
1687 shaderParams.destOffset[0] = params.destOffset[0];
1688 shaderParams.destOffset[1] = params.destOffset[1];
1689
1690 ASSERT(!(params.srcFlipY && params.destFlipY));
1691 if (params.srcFlipY)
1692 {
1693 // If viewport is flipped, the shader expects srcOffset[1] to have the
1694 // last row's index instead of the first's.
1695 shaderParams.srcOffset[1] = params.srcHeight - params.srcOffset[1] - 1;
1696 }
1697 else if (params.destFlipY)
1698 {
1699 // If image is flipped during copy, the shader uses the same code path as above,
1700 // with srcOffset being set to the last row's index instead of the first's.
1701 shaderParams.srcOffset[1] = params.srcOffset[1] + params.srcExtents[1] - 1;
1702 }
1703
1704 uint32_t flags = GetImageCopyFlags(srcFormat, dstFormat);
1705 flags |= src->getLayerCount() > 1 ? ImageCopy_frag::kSrcIsArray : 0;
1706
1707 VkDescriptorSet descriptorSet;
1708 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1709 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::ImageCopy, &descriptorPoolBinding,
1710 &descriptorSet));
1711
1712 vk::RenderPassDesc renderPassDesc;
1713 renderPassDesc.setSamples(dest->getSamples());
1714 renderPassDesc.packColorAttachment(0, dstFormat.intendedFormatID);
1715
1716 // Multisampled copy is not yet supported.
1717 ASSERT(src->getSamples() == 1 && dest->getSamples() == 1);
1718
1719 vk::GraphicsPipelineDesc pipelineDesc;
1720 pipelineDesc.initDefaults();
1721 pipelineDesc.setCullMode(VK_CULL_MODE_NONE);
1722 pipelineDesc.setRenderPassDesc(renderPassDesc);
1723
1724 gl::Rectangle renderArea;
1725 renderArea.x = params.destOffset[0];
1726 renderArea.y = params.destOffset[1];
1727 renderArea.width = params.srcExtents[0];
1728 renderArea.height = params.srcExtents[1];
1729
1730 VkViewport viewport;
1731 gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, dest->getExtents().height, &viewport);
1732 pipelineDesc.setViewport(viewport);
1733
1734 VkRect2D scissor = gl_vk::GetRect(renderArea);
1735 pipelineDesc.setScissor(scissor);
1736
1737 // Change source layout outside render pass
1738 ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
1739 vk::ImageLayout::FragmentShaderReadOnly, src));
1740 ANGLE_TRY(
1741 contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment, dest));
1742
1743 vk::CommandBuffer *commandBuffer;
1744 ANGLE_TRY(
1745 startRenderPass(contextVk, dest, destView, renderPassDesc, renderArea, &commandBuffer));
1746
1747 VkDescriptorImageInfo imageInfo = {};
1748 imageInfo.imageView = srcView->getHandle();
1749 imageInfo.imageLayout = src->getCurrentLayout();
1750
1751 VkWriteDescriptorSet writeInfo = {};
1752 writeInfo.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1753 writeInfo.dstSet = descriptorSet;
1754 writeInfo.dstBinding = kImageCopySourceBinding;
1755 writeInfo.descriptorCount = 1;
1756 writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1757 writeInfo.pImageInfo = &imageInfo;
1758
1759 vkUpdateDescriptorSets(contextVk->getDevice(), 1, &writeInfo, 0, nullptr);
1760
1761 vk::ShaderLibrary &shaderLibrary = contextVk->getShaderLibrary();
1762 vk::RefCounted<vk::ShaderAndSerial> *vertexShader = nullptr;
1763 vk::RefCounted<vk::ShaderAndSerial> *fragmentShader = nullptr;
1764 ANGLE_TRY(shaderLibrary.getFullScreenQuad_vert(contextVk, 0, &vertexShader));
1765 ANGLE_TRY(shaderLibrary.getImageCopy_frag(contextVk, flags, &fragmentShader));
1766
1767 ANGLE_TRY(setupProgram(contextVk, Function::ImageCopy, fragmentShader, vertexShader,
1768 &mImageCopyPrograms[flags], &pipelineDesc, descriptorSet, &shaderParams,
1769 sizeof(shaderParams), commandBuffer));
1770 commandBuffer->draw(6, 0);
1771 descriptorPoolBinding.reset();
1772
1773 return angle::Result::Continue;
1774 }
1775
cullOverlayWidgets(ContextVk * contextVk,vk::BufferHelper * enabledWidgetsBuffer,vk::ImageHelper * dest,const vk::ImageView * destView,const OverlayCullParameters & params)1776 angle::Result UtilsVk::cullOverlayWidgets(ContextVk *contextVk,
1777 vk::BufferHelper *enabledWidgetsBuffer,
1778 vk::ImageHelper *dest,
1779 const vk::ImageView *destView,
1780 const OverlayCullParameters ¶ms)
1781 {
1782 ANGLE_TRY(ensureOverlayCullResourcesInitialized(contextVk));
1783
1784 ASSERT(params.subgroupSize[0] == 8 &&
1785 (params.subgroupSize[1] == 8 || params.subgroupSize[1] == 4));
1786 uint32_t flags =
1787 params.subgroupSize[1] == 8 ? OverlayCull_comp::kIs8x8 : OverlayCull_comp::kIs8x4;
1788 if (params.supportsSubgroupBallot)
1789 {
1790 flags |= OverlayCull_comp::kSupportsBallot;
1791 }
1792 else if (params.supportsSubgroupBallot)
1793 {
1794 flags |= OverlayCull_comp::kSupportsArithmetic;
1795 }
1796 else
1797 {
1798 flags |= OverlayCull_comp::kSupportsNone;
1799 }
1800
1801 VkDescriptorSet descriptorSet;
1802 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1803 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::OverlayCull, &descriptorPoolBinding,
1804 &descriptorSet));
1805
1806 vk::CommandBuffer *commandBuffer;
1807 ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, enabledWidgetsBuffer));
1808 ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
1809 vk::ImageLayout::ComputeShaderWrite, dest));
1810 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1811
1812 VkDescriptorImageInfo imageInfo = {};
1813 imageInfo.imageView = destView->getHandle();
1814 imageInfo.imageLayout = dest->getCurrentLayout();
1815
1816 VkDescriptorBufferInfo bufferInfo = {};
1817 bufferInfo.buffer = enabledWidgetsBuffer->getBuffer().getHandle();
1818 bufferInfo.offset = 0;
1819 bufferInfo.range = VK_WHOLE_SIZE;
1820
1821 VkWriteDescriptorSet writeInfos[2] = {};
1822 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1823 writeInfos[0].dstSet = descriptorSet;
1824 writeInfos[0].dstBinding = kOverlayCullCulledWidgetsBinding;
1825 writeInfos[0].descriptorCount = 1;
1826 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1827 writeInfos[0].pImageInfo = &imageInfo;
1828
1829 writeInfos[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1830 writeInfos[1].dstSet = descriptorSet;
1831 writeInfos[1].dstBinding = kOverlayCullWidgetCoordsBinding;
1832 writeInfos[1].descriptorCount = 1;
1833 writeInfos[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1834 writeInfos[1].pBufferInfo = &bufferInfo;
1835
1836 vkUpdateDescriptorSets(contextVk->getDevice(), 2, writeInfos, 0, nullptr);
1837
1838 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1839 ANGLE_TRY(contextVk->getShaderLibrary().getOverlayCull_comp(contextVk, flags, &shader));
1840
1841 ANGLE_TRY(setupProgram(contextVk, Function::OverlayCull, shader, nullptr,
1842 &mOverlayCullPrograms[flags], nullptr, descriptorSet, nullptr, 0,
1843 commandBuffer));
1844 commandBuffer->dispatch(dest->getExtents().width, dest->getExtents().height, 1);
1845 descriptorPoolBinding.reset();
1846
1847 return angle::Result::Continue;
1848 }
1849
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)1850 angle::Result UtilsVk::drawOverlay(ContextVk *contextVk,
1851 vk::BufferHelper *textWidgetsBuffer,
1852 vk::BufferHelper *graphWidgetsBuffer,
1853 vk::ImageHelper *font,
1854 const vk::ImageView *fontView,
1855 vk::ImageHelper *culledWidgets,
1856 const vk::ImageView *culledWidgetsView,
1857 vk::ImageHelper *dest,
1858 const vk::ImageView *destView,
1859 const OverlayDrawParameters ¶ms)
1860 {
1861 ANGLE_TRY(ensureOverlayDrawResourcesInitialized(contextVk));
1862
1863 OverlayDrawShaderParams shaderParams;
1864 shaderParams.outputSize[0] = dest->getExtents().width;
1865 shaderParams.outputSize[1] = dest->getExtents().height;
1866
1867 ASSERT(params.subgroupSize[0] == 8 &&
1868 (params.subgroupSize[1] == 8 || params.subgroupSize[1] == 4));
1869 uint32_t flags =
1870 params.subgroupSize[1] == 8 ? OverlayDraw_comp::kIs8x8 : OverlayDraw_comp::kIs8x4;
1871
1872 VkDescriptorSet descriptorSet;
1873 vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
1874 ANGLE_TRY(allocateDescriptorSet(contextVk, Function::OverlayDraw, &descriptorPoolBinding,
1875 &descriptorSet));
1876
1877 vk::CommandBuffer *commandBuffer;
1878 ANGLE_TRY(contextVk->onImageWrite(VK_IMAGE_ASPECT_COLOR_BIT,
1879 vk::ImageLayout::ComputeShaderWrite, dest));
1880 ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
1881 vk::ImageLayout::ComputeShaderReadOnly, culledWidgets));
1882 ANGLE_TRY(contextVk->onImageRead(VK_IMAGE_ASPECT_COLOR_BIT,
1883 vk::ImageLayout::ComputeShaderReadOnly, font));
1884 ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, textWidgetsBuffer));
1885 ANGLE_TRY(contextVk->onBufferRead(VK_ACCESS_SHADER_READ_BIT, graphWidgetsBuffer));
1886
1887 ANGLE_TRY(contextVk->endRenderPassAndGetCommandBuffer(&commandBuffer));
1888
1889 VkDescriptorImageInfo imageInfos[3] = {};
1890 imageInfos[0].imageView = destView->getHandle();
1891 imageInfos[0].imageLayout = dest->getCurrentLayout();
1892
1893 imageInfos[1].imageView = culledWidgetsView->getHandle();
1894 imageInfos[1].imageLayout = culledWidgets->getCurrentLayout();
1895
1896 imageInfos[2].imageView = fontView->getHandle();
1897 imageInfos[2].imageLayout = font->getCurrentLayout();
1898
1899 VkDescriptorBufferInfo bufferInfos[2] = {};
1900 bufferInfos[0].buffer = textWidgetsBuffer->getBuffer().getHandle();
1901 bufferInfos[0].offset = 0;
1902 bufferInfos[0].range = VK_WHOLE_SIZE;
1903
1904 bufferInfos[1].buffer = graphWidgetsBuffer->getBuffer().getHandle();
1905 bufferInfos[1].offset = 0;
1906 bufferInfos[1].range = VK_WHOLE_SIZE;
1907
1908 VkWriteDescriptorSet writeInfos[5] = {};
1909 writeInfos[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1910 writeInfos[0].dstSet = descriptorSet;
1911 writeInfos[0].dstBinding = kOverlayDrawOutputBinding;
1912 writeInfos[0].descriptorCount = 1;
1913 writeInfos[0].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
1914 writeInfos[0].pImageInfo = &imageInfos[0];
1915
1916 writeInfos[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1917 writeInfos[1].dstSet = descriptorSet;
1918 writeInfos[1].dstBinding = kOverlayDrawCulledWidgetsBinding;
1919 writeInfos[1].descriptorCount = 1;
1920 writeInfos[1].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1921 writeInfos[1].pImageInfo = &imageInfos[1];
1922
1923 writeInfos[2].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1924 writeInfos[2].dstSet = descriptorSet;
1925 writeInfos[2].dstBinding = kOverlayDrawFontBinding;
1926 writeInfos[2].descriptorCount = 1;
1927 writeInfos[2].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
1928 writeInfos[2].pImageInfo = &imageInfos[2];
1929
1930 writeInfos[3].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
1931 writeInfos[3].dstSet = descriptorSet;
1932 writeInfos[3].dstBinding = kOverlayDrawTextWidgetsBinding;
1933 writeInfos[3].descriptorCount = 1;
1934 writeInfos[3].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
1935 writeInfos[3].pBufferInfo = &bufferInfos[0];
1936
1937 writeInfos[4] = writeInfos[3];
1938 writeInfos[4].dstBinding = kOverlayDrawGraphWidgetsBinding;
1939 writeInfos[4].pBufferInfo = &bufferInfos[1];
1940
1941 vkUpdateDescriptorSets(contextVk->getDevice(), 5, writeInfos, 0, nullptr);
1942
1943 vk::RefCounted<vk::ShaderAndSerial> *shader = nullptr;
1944 ANGLE_TRY(contextVk->getShaderLibrary().getOverlayDraw_comp(contextVk, flags, &shader));
1945
1946 ANGLE_TRY(setupProgram(contextVk, Function::OverlayDraw, shader, nullptr,
1947 &mOverlayDrawPrograms[flags], nullptr, descriptorSet, &shaderParams,
1948 sizeof(shaderParams), commandBuffer));
1949
1950 // Every pixel of culledWidgets corresponds to one workgroup, so we can use that as dispatch
1951 // size.
1952 commandBuffer->dispatch(culledWidgets->getExtents().width, culledWidgets->getExtents().height,
1953 1);
1954 descriptorPoolBinding.reset();
1955
1956 return angle::Result::Continue;
1957 }
1958
allocateDescriptorSet(ContextVk * contextVk,Function function,vk::RefCountedDescriptorPoolBinding * bindingOut,VkDescriptorSet * descriptorSetOut)1959 angle::Result UtilsVk::allocateDescriptorSet(ContextVk *contextVk,
1960 Function function,
1961 vk::RefCountedDescriptorPoolBinding *bindingOut,
1962 VkDescriptorSet *descriptorSetOut)
1963 {
1964 ANGLE_TRY(mDescriptorPools[function].allocateSets(
1965 contextVk, mDescriptorSetLayouts[function][kSetIndex].get().ptr(), 1, bindingOut,
1966 descriptorSetOut));
1967 bindingOut->get().updateSerial(contextVk->getCurrentQueueSerial());
1968 return angle::Result::Continue;
1969 }
1970
ClearFramebufferParameters()1971 UtilsVk::ClearFramebufferParameters::ClearFramebufferParameters()
1972 : clearColor(false),
1973 clearStencil(false),
1974 stencilMask(0),
1975 colorMaskFlags(0),
1976 colorAttachmentIndexGL(0),
1977 colorFormat(nullptr),
1978 colorClearValue{},
1979 stencilClearValue(0)
1980 {}
1981
1982 } // namespace rx
1983