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