• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include "GrVkRenderPass.h"
9 
10 #include "GrProcessor.h"
11 #include "GrVkFramebuffer.h"
12 #include "GrVkGpu.h"
13 #include "GrVkRenderTarget.h"
14 #include "GrVkUtil.h"
15 
16 typedef GrVkRenderPass::AttachmentsDescriptor::AttachmentDesc AttachmentDesc;
17 
setup_vk_attachment_description(VkAttachmentDescription * attachment,const AttachmentDesc & desc,VkImageLayout layout)18 void setup_vk_attachment_description(VkAttachmentDescription* attachment,
19                                      const AttachmentDesc& desc,
20                                      VkImageLayout layout) {
21     attachment->flags = 0;
22     attachment->format = desc.fFormat;
23     SkAssertResult(GrSampleCountToVkSampleCount(desc.fSamples, &attachment->samples));
24     switch (layout) {
25         case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
26             attachment->loadOp = desc.fLoadStoreOps.fLoadOp;
27             attachment->storeOp = desc.fLoadStoreOps.fStoreOp;
28             attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
29             attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
30             break;
31         case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
32             attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
33             attachment->storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
34             attachment->stencilLoadOp = desc.fLoadStoreOps.fLoadOp;
35             attachment->stencilStoreOp = desc.fLoadStoreOps.fStoreOp;
36             break;
37         default:
38             SkFAIL("Unexpected attachment layout");
39     }
40 
41     attachment->initialLayout = layout;
42     attachment->finalLayout = layout;
43 }
44 
initSimple(const GrVkGpu * gpu,const GrVkRenderTarget & target)45 void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& target) {
46     static const GrVkRenderPass::LoadStoreOps kBasicLoadStoreOps(VK_ATTACHMENT_LOAD_OP_LOAD,
47                                                                  VK_ATTACHMENT_STORE_OP_STORE);
48 
49     this->init(gpu, target, kBasicLoadStoreOps, kBasicLoadStoreOps);
50 }
51 
init(const GrVkGpu * gpu,const LoadStoreOps & colorOp,const LoadStoreOps & stencilOp)52 void GrVkRenderPass::init(const GrVkGpu* gpu,
53                           const LoadStoreOps& colorOp,
54                           const LoadStoreOps& stencilOp) {
55     uint32_t numAttachments = fAttachmentsDescriptor.fAttachmentCount;
56     // Attachment descriptions to be set on the render pass
57     SkTArray<VkAttachmentDescription> attachments(numAttachments);
58     attachments.reset(numAttachments);
59     memset(attachments.begin(), 0, numAttachments * sizeof(VkAttachmentDescription));
60 
61     // Refs to attachments on the render pass (as described by teh VkAttachmentDescription above),
62     // that are used by the subpass.
63     VkAttachmentReference colorRef;
64     VkAttachmentReference stencilRef;
65     uint32_t currentAttachment = 0;
66 
67     // Go through each of the attachment types (color, stencil) and set the necessary
68     // on the various Vk structs.
69     VkSubpassDescription subpassDesc;
70     memset(&subpassDesc, 0, sizeof(VkSubpassDescription));
71     subpassDesc.flags = 0;
72     subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
73     subpassDesc.inputAttachmentCount = 0;
74     subpassDesc.pInputAttachments = nullptr;
75     subpassDesc.pResolveAttachments = nullptr;
76 
77     if (fAttachmentFlags & kColor_AttachmentFlag) {
78         // set up color attachment
79         fAttachmentsDescriptor.fColor.fLoadStoreOps = colorOp;
80         setup_vk_attachment_description(&attachments[currentAttachment],
81                                         fAttachmentsDescriptor.fColor,
82                                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
83         // setup subpass use of attachment
84         colorRef.attachment = currentAttachment++;
85         colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
86         subpassDesc.colorAttachmentCount = 1;
87 
88         if (VK_ATTACHMENT_LOAD_OP_CLEAR == colorOp.fLoadOp) {
89             fClearValueCount++;
90         }
91     } else {
92         // I don't think there should ever be a time where we don't have a color attachment
93         SkASSERT(false);
94         colorRef.attachment = VK_ATTACHMENT_UNUSED;
95         colorRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
96         subpassDesc.colorAttachmentCount = 0;
97     }
98     subpassDesc.pColorAttachments = &colorRef;
99 
100     if (fAttachmentFlags & kStencil_AttachmentFlag) {
101         // set up stencil attachment
102         fAttachmentsDescriptor.fStencil.fLoadStoreOps = stencilOp;
103         setup_vk_attachment_description(&attachments[currentAttachment],
104                                         fAttachmentsDescriptor.fStencil,
105                                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
106         // setup subpass use of attachment
107         stencilRef.attachment = currentAttachment++;
108         stencilRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
109         if (VK_ATTACHMENT_LOAD_OP_CLEAR == stencilOp.fLoadOp) {
110             fClearValueCount++;
111         }
112     } else {
113         stencilRef.attachment = VK_ATTACHMENT_UNUSED;
114         stencilRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
115     }
116     subpassDesc.pDepthStencilAttachment = &stencilRef;
117 
118     subpassDesc.preserveAttachmentCount = 0;
119     subpassDesc.pPreserveAttachments = nullptr;
120 
121     SkASSERT(numAttachments == currentAttachment);
122 
123     // Create the VkRenderPass compatible with the attachment descriptions above
124     VkRenderPassCreateInfo createInfo;
125     memset(&createInfo, 0, sizeof(VkRenderPassCreateInfo));
126     createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
127     createInfo.pNext = nullptr;
128     createInfo.flags = 0;
129     createInfo.attachmentCount = numAttachments;
130     createInfo.pAttachments = attachments.begin();
131     createInfo.subpassCount = 1;
132     createInfo.pSubpasses = &subpassDesc;
133     createInfo.dependencyCount = 0;
134     createInfo.pDependencies = nullptr;
135 
136     GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateRenderPass(gpu->device(),
137                                                              &createInfo,
138                                                              nullptr,
139                                                              &fRenderPass));
140 
141     // Get granularity for this render pass
142     GR_VK_CALL(gpu->vkInterface(), GetRenderAreaGranularity(gpu->device(),
143                                                             fRenderPass,
144                                                             &fGranularity));
145 }
146 
init(const GrVkGpu * gpu,const GrVkRenderPass & compatibleRenderPass,const LoadStoreOps & colorOp,const LoadStoreOps & stencilOp)147 void GrVkRenderPass::init(const GrVkGpu* gpu,
148                           const GrVkRenderPass& compatibleRenderPass,
149                           const LoadStoreOps& colorOp,
150                           const LoadStoreOps& stencilOp) {
151     fAttachmentFlags = compatibleRenderPass.fAttachmentFlags;
152     fAttachmentsDescriptor = compatibleRenderPass.fAttachmentsDescriptor;
153     this->init(gpu, colorOp, stencilOp);
154 }
155 
init(const GrVkGpu * gpu,const GrVkRenderTarget & target,const LoadStoreOps & colorOp,const LoadStoreOps & stencilOp)156 void GrVkRenderPass::init(const GrVkGpu* gpu,
157                           const GrVkRenderTarget& target,
158                           const LoadStoreOps& colorOp,
159                           const LoadStoreOps& stencilOp) {
160     // Get attachment information from render target. This includes which attachments the render
161     // target has (color, stencil) and the attachments format and sample count.
162     target.getAttachmentsDescriptor(&fAttachmentsDescriptor, &fAttachmentFlags);
163     this->init(gpu, colorOp, stencilOp);
164 }
165 
freeGPUData(const GrVkGpu * gpu) const166 void GrVkRenderPass::freeGPUData(const GrVkGpu* gpu) const {
167     GR_VK_CALL(gpu->vkInterface(), DestroyRenderPass(gpu->device(), fRenderPass, nullptr));
168 }
169 
170 // Works under the assumption that color attachment will always be the first attachment in our
171 // attachment array if it exists.
colorAttachmentIndex(uint32_t * index) const172 bool GrVkRenderPass::colorAttachmentIndex(uint32_t* index) const {
173     *index = 0;
174     if (fAttachmentFlags & kColor_AttachmentFlag) {
175         return true;
176     }
177     return false;
178 }
179 
180 // Works under the assumption that stencil attachment will always be after the color and resolve
181 // attachment.
stencilAttachmentIndex(uint32_t * index) const182 bool GrVkRenderPass::stencilAttachmentIndex(uint32_t* index) const {
183     *index = 0;
184     if (fAttachmentFlags & kColor_AttachmentFlag) {
185         ++(*index);
186     }
187     if (fAttachmentFlags & kStencil_AttachmentFlag) {
188         return true;
189     }
190     return false;
191 }
192 
isCompatible(const AttachmentsDescriptor & desc,const AttachmentFlags & flags) const193 bool GrVkRenderPass::isCompatible(const AttachmentsDescriptor& desc,
194                                   const AttachmentFlags& flags) const {
195     if (flags != fAttachmentFlags) {
196         return false;
197     }
198 
199     if (fAttachmentFlags & kColor_AttachmentFlag) {
200         if (!fAttachmentsDescriptor.fColor.isCompatible(desc.fColor)) {
201             return false;
202         }
203     }
204     if (fAttachmentFlags & kStencil_AttachmentFlag) {
205         if (!fAttachmentsDescriptor.fStencil.isCompatible(desc.fStencil)) {
206             return false;
207         }
208     }
209 
210     return true;
211 }
212 
isCompatible(const GrVkRenderTarget & target) const213 bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const {
214     AttachmentsDescriptor desc;
215     AttachmentFlags flags;
216     target.getAttachmentsDescriptor(&desc, &flags);
217 
218     return this->isCompatible(desc, flags);
219 }
220 
isCompatible(const GrVkRenderPass & renderPass) const221 bool GrVkRenderPass::isCompatible(const GrVkRenderPass& renderPass) const {
222     return this->isCompatible(renderPass.fAttachmentsDescriptor, renderPass.fAttachmentFlags);
223 }
224 
equalLoadStoreOps(const LoadStoreOps & colorOps,const LoadStoreOps & stencilOps) const225 bool GrVkRenderPass::equalLoadStoreOps(const LoadStoreOps& colorOps,
226                                        const LoadStoreOps& stencilOps) const {
227     if (fAttachmentFlags & kColor_AttachmentFlag) {
228         if (fAttachmentsDescriptor.fColor.fLoadStoreOps != colorOps) {
229             return false;
230         }
231     }
232     if (fAttachmentFlags & kStencil_AttachmentFlag) {
233         if (fAttachmentsDescriptor.fStencil.fLoadStoreOps != stencilOps) {
234             return false;
235         }
236     }
237     return true;
238 }
239 
genKey(GrProcessorKeyBuilder * b) const240 void GrVkRenderPass::genKey(GrProcessorKeyBuilder* b) const {
241     b->add32(fAttachmentFlags);
242     if (fAttachmentFlags & kColor_AttachmentFlag) {
243         b->add32(fAttachmentsDescriptor.fColor.fFormat);
244         b->add32(fAttachmentsDescriptor.fColor.fSamples);
245     }
246     if (fAttachmentFlags & kStencil_AttachmentFlag) {
247         b->add32(fAttachmentsDescriptor.fStencil.fFormat);
248         b->add32(fAttachmentsDescriptor.fStencil.fSamples);
249     }
250 }
251