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