xref: /aosp_15_r20/external/skia/src/gpu/graphite/vk/VulkanRenderPass.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2 * Copyright 2023 Google LLC
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 
8 #include "src/gpu/graphite/vk/VulkanRenderPass.h"
9 
10 #include "include/gpu/graphite/vk/VulkanGraphiteTypes.h"
11 #include "src/gpu/graphite/RenderPassDesc.h"
12 #include "src/gpu/graphite/Texture.h"
13 #include "src/gpu/graphite/vk/VulkanCommandBuffer.h"
14 #include "src/gpu/graphite/vk/VulkanGraphiteUtilsPriv.h"
15 #include "src/gpu/graphite/vk/VulkanSharedContext.h"
16 #include "src/gpu/graphite/vk/VulkanTexture.h"
17 
18 #include <limits>
19 
20 namespace skgpu::graphite {
21 
22 namespace { // anonymous namespace
23 
determine_uint32_count(int rpAttachmentCount,int subpassCount,int subpassDependencyCount)24 int determine_uint32_count(int rpAttachmentCount, int subpassCount, int subpassDependencyCount ) {
25     // The key will be formed such that bigger-picture items (such as the total attachment count)
26     // will be near the front of the key to more quickly eliminate incompatible keys. Each
27     // renderpass key will start with the total number of attachments associated with it
28     // followed by how many subpasses and subpass dependencies the renderpass has.Packed together,
29     // these will use one uint32.
30     int num32DataCnt = 1;
31     SkASSERT(static_cast<uint32_t>(rpAttachmentCount) <= (1u << 8));
32     SkASSERT(static_cast<uint32_t>(subpassCount) <= (1u << 8));
33     SkASSERT(static_cast<uint32_t>(subpassDependencyCount) <= (1u << 8));
34 
35     // The key will then contain key information for each attachment. This includes format, sample
36     // count, and load/store operation information.
37     num32DataCnt += 3 * rpAttachmentCount;
38     // Then, subpass information will be added in the form of attachment reference indices. Reserve
39     // one int32 for each possible attachment reference type, of which there are 4.
40     // There are 4 possible attachment reference types. Pack all 4 attachment reference indices into
41     // one uint32.
42     num32DataCnt += subpassCount;
43     // Each subpass dependency will be allotted 6 int32s to store all its pertinent information.
44     num32DataCnt += 6 * subpassDependencyCount;
45 
46     return num32DataCnt;
47 }
48 
add_attachment_description_info_to_key(ResourceKey::Builder & builder,const TextureInfo & textureInfo,int & builderIdx,LoadOp loadOp,StoreOp storeOp)49 void add_attachment_description_info_to_key(ResourceKey::Builder& builder,
50                                             const TextureInfo& textureInfo,
51                                             int& builderIdx,
52                                             LoadOp loadOp,
53                                             StoreOp storeOp) {
54     VulkanTextureInfo vkTexInfo;
55     if (textureInfo.isValid() && TextureInfos::GetVulkanTextureInfo(textureInfo, &vkTexInfo)) {
56         builder[builderIdx++] = vkTexInfo.fFormat;
57         builder[builderIdx++] = vkTexInfo.fSampleCount;
58         SkASSERT(sizeof(loadOp)  < (1u << 8));
59         SkASSERT(sizeof(storeOp) < (1u << 8));
60         builder[builderIdx++] = static_cast<uint8_t>(loadOp) << 8 | static_cast<uint8_t>(storeOp);
61     }
62     // We only count attachments that are valid textures when calculating the total number of
63     // render pass attachments, so if a texture is invalid, simply skip it rather than using
64     // VK_ATTACHMENT_UNUSED and incrementing the builderIdx. Attachments can be differentiated from
65     // one another by their sample count and format (i.e. depth/stencil attachments will have a
66     // depth/stencil format).
67 }
68 
add_subpass_info_to_key(ResourceKey::Builder & builder,int & builderIdx,bool hasColorAttachment,bool hasColorResolveAttachment,bool hasDepthStencilAttachment,bool loadMSAAFromResolve,int subpassCount,int subpassDependencyCount)69 void add_subpass_info_to_key(ResourceKey::Builder& builder,
70                              int& builderIdx,
71                              bool hasColorAttachment,
72                              bool hasColorResolveAttachment,
73                              bool hasDepthStencilAttachment,
74                              bool loadMSAAFromResolve,
75                              int subpassCount,
76                              int subpassDependencyCount) {
77     // TODO: Fetch actual attachment reference and index information for each
78     // subpass from RenderPassDesc. For now, determine subpass data based upon whether we are
79     // loading from MSAA or not.
80     const int mainSubpassIdx = loadMSAAFromResolve ? 1 : 0;
81     // Assign a smaller value to represent VK_ATTACHMENT_UNUSED.
82     static constexpr int kAttachmentUnused = std::numeric_limits<uint8_t>::max();
83 
84     // The following key structure assumes that we only have up to one reference of each type per
85     // subpass and that attachments are indexed in order of color, resolve, depth/stencil, then
86     // input attachments. These indices are statically defined in the VulkanRenderPass header file.
87     for (int j = 0; j < subpassCount; j++) {
88         if (j == mainSubpassIdx) {
89             uint32_t attachmentIdxKeyInfo;
90             attachmentIdxKeyInfo = hasColorAttachment ? VulkanRenderPass::kColorAttachmentIdx
91                                                       : kAttachmentUnused;
92             attachmentIdxKeyInfo |=
93                     (hasColorResolveAttachment ? VulkanRenderPass::kColorResolveAttachmentIdx
94                                                : kAttachmentUnused) << 8;
95             attachmentIdxKeyInfo |=
96                     (hasDepthStencilAttachment ? VulkanRenderPass::kDepthStencilAttachmentIdx
97                                                : kAttachmentUnused) << 16;
98             // TODO: Add input attachment info to key once supported for use in main subpass
99             attachmentIdxKeyInfo |= kAttachmentUnused << 24;
100 
101             builder[builderIdx++] = attachmentIdxKeyInfo;
102         } else { // Loading MSAA from resolve subpass
103             SkASSERT(hasColorAttachment);
104             builder[builderIdx++] =
105                     VulkanRenderPass::kColorAttachmentIdx | // color attachment
106                     (kAttachmentUnused << 8)              | // No color resolve attachment
107                     (kAttachmentUnused << 16)             | // No depth/stencil attachment
108                     // The input attachment for the load subpass is the color resolve texture.
109                     (VulkanRenderPass::kColorResolveAttachmentIdx << 24);
110         }
111     }
112 
113     // TODO: Query RenderPassDesc for subpass dependency information & populate the key accordingly.
114     // For now, we know that the only subpass dependency will be that expected for loading MSAA from
115     // resolve.
116     for (int i = 0; i < subpassDependencyCount; i++) {
117         builder[builderIdx++] = 0 | (mainSubpassIdx << 8); // srcSubpass, dstSubpass
118         builder[builderIdx++] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // srcStageMask
119         builder[builderIdx++] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; // dstStageMask
120         builder[builderIdx++] = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;          // srcAccessMask
121         builder[builderIdx++] = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |          // dstAccessMask
122                                 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
123         builder[builderIdx++] = VK_DEPENDENCY_BY_REGION_BIT;                   // dependencyFlags
124     }
125 }
126 
populate_key(VulkanRenderPass::VulkanRenderPassMetaData & rpMetaData,ResourceKey::Builder & builder,int & builderIdx,bool compatibleOnly)127 void populate_key(VulkanRenderPass::VulkanRenderPassMetaData& rpMetaData,
128                   ResourceKey::Builder& builder,
129                   int& builderIdx,
130                   bool compatibleOnly) {
131     builder[builderIdx++] = rpMetaData.fAttachments.size()  |
132                             (rpMetaData.fSubpassCount << 8) |
133                             (rpMetaData.fSubpassDependencyCount << 16);
134 
135     // Iterate through each renderpass attachment to add its information
136     for (int i = 0; i < rpMetaData.fAttachments.size(); i++) {
137         add_attachment_description_info_to_key(
138                 builder,
139                 rpMetaData.fAttachments[i]->fTextureInfo,
140                 builderIdx,
141                 // Assign LoadOp::kLoad and StoreOp::kStore as default load/store operations for
142                 // compatible render passes where load/store ops don't need to match.
143                 compatibleOnly ? LoadOp::kLoad   : rpMetaData.fAttachments[i]->fLoadOp,
144                 compatibleOnly ? StoreOp::kStore : rpMetaData.fAttachments[i]->fStoreOp);
145     }
146 
147     add_subpass_info_to_key(builder,
148                             builderIdx,
149                             rpMetaData.fHasColorAttachment,
150                             rpMetaData.fHasColorResolveAttachment,
151                             rpMetaData.fHasDepthStencilAttachment,
152                             rpMetaData.fLoadMSAAFromResolve,
153                             rpMetaData.fSubpassCount,
154                             rpMetaData.fSubpassDependencyCount);
155 }
156 
157 } // anonymous namespace
158 
VulkanRenderPassMetaData(const RenderPassDesc & renderPassDesc)159 VulkanRenderPass::VulkanRenderPassMetaData::VulkanRenderPassMetaData(
160         const RenderPassDesc& renderPassDesc) {
161     fLoadMSAAFromResolve = renderPassDesc.fColorResolveAttachment.fTextureInfo.isValid() &&
162                            renderPassDesc.fColorResolveAttachment.fLoadOp == LoadOp::kLoad;
163     fHasColorAttachment        = renderPassDesc.fColorAttachment.fTextureInfo.isValid();
164     fHasColorResolveAttachment =
165             renderPassDesc.fColorResolveAttachment.fTextureInfo.isValid();
166     fHasDepthStencilAttachment =
167             renderPassDesc.fDepthStencilAttachment.fTextureInfo.isValid();
168 
169     // TODO: Query for more attachments once the RenderPassDesc struct contains that information.
170     // For now, we only ever expect to see 0 or 1 of each attachment type (color, resolve, and
171     // depth/stencil), so the count of each of those can simply be determined with a bool.
172     fNumColorAttachments        = fHasColorAttachment ? 1 : 0;
173     fNumResolveAttachments      = fHasColorResolveAttachment ? 1 : 0;
174     fNumDepthStencilAttachments = fHasDepthStencilAttachment ? 1 : 0;
175 
176     // Accumulate attachments into a container to mimic future structure in RenderPassDesc
177     fAttachments = skia_private::TArray<const AttachmentDesc*>(fNumColorAttachments   +
178                                                                fNumResolveAttachments +
179                                                                fNumDepthStencilAttachments);
180     if (fHasColorAttachment) {
181         fAttachments.push_back(&renderPassDesc.fColorAttachment);
182     }
183     if (fHasColorResolveAttachment) {
184         fAttachments.push_back(&renderPassDesc.fColorResolveAttachment);
185     }
186     if (fHasDepthStencilAttachment) {
187         fAttachments.push_back(&renderPassDesc.fDepthStencilAttachment);
188     }
189 
190     // TODO: Reference RenderPassDesc to determine number and makeup of subpasses and their
191     // dependencies. For now, we only ever expect 1 (in most cases) or 2 (when loading MSAA).
192     fSubpassCount = fLoadMSAAFromResolve ? 2 : 1;
193     fSubpassDependencyCount = fLoadMSAAFromResolve ? 1 : 0;
194     fUint32DataCnt = determine_uint32_count(
195             fAttachments.size(), fSubpassCount,  fSubpassDependencyCount);
196 }
197 
MakeRenderPassKey(const RenderPassDesc & renderPassDesc,bool compatibleOnly)198 GraphiteResourceKey VulkanRenderPass::MakeRenderPassKey(
199         const RenderPassDesc& renderPassDesc, bool compatibleOnly) {
200 
201     VulkanRenderPassMetaData rpMetaData = VulkanRenderPassMetaData(renderPassDesc);
202 
203     static const ResourceType kType = GraphiteResourceKey::GenerateResourceType();
204     GraphiteResourceKey key;
205     GraphiteResourceKey::Builder builder(&key, kType, rpMetaData.fUint32DataCnt, Shareable::kYes);
206 
207     int startingIdx = 0;
208     populate_key(rpMetaData, builder, startingIdx, compatibleOnly);
209 
210     builder.finish();
211     return key;
212 }
213 
AddRenderPassInfoToKey(VulkanRenderPassMetaData & rpMetaData,ResourceKey::Builder & builder,int & builderIdx,bool compatibleOnly)214 void VulkanRenderPass::AddRenderPassInfoToKey(VulkanRenderPassMetaData& rpMetaData,
215                                               ResourceKey::Builder& builder,
216                                               int& builderIdx,
217                                               bool compatibleOnly) {
218     populate_key(rpMetaData, builder, builderIdx, /*compatibleOnly=*/true);
219 }
220 
221 namespace { // anonymous namespace
setup_vk_attachment_description(VkAttachmentDescription * outAttachment,const VulkanTextureInfo & textureInfo,const AttachmentDesc & desc,const LoadOp loadOp,const StoreOp storeOp,const VkImageLayout initialLayout,const VkImageLayout finalLayout)222 void setup_vk_attachment_description(VkAttachmentDescription* outAttachment,
223                                      const VulkanTextureInfo& textureInfo,
224                                      const AttachmentDesc& desc,
225                                      const LoadOp loadOp,
226                                      const StoreOp storeOp,
227                                      const VkImageLayout initialLayout,
228                                      const VkImageLayout finalLayout) {
229     static_assert((int)LoadOp::kLoad == 0);
230     static_assert((int)LoadOp::kClear == 1);
231     static_assert((int)LoadOp::kDiscard == 2);
232     static_assert(std::size(vkLoadOp) == kLoadOpCount);
233     static_assert((int)StoreOp::kStore == 0);
234     static_assert((int)StoreOp::kDiscard == 1);
235     static_assert(std::size(vkStoreOp) == kStoreOpCount);
236 
237     outAttachment->flags = 0;
238     outAttachment->format = textureInfo.fFormat;
239     VkSampleCountFlagBits sampleCount;
240     SkAssertResult(
241             skgpu::SampleCountToVkSampleCount(textureInfo.fSampleCount, &sampleCount));
242     outAttachment->samples = sampleCount;
243     switch (initialLayout) {
244         case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
245         case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
246         case VK_IMAGE_LAYOUT_GENERAL:
247             outAttachment->loadOp = vkLoadOp[static_cast<int>(loadOp)];
248             outAttachment->storeOp = vkStoreOp[static_cast<int>(storeOp)];
249             outAttachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
250             outAttachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
251             break;
252         case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
253             // The loadOp and storeOp refer to the depth part of the attachment and the stencil*Ops
254             // refer to the stencil bits in the attachment.
255             outAttachment->loadOp = vkLoadOp[static_cast<int>(loadOp)];
256             outAttachment->storeOp = vkStoreOp[static_cast<int>(storeOp)];
257             outAttachment->stencilLoadOp = vkLoadOp[static_cast<int>(loadOp)];
258             outAttachment->stencilStoreOp = vkStoreOp[static_cast<int>(storeOp)];
259             break;
260         default:
261             SK_ABORT("Unexpected attachment layout");
262     }
263     outAttachment->initialLayout = initialLayout;
264     outAttachment->finalLayout = finalLayout == VK_IMAGE_LAYOUT_UNDEFINED ? initialLayout
265                                                                           : finalLayout;
266 }
267 } // anonymous namespace
268 
MakeRenderPass(const VulkanSharedContext * context,const RenderPassDesc & renderPassDesc,bool compatibleOnly)269 sk_sp<VulkanRenderPass> VulkanRenderPass::MakeRenderPass(const VulkanSharedContext* context,
270                                                          const RenderPassDesc& renderPassDesc,
271                                                          bool compatibleOnly) {
272     VkRenderPass renderPass;
273     renderPass = VK_NULL_HANDLE;
274     auto& colorAttachmentTextureInfo        = renderPassDesc.fColorAttachment.fTextureInfo;
275     auto& colorResolveAttachmentTextureInfo = renderPassDesc.fColorResolveAttachment.fTextureInfo;
276     auto& depthStencilAttachmentTextureInfo = renderPassDesc.fDepthStencilAttachment.fTextureInfo;
277     bool hasColorAttachment        = colorAttachmentTextureInfo.isValid();
278     bool hasColorResolveAttachment = colorResolveAttachmentTextureInfo.isValid();
279     bool hasDepthStencilAttachment = depthStencilAttachmentTextureInfo.isValid();
280 
281     skia_private::TArray<VkAttachmentDescription> attachmentDescs;
282     // Create and track attachment references for the subpass.
283     VkAttachmentReference colorRef;
284     VkAttachmentReference resolveRef;
285     VkAttachmentReference resolveLoadInputRef;
286     VkAttachmentReference depthStencilRef;
287 
288     bool loadMSAAFromResolve = false;
289     if (hasColorAttachment) {
290         VulkanTextureInfo colorAttachTexInfo;
291         SkAssertResult(TextureInfos::GetVulkanTextureInfo(colorAttachmentTextureInfo,
292                                                           &colorAttachTexInfo));
293         auto& colorAttachDesc = renderPassDesc.fColorAttachment;
294 
295         colorRef.attachment = attachmentDescs.size();
296         VkAttachmentDescription& vkColorAttachDesc = attachmentDescs.push_back();
297         memset(&vkColorAttachDesc, 0, sizeof(VkAttachmentDescription));
298         setup_vk_attachment_description(
299                 &vkColorAttachDesc,
300                 colorAttachTexInfo,
301                 colorAttachDesc,
302                 compatibleOnly ? LoadOp::kDiscard  : colorAttachDesc.fLoadOp,
303                 compatibleOnly ? StoreOp::kDiscard : colorAttachDesc.fStoreOp,
304                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
305                 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
306         colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
307 
308         if (hasColorResolveAttachment) {
309             loadMSAAFromResolve = renderPassDesc.fColorResolveAttachment.fLoadOp == LoadOp::kLoad;
310             SkASSERT(renderPassDesc.fColorResolveAttachment.fStoreOp == StoreOp::kStore);
311             VulkanTextureInfo resolveAttachTexInfo;
312             SkAssertResult(TextureInfos::GetVulkanTextureInfo(colorResolveAttachmentTextureInfo,
313                                                               &resolveAttachTexInfo));
314             auto& resolveAttachDesc = renderPassDesc.fColorResolveAttachment;
315 
316             resolveRef.attachment = attachmentDescs.size();
317             VkAttachmentDescription& vkResolveAttachDesc = attachmentDescs.push_back();
318             memset(&vkResolveAttachDesc, 0, sizeof(VkAttachmentDescription));
319             setup_vk_attachment_description(
320                     &vkResolveAttachDesc,
321                     resolveAttachTexInfo,
322                     resolveAttachDesc,
323                     compatibleOnly ? LoadOp::kDiscard  : resolveAttachDesc.fLoadOp,
324                     compatibleOnly ? StoreOp::kDiscard : resolveAttachDesc.fStoreOp,
325                     loadMSAAFromResolve ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
326                                         : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
327                     VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
328             resolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
329         } else {
330             resolveRef.attachment = VK_ATTACHMENT_UNUSED;
331             resolveRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
332         }
333     } else {
334         SkASSERT(false);
335         colorRef.attachment = VK_ATTACHMENT_UNUSED;
336         colorRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
337         resolveRef.attachment = VK_ATTACHMENT_UNUSED;
338         resolveRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
339     }
340 
341     if (hasDepthStencilAttachment) {
342         VulkanTextureInfo depthStencilTexInfo;
343         SkAssertResult(TextureInfos::GetVulkanTextureInfo(depthStencilAttachmentTextureInfo,
344                                                           &depthStencilTexInfo));
345         auto& depthStencilAttachDesc = renderPassDesc.fDepthStencilAttachment;
346 
347         depthStencilRef.attachment = attachmentDescs.size();
348         VkAttachmentDescription& vkDepthStencilAttachDesc = attachmentDescs.push_back();
349         setup_vk_attachment_description(
350                 &vkDepthStencilAttachDesc,
351                 depthStencilTexInfo,
352                 depthStencilAttachDesc,
353                 compatibleOnly ? LoadOp::kDiscard   : depthStencilAttachDesc.fLoadOp,
354                 compatibleOnly ? StoreOp::kDiscard  : depthStencilAttachDesc.fStoreOp,
355                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
356                 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
357         depthStencilRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
358     } else {
359         depthStencilRef.attachment = VK_ATTACHMENT_UNUSED;
360         depthStencilRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
361     }
362 
363     // Create VkRenderPass
364     VkRenderPassCreateInfo renderPassInfo;
365     memset(&renderPassInfo, 0, sizeof(VkRenderPassCreateInfo));
366     renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
367     renderPassInfo.pNext = nullptr;
368     renderPassInfo.flags = 0;
369     renderPassInfo.subpassCount = loadMSAAFromResolve ? 2 : 1;
370 
371     skia_private::TArray<VkSubpassDescription> subpassDescs(renderPassInfo.subpassCount);
372     memset(subpassDescs.begin(), 0, renderPassInfo.subpassCount * sizeof(VkSubpassDescription));
373 
374     // If we are loading MSAA from resolve, that subpass must always be first.
375     VkSubpassDependency dependency;
376     if (loadMSAAFromResolve) {
377         resolveLoadInputRef.attachment = resolveRef.attachment;
378         resolveLoadInputRef.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
379 
380         VkSubpassDescription& loadSubpassDesc = subpassDescs.push_back();
381         memset(&loadSubpassDesc, 0, sizeof(VkSubpassDescription));
382         loadSubpassDesc.flags = 0;
383         loadSubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
384         loadSubpassDesc.inputAttachmentCount = 1;
385         loadSubpassDesc.pInputAttachments = &resolveLoadInputRef;
386         loadSubpassDesc.colorAttachmentCount = 1;
387         loadSubpassDesc.pColorAttachments = &colorRef;
388         loadSubpassDesc.pResolveAttachments = nullptr;
389         loadSubpassDesc.pDepthStencilAttachment = nullptr;
390         loadSubpassDesc.preserveAttachmentCount = 0;
391         loadSubpassDesc.pPreserveAttachments = nullptr;
392 
393         // Set up the subpass dependency
394         const int mainSubpassIdx = loadMSAAFromResolve ? 1 : 0;
395         dependency.srcSubpass = 0;
396         dependency.dstSubpass = mainSubpassIdx;
397         dependency.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT;
398         dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
399         dependency.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
400         dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
401         dependency.dstAccessMask =
402                 VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
403     }
404 
405     VkSubpassDescription& mainSubpassDesc = subpassDescs.push_back();
406     memset(&mainSubpassDesc, 0, sizeof(VkSubpassDescription));
407     mainSubpassDesc.flags = 0;
408     mainSubpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
409     mainSubpassDesc.inputAttachmentCount = 0; // TODO: Add input attachment support in main subpass
410     mainSubpassDesc.pInputAttachments = nullptr;
411     mainSubpassDesc.colorAttachmentCount = 1;
412     mainSubpassDesc.pColorAttachments = &colorRef;
413     mainSubpassDesc.pResolveAttachments = &resolveRef;
414     mainSubpassDesc.pDepthStencilAttachment = &depthStencilRef;
415     mainSubpassDesc.preserveAttachmentCount = 0;
416     mainSubpassDesc.pPreserveAttachments = nullptr;
417 
418     renderPassInfo.pSubpasses = subpassDescs.begin();
419     renderPassInfo.dependencyCount = loadMSAAFromResolve ? 1 : 0;
420     renderPassInfo.pDependencies = loadMSAAFromResolve ? &dependency : VK_NULL_HANDLE;
421     renderPassInfo.attachmentCount = attachmentDescs.size();
422     renderPassInfo.pAttachments = attachmentDescs.begin();
423 
424     VkResult result;
425     VULKAN_CALL_RESULT(context,
426                        result,
427                        CreateRenderPass(context->device(), &renderPassInfo, nullptr, &renderPass));
428     if (result != VK_SUCCESS) {
429         return nullptr;
430     }
431     VkExtent2D granularity;
432     VULKAN_CALL(context->interface(), GetRenderAreaGranularity(context->device(),
433                                                                renderPass,
434                                                                &granularity));
435     return sk_sp<VulkanRenderPass>(new VulkanRenderPass(context, renderPass, granularity));
436 }
437 
VulkanRenderPass(const VulkanSharedContext * context,VkRenderPass renderPass,VkExtent2D granularity)438 VulkanRenderPass::VulkanRenderPass(const VulkanSharedContext* context,
439                                    VkRenderPass renderPass,
440                                    VkExtent2D granularity)
441         : Resource(context,
442                    Ownership::kOwned,
443                    skgpu::Budgeted::kYes,
444                    /*gpuMemorySize=*/0)
445         , fSharedContext(context)
446         , fRenderPass(renderPass)
447         , fGranularity(granularity) {}
448 
freeGpuData()449 void VulkanRenderPass::freeGpuData() {
450     VULKAN_CALL(fSharedContext->interface(),
451                 DestroyRenderPass(fSharedContext->device(), fRenderPass, nullptr));
452 }
453 
454 } // namespace skgpu::graphite
455