Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
GrVkRenderPass.cpp
Go to the documentation of this file.
1/*
2* Copyright 2015 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
9
10#include "src/gpu/KeyBuilder.h"
17
18using namespace skia_private;
19
21
23 const AttachmentDesc& desc,
24 VkImageLayout startLayout,
25 VkImageLayout endLayout) {
26 attachment->flags = 0;
27 attachment->format = desc.fFormat;
28 SkAssertResult(skgpu::SampleCountToVkSampleCount(desc.fSamples, &attachment->samples));
29 switch (startLayout) {
33 attachment->loadOp = desc.fLoadStoreOps.fLoadOp;
34 attachment->storeOp = desc.fLoadStoreOps.fStoreOp;
37 break;
41 attachment->stencilLoadOp = desc.fLoadStoreOps.fLoadOp;
42 attachment->stencilStoreOp = desc.fLoadStoreOps.fStoreOp;
43 break;
44 default:
45 SK_ABORT("Unexpected attachment layout");
46 }
47
48 attachment->initialLayout = startLayout;
49 attachment->finalLayout = endLayout == VK_IMAGE_LAYOUT_UNDEFINED ? startLayout : endLayout;
50}
51
53 AttachmentsDescriptor* attachmentsDescriptor,
54 AttachmentFlags attachmentFlags,
55 SelfDependencyFlags selfDepFlags,
56 LoadFromResolve loadFromResolve) {
57 static const GrVkRenderPass::LoadStoreOps kBasicLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD,
59 switch (loadFromResolve) {
61 return Create(gpu, attachmentFlags, attachmentsDescriptor, kBasicLoadStoreOps,
62 kBasicLoadStoreOps, kBasicLoadStoreOps, selfDepFlags, loadFromResolve);
64 static const GrVkRenderPass::LoadStoreOps kDiscardLoadStoreOps(
66 return Create(gpu, attachmentFlags, attachmentsDescriptor, kDiscardLoadStoreOps,
67 kBasicLoadStoreOps, kBasicLoadStoreOps, selfDepFlags, loadFromResolve);
68 }
69 }
71}
72
74 const GrVkRenderPass& compatibleRenderPass,
75 const LoadStoreOps& colorOp,
76 const LoadStoreOps& resolveOp,
77 const LoadStoreOps& stencilOp) {
78 AttachmentFlags attachmentFlags = compatibleRenderPass.fAttachmentFlags;
79 AttachmentsDescriptor attachmentsDescriptor = compatibleRenderPass.fAttachmentsDescriptor;
80 SelfDependencyFlags selfDepFlags = compatibleRenderPass.fSelfDepFlags;
81 LoadFromResolve loadFromResolve = compatibleRenderPass.fLoadFromResolve;
82 return Create(gpu, attachmentFlags, &attachmentsDescriptor, colorOp, resolveOp, stencilOp,
83 selfDepFlags, loadFromResolve);
84}
85
87 AttachmentFlags attachmentFlags,
88 AttachmentsDescriptor* attachmentsDescriptor,
89 const LoadStoreOps& colorOp,
90 const LoadStoreOps& resolveOp,
91 const LoadStoreOps& stencilOp,
92 SelfDependencyFlags selfDepFlags,
93 LoadFromResolve loadFromResolve) {
97 gpu->caps()->textureBarrierSupport());
98
99 // If we have a resolve attachment, we will always do a resolve into it. Thus it doesn't make
100 // sense not to store the resolve attachment at the end of the render pass.
101 //
102 // Currently today (when not using discardable msaa images) we load and store the the msaa image
103 // and then use the copy resolve command to handle the resolving. If instead we moved to doing
104 // the resolving at the end of the last render pass, we would probably want a separate flag
105 // for having a resolve attachment versus actually doing the resolving. This would allow us to
106 // use the same VkPiplines for render passes where we resolve and those we don't since each will
107 // always have the resolve attachment. The actual resolving or not does not affect render pass
108 // compatibility if there is only one sub pass, just the presence of the attachment or not.
109 SkASSERT(!SkToBool(attachmentFlags & kResolve_AttachmentFlag) ||
110 resolveOp.fStoreOp == VK_ATTACHMENT_STORE_OP_STORE);
111
113 (SkToBool(attachmentFlags & kColor_AttachmentFlag) &&
114 SkToBool(attachmentFlags & kResolve_AttachmentFlag)));
115
116#ifdef SK_DEBUG
118 // If we are loading the resolve image into the msaa color attachment then we should not be
119 // loading or storing the msaa attachment. Additionally we need to make sure we are loading
120 // the resolve so it can be copied into the msaa color attachment.
121 SkASSERT(colorOp.fLoadOp == VK_ATTACHMENT_LOAD_OP_DONT_CARE);
122 SkASSERT(colorOp.fStoreOp == VK_ATTACHMENT_STORE_OP_DONT_CARE);
123 SkASSERT(resolveOp.fLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD);
124 }
125#endif
126
127 uint32_t numAttachments = attachmentsDescriptor->fAttachmentCount;
128 // Attachment descriptions to be set on the render pass
129 TArray<VkAttachmentDescription> attachments(numAttachments);
130 attachments.reset(numAttachments);
131 memset(attachments.begin(), 0, numAttachments * sizeof(VkAttachmentDescription));
132
133 // Refs to attachments on the render pass (as described by the VkAttachmentDescription above),
134 // that are used by the subpass.
135 VkAttachmentReference colorRef;
136 VkAttachmentReference resolveRef;
137 VkAttachmentReference resolveLoadInputRef;
138 VkAttachmentReference stencilRef;
139 uint32_t currentAttachment = 0;
140
141 // Go through each of the attachment types (color, stencil) and set the necessary
142 // on the various Vk structs.
143 VkSubpassDescription subpassDescs[2];
144 memset(subpassDescs, 0, 2*sizeof(VkSubpassDescription));
145 const int mainSubpass = loadFromResolve == LoadFromResolve::kLoad ? 1 : 0;
146 VkSubpassDescription& subpassDescMain = subpassDescs[mainSubpass];
147 subpassDescMain.flags = 0;
149 subpassDescMain.inputAttachmentCount = 0;
150 subpassDescMain.pInputAttachments = nullptr;
151 subpassDescMain.pResolveAttachments = nullptr;
152
153 uint32_t clearValueCount = 0;
154
156 int currentDependency = 0;
157
158 if (attachmentFlags & kColor_AttachmentFlag) {
159 // set up color attachment
160 bool needsGeneralLayout = SkToBool(selfDepFlags & SelfDependencyFlags::kForInputAttachment);
161 VkImageLayout layout = needsGeneralLayout ? VK_IMAGE_LAYOUT_GENERAL
163
164 attachmentsDescriptor->fColor.fLoadStoreOps = colorOp;
165
166 setup_vk_attachment_description(&attachments[currentAttachment],
167 attachmentsDescriptor->fColor,
168 layout, layout);
169 // setup subpass use of attachment
170 colorRef.attachment = currentAttachment++;
171 colorRef.layout = layout;
172 subpassDescMain.colorAttachmentCount = 1;
173
174 if (selfDepFlags != SelfDependencyFlags::kNone) {
175 VkSubpassDependency& dependency = dependencies[currentDependency++];
176 dependency.srcSubpass = mainSubpass;
177 dependency.dstSubpass = mainSubpass;
178 dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
181 dependency.dstStageMask = 0;
182 dependency.dstAccessMask = 0;
183
185 // If we have coherent support we shouldn't be needing a self dependency
189 }
190 if (selfDepFlags & SelfDependencyFlags::kForInputAttachment) {
192
193 subpassDescMain.inputAttachmentCount = 1;
194 subpassDescMain.pInputAttachments = &colorRef;
195
198 }
199 }
200
201 if (VK_ATTACHMENT_LOAD_OP_CLEAR == colorOp.fLoadOp) {
202 clearValueCount = colorRef.attachment + 1;
203 }
204 } else {
205 // I don't think there should ever be a time where we don't have a color attachment
206 SkASSERT(false);
207 SkASSERT(selfDepFlags == SelfDependencyFlags::kNone);
210 subpassDescMain.colorAttachmentCount = 0;
211 }
212
213 subpassDescMain.pColorAttachments = &colorRef;
214
215 if (attachmentFlags & kResolve_AttachmentFlag) {
216 attachmentsDescriptor->fResolve.fLoadStoreOps = resolveOp;
217
221
222 setup_vk_attachment_description(&attachments[currentAttachment],
223 attachmentsDescriptor->fResolve,
224 layout,
226
227 // setup main subpass use of attachment
228 resolveRef.attachment = currentAttachment++;
230
231 subpassDescMain.pResolveAttachments = &resolveRef;
232
233 // Setup the load subpass and set subpass dependendcies
235 resolveLoadInputRef.attachment = resolveRef.attachment;
237
238 // The load subpass will always be the first
239 VkSubpassDescription& subpassDescLoad = subpassDescs[0];
240 subpassDescLoad.flags = 0;
242 subpassDescLoad.inputAttachmentCount = 1;
243 subpassDescLoad.pInputAttachments = &resolveLoadInputRef;
244 subpassDescLoad.colorAttachmentCount = 1;
245 subpassDescLoad.pColorAttachments = &colorRef;
246 subpassDescLoad.pResolveAttachments = nullptr;
247 subpassDescLoad.pDepthStencilAttachment = nullptr;
248 subpassDescLoad.preserveAttachmentCount = 0;
249 subpassDescLoad.pPreserveAttachments = nullptr;
250
251 VkSubpassDependency& dependency = dependencies[currentDependency++];
252 dependency.srcSubpass = 0;
253 dependency.dstSubpass = mainSubpass;
254 dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
258 dependency.dstAccessMask =
260 }
261 }
262
263
264 if (attachmentFlags & kStencil_AttachmentFlag) {
265 // set up stencil attachment
266 attachmentsDescriptor->fStencil.fLoadStoreOps = stencilOp;
267 setup_vk_attachment_description(&attachments[currentAttachment],
268 attachmentsDescriptor->fStencil,
271 // setup subpass use of attachment
272 stencilRef.attachment = currentAttachment++;
274 if (VK_ATTACHMENT_LOAD_OP_CLEAR == stencilOp.fLoadOp) {
275 clearValueCount = std::max(clearValueCount, stencilRef.attachment + 1);
276 }
277 } else {
278 stencilRef.attachment = VK_ATTACHMENT_UNUSED;
280 }
281 subpassDescMain.pDepthStencilAttachment = &stencilRef;
282
283 subpassDescMain.preserveAttachmentCount = 0;
284 subpassDescMain.pPreserveAttachments = nullptr;
285
286 SkASSERT(numAttachments == currentAttachment);
287
288 uint32_t subpassCount = loadFromResolve == LoadFromResolve::kLoad ? 2 : 1;
289
290 // Create the VkRenderPass compatible with the attachment descriptions above
291 VkRenderPassCreateInfo createInfo;
292 memset(&createInfo, 0, sizeof(VkRenderPassCreateInfo));
294 createInfo.pNext = nullptr;
295 createInfo.flags = 0;
296 createInfo.attachmentCount = numAttachments;
297 createInfo.pAttachments = attachments.begin();
298 createInfo.subpassCount = subpassCount;
299 createInfo.pSubpasses = subpassDescs;
300 createInfo.dependencyCount = currentDependency;
301 createInfo.pDependencies = dependencies;
302
304 VkRenderPass renderPass;
305 GR_VK_CALL_RESULT(gpu, result, CreateRenderPass(gpu->device(),
306 &createInfo,
307 nullptr,
308 &renderPass));
309 if (result != VK_SUCCESS) {
310 return nullptr;
311 }
312
314 // Get granularity for this render pass
315 GR_VK_CALL(gpu->vkInterface(), GetRenderAreaGranularity(gpu->device(),
316 renderPass,
317 &granularity));
318
319 return new GrVkRenderPass(gpu, renderPass, attachmentFlags, *attachmentsDescriptor,
321}
322
323GrVkRenderPass::GrVkRenderPass(const GrVkGpu* gpu, VkRenderPass renderPass, AttachmentFlags flags,
324 const AttachmentsDescriptor& descriptor,
325 SelfDependencyFlags selfDepFlags,
326 LoadFromResolve loadFromResolve,
327 const VkExtent2D& granularity, uint32_t clearValueCount)
328 : INHERITED(gpu)
329 , fRenderPass(renderPass)
330 , fAttachmentFlags(flags)
331 , fAttachmentsDescriptor(descriptor)
332 , fSelfDepFlags(selfDepFlags)
333 , fLoadFromResolve(loadFromResolve)
334 , fGranularity(granularity)
335 , fClearValueCount(clearValueCount) {
336}
337
339 if (!(fAttachmentFlags & kExternal_AttachmentFlag)) {
340 GR_VK_CALL(fGpu->vkInterface(), DestroyRenderPass(fGpu->device(), fRenderPass, nullptr));
341 }
342}
343
344bool GrVkRenderPass::colorAttachmentIndex(uint32_t* index) const {
345 *index = fColorAttachmentIndex;
346 if ((fAttachmentFlags & kColor_AttachmentFlag) ||
347 (fAttachmentFlags & kExternal_AttachmentFlag)) {
348 return true;
349 }
350 return false;
351}
352
353// Works under the assumption that stencil attachment will always be after the color and resolve
354// attachments.
355bool GrVkRenderPass::stencilAttachmentIndex(uint32_t* index) const {
356 *index = 0;
357 if (fAttachmentFlags & kColor_AttachmentFlag) {
358 ++(*index);
359 }
360 if (fAttachmentFlags & kStencil_AttachmentFlag) {
361 return true;
362 }
363 return false;
364}
365
367 const AttachmentFlags& flags,
368 SelfDependencyFlags selfDepFlags,
369 LoadFromResolve loadFromResolve) const {
370 SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
371 if (flags != fAttachmentFlags) {
372 return false;
373 }
374
375 if (fAttachmentFlags & kColor_AttachmentFlag) {
376 if (!fAttachmentsDescriptor.fColor.isCompatible(desc.fColor)) {
377 return false;
378 }
379 }
380 if (fAttachmentFlags & kResolve_AttachmentFlag) {
381 if (!fAttachmentsDescriptor.fResolve.isCompatible(desc.fResolve)) {
382 return false;
383 }
384 }
385 if (fAttachmentFlags & kStencil_AttachmentFlag) {
386 if (!fAttachmentsDescriptor.fStencil.isCompatible(desc.fStencil)) {
387 return false;
388 }
389 }
390
391 if (fSelfDepFlags != selfDepFlags) {
392 return false;
393 }
394
395 if (fLoadFromResolve != loadFromResolve) {
396 return false;
397 }
398
399 return true;
400}
401
403 SelfDependencyFlags selfDepFlags,
404 LoadFromResolve loadFromResolve) const {
405 SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
406
409 if (!target->getAttachmentsDescriptor(&desc, &flags, this->hasResolveAttachment(),
410 this->hasStencilAttachment())) {
411 return false;
412 }
413
414 return this->isCompatible(desc, flags, selfDepFlags, loadFromResolve);
415}
416
417bool GrVkRenderPass::isCompatible(const GrVkRenderPass& renderPass) const {
418 SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
419 return this->isCompatible(renderPass.fAttachmentsDescriptor, renderPass.fAttachmentFlags,
420 renderPass.fSelfDepFlags, renderPass.fLoadFromResolve);
421}
422
423bool GrVkRenderPass::isCompatibleExternalRP(VkRenderPass renderPass) const {
424 SkASSERT(fAttachmentFlags & kExternal_AttachmentFlag);
425 return fRenderPass == renderPass;
426}
427
428bool GrVkRenderPass::equalLoadStoreOps(const LoadStoreOps& colorOps,
429 const LoadStoreOps& resolveOps,
430 const LoadStoreOps& stencilOps) const {
431 SkASSERT(!(fAttachmentFlags & kExternal_AttachmentFlag));
432 if (fAttachmentFlags & kColor_AttachmentFlag) {
433 if (fAttachmentsDescriptor.fColor.fLoadStoreOps != colorOps) {
434 return false;
435 }
436 }
437 if (fAttachmentFlags & kResolve_AttachmentFlag) {
438 if (fAttachmentsDescriptor.fResolve.fLoadStoreOps != resolveOps) {
439 return false;
440 }
441 }
442 if (fAttachmentFlags & kStencil_AttachmentFlag) {
443 if (fAttachmentsDescriptor.fStencil.fLoadStoreOps != stencilOps) {
444 return false;
445 }
446 }
447 return true;
448}
449
451 GenKey(b, fAttachmentFlags, fAttachmentsDescriptor, fSelfDepFlags,
452 fLoadFromResolve, (uint64_t)fRenderPass);
453}
454
456 AttachmentFlags attachmentFlags,
457 const AttachmentsDescriptor& attachmentsDescriptor,
458 SelfDependencyFlags selfDepFlags,
459 LoadFromResolve loadFromResolve,
460 uint64_t externalRenderPass) {
461 b->add32(attachmentFlags);
462 if (attachmentFlags & kColor_AttachmentFlag) {
463 b->add32(attachmentsDescriptor.fColor.fFormat);
464 b->add32(attachmentsDescriptor.fColor.fSamples);
465 }
466 if (attachmentFlags & kResolve_AttachmentFlag) {
467 b->add32(attachmentsDescriptor.fResolve.fFormat);
468 b->add32(attachmentsDescriptor.fResolve.fSamples);
469 }
470 if (attachmentFlags & kStencil_AttachmentFlag) {
471 b->add32(attachmentsDescriptor.fStencil.fFormat);
472 b->add32(attachmentsDescriptor.fStencil.fSamples);
473 }
474
475 uint32_t extraFlags = (uint32_t)selfDepFlags;
476 SkASSERT(extraFlags < (1 << 30));
477 SkASSERT((uint32_t)loadFromResolve <= 2);
478 extraFlags |= ((uint32_t)loadFromResolve << 30);
479
480 b->add32(extraFlags);
481
482 if (attachmentFlags & kExternal_AttachmentFlag) {
483 SkASSERT(!(attachmentFlags & ~kExternal_AttachmentFlag));
484 b->add32((uint32_t)(externalRenderPass & 0xFFFFFFFF));
485 b->add32((uint32_t)(externalRenderPass>>32));
486 }
487}
GrVkRenderPass::AttachmentsDescriptor::AttachmentDesc AttachmentDesc
void setup_vk_attachment_description(VkAttachmentDescription *attachment, const AttachmentDesc &desc, VkImageLayout startLayout, VkImageLayout endLayout)
#define GR_VK_CALL(IFACE, X)
Definition GrVkUtil.h:24
#define GR_VK_CALL_RESULT(GPU, RESULT, X)
Definition GrVkUtil.h:35
static sk_sp< Effect > Create()
#define SkAssertResult(cond)
Definition SkAssert.h:123
#define SkUNREACHABLE
Definition SkAssert.h:135
#define SK_ABORT(message,...)
Definition SkAssert.h:70
#define SkASSERT(cond)
Definition SkAssert.h:116
#define INHERITED(method,...)
static constexpr bool SkToBool(const T &x)
Definition SkTo.h:35
bool advancedBlendEquationSupport() const
Definition GrCaps.h:162
bool advancedCoherentBlendEquationSupport() const
Definition GrCaps.h:166
bool textureBarrierSupport() const
Definition GrCaps.h:78
const GrCaps * caps() const
Definition GrGpu.h:73
uint32_t maxInputAttachmentDescriptors() const
Definition GrVkCaps.h:181
const GrVkCaps & vkCaps() const
Definition GrVkGpu.h:61
const skgpu::VulkanInterface * vkInterface() const
Definition GrVkGpu.h:60
VkDevice device() const
Definition GrVkGpu.h:71
GrVkRenderPass(const GrVkGpu *gpu, VkRenderPass renderPass, uint32_t colorAttachmentIndex)
bool colorAttachmentIndex(uint32_t *index) const
void freeGPUData() const override
void genKey(skgpu::KeyBuilder *) const
const VkExtent2D & granularity() const
LoadFromResolve loadFromResolve() const
bool isCompatible(GrVkRenderTarget *target, SelfDependencyFlags selfDepFlags, LoadFromResolve) const
static void GenKey(skgpu::KeyBuilder *, AttachmentFlags, const AttachmentsDescriptor &, SelfDependencyFlags selfDepFlags, LoadFromResolve, uint64_t externalRenderPass)
bool isCompatibleExternalRP(VkRenderPass) const
bool stencilAttachmentIndex(uint32_t *index) const
static GrVkRenderPass * Create(GrVkGpu *, const GrVkRenderPass &compatibleRenderPass, const LoadStoreOps &colorOp, const LoadStoreOps &resolveOp, const LoadStoreOps &stencilOp)
static GrVkRenderPass * CreateSimple(GrVkGpu *, AttachmentsDescriptor *, AttachmentFlags, SelfDependencyFlags selfDepFlags, LoadFromResolve)
const LoadStoreOps & resolveOps
uint32_t clearValueCount() const
static bool b
FlutterSemanticsFlag flags
GAsyncResult * result
uint32_t * target
static constexpr bool SampleCountToVkSampleCount(uint32_t samples, VkSampleCountFlagBits *vkSamples)
bool isCompatible(const AttachmentDesc &desc) const
VkAttachmentLoadOp loadOp
VkAttachmentStoreOp stencilStoreOp
VkSampleCountFlagBits samples
VkAttachmentDescriptionFlags flags
VkAttachmentStoreOp storeOp
VkImageLayout initialLayout
VkImageLayout finalLayout
VkAttachmentLoadOp stencilLoadOp
VkStructureType sType
const VkSubpassDescription * pSubpasses
const VkSubpassDependency * pDependencies
const VkAttachmentDescription * pAttachments
VkRenderPassCreateFlags flags
const VkAttachmentReference * pDepthStencilAttachment
VkSubpassDescriptionFlags flags
uint32_t inputAttachmentCount
const VkAttachmentReference * pResolveAttachments
const uint32_t * pPreserveAttachments
const VkAttachmentReference * pInputAttachments
uint32_t colorAttachmentCount
const VkAttachmentReference * pColorAttachments
VkPipelineBindPoint pipelineBindPoint
uint32_t preserveAttachmentCount
VkImageLayout
@ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
@ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
@ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
@ VK_IMAGE_LAYOUT_UNDEFINED
@ VK_IMAGE_LAYOUT_GENERAL
@ VK_DEPENDENCY_BY_REGION_BIT
@ VK_PIPELINE_BIND_POINT_GRAPHICS
#define VK_ATTACHMENT_UNUSED
VkResult
@ VK_SUCCESS
@ VK_ACCESS_INPUT_ATTACHMENT_READ_BIT
@ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
@ VK_ACCESS_COLOR_ATTACHMENT_READ_NONCOHERENT_BIT_EXT
@ VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
@ VK_ATTACHMENT_LOAD_OP_CLEAR
@ VK_ATTACHMENT_LOAD_OP_LOAD
@ VK_ATTACHMENT_LOAD_OP_DONT_CARE
@ VK_ATTACHMENT_STORE_OP_DONT_CARE
@ VK_ATTACHMENT_STORE_OP_STORE
@ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
@ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
@ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO