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 "GrVkFramebuffer.h"
11 #include "GrVkGpu.h"
12 #include "GrVkRenderTarget.h"
13 #include "GrVkUtil.h"
14 
setup_simple_vk_attachment_description(VkAttachmentDescription * attachment,VkFormat format,uint32_t samples,VkImageLayout layout)15 void setup_simple_vk_attachment_description(VkAttachmentDescription* attachment,
16                                             VkFormat format,
17                                             uint32_t samples,
18                                             VkImageLayout layout) {
19     attachment->flags = 0;
20     attachment->format = format;
21     SkAssertResult(GrSampleCountToVkSampleCount(samples, &attachment->samples));
22     attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
23     attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
24     attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
25     attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
26     attachment->initialLayout = layout;
27     attachment->finalLayout = layout;
28 }
29 
initSimple(const GrVkGpu * gpu,const GrVkRenderTarget & target)30 void GrVkRenderPass::initSimple(const GrVkGpu* gpu, const GrVkRenderTarget& target) {
31     // Get attachment information from render target. This includes which attachments the render
32     // target has (color, resolve, stencil) and the attachments format and sample count.
33     target.getAttachmentsDescriptor(&fAttachmentsDescriptor, &fAttachmentFlags);
34 
35     uint32_t numAttachments = fAttachmentsDescriptor.fAttachmentCount;
36     // Attachment descriptions to be set on the render pass
37     SkTArray<VkAttachmentDescription> attachments(numAttachments);
38     attachments.reset(numAttachments);
39     memset(attachments.begin(), 0, numAttachments*sizeof(VkAttachmentDescription));
40 
41     // Refs to attachments on the render pass (as described by teh VkAttachmentDescription above),
42     // that are used by the subpass.
43     VkAttachmentReference colorRef;
44     VkAttachmentReference resolveRef;
45     VkAttachmentReference stencilRef;
46     uint32_t currentAttachment = 0;
47 
48     // Go through each of the attachment types (color, resolve, stencil) and set the necessary
49     // on the various Vk structs.
50     VkSubpassDescription subpassDesc;
51     memset(&subpassDesc, 0, sizeof(VkSubpassDescription));
52     subpassDesc.flags = 0;
53     subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
54     subpassDesc.inputAttachmentCount = 0;
55     subpassDesc.pInputAttachments = nullptr;
56     if (fAttachmentFlags & kColor_AttachmentFlag) {
57         // set up color attachment
58         setup_simple_vk_attachment_description(&attachments[currentAttachment],
59                                                fAttachmentsDescriptor.fColor.fFormat,
60                                                fAttachmentsDescriptor.fColor.fSamples,
61                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
62         // setup subpass use of attachment
63         colorRef.attachment = currentAttachment++;
64         colorRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
65         subpassDesc.colorAttachmentCount = 1;
66     } else {
67         // I don't think there should ever be a time where we don't have a color attachment
68         SkASSERT(false);
69         colorRef.attachment = VK_ATTACHMENT_UNUSED;
70         colorRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
71         subpassDesc.colorAttachmentCount = 0;
72     }
73     subpassDesc.pColorAttachments = &colorRef;
74 
75     if (fAttachmentFlags & kResolve_AttachmentFlag) {
76         // set up resolve attachment
77         setup_simple_vk_attachment_description(&attachments[currentAttachment],
78                                                fAttachmentsDescriptor.fResolve.fFormat,
79                                                fAttachmentsDescriptor.fResolve.fSamples,
80                                                VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
81         // setup subpass use of attachment
82         resolveRef.attachment = currentAttachment++;
83         // I'm really not sure what the layout should be for the resolve textures.
84         resolveRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
85         subpassDesc.pResolveAttachments = &resolveRef;
86     } else {
87         subpassDesc.pResolveAttachments = nullptr;
88     }
89 
90     if (fAttachmentFlags & kStencil_AttachmentFlag) {
91         // set up stencil attachment
92         setup_simple_vk_attachment_description(&attachments[currentAttachment],
93                                                fAttachmentsDescriptor.fStencil.fFormat,
94                                                fAttachmentsDescriptor.fStencil.fSamples,
95                                                VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
96         // setup subpass use of attachment
97         stencilRef.attachment = currentAttachment++;
98         stencilRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
99     } else {
100         stencilRef.attachment = VK_ATTACHMENT_UNUSED;
101         stencilRef.layout = VK_IMAGE_LAYOUT_UNDEFINED;
102     }
103     subpassDesc.pDepthStencilAttachment = &stencilRef;
104 
105     subpassDesc.preserveAttachmentCount = 0;
106     subpassDesc.pPreserveAttachments = nullptr;
107 
108     SkASSERT(numAttachments == currentAttachment);
109 
110     // Create the VkRenderPass compatible with the attachment descriptions above
111     VkRenderPassCreateInfo createInfo;
112     memset(&createInfo, 0, sizeof(VkRenderPassCreateInfo));
113     createInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
114     createInfo.pNext = nullptr;
115     createInfo.flags = 0;
116     createInfo.attachmentCount = numAttachments;
117     createInfo.pAttachments = attachments.begin();
118     createInfo.subpassCount = 1;
119     createInfo.pSubpasses = &subpassDesc;
120     createInfo.dependencyCount = 0;
121     createInfo.pDependencies = nullptr;
122 
123     GR_VK_CALL_ERRCHECK(gpu->vkInterface(), CreateRenderPass(gpu->device(),
124                                                              &createInfo,
125                                                              nullptr,
126                                                              &fRenderPass));
127 }
128 
freeGPUData(const GrVkGpu * gpu) const129 void GrVkRenderPass::freeGPUData(const GrVkGpu* gpu) const {
130     GR_VK_CALL(gpu->vkInterface(), DestroyRenderPass(gpu->device(), fRenderPass, nullptr));
131 }
132 
133 // Works under the assumption that color attachment will always be the first attachment in our
134 // attachment array if it exists.
colorAttachmentIndex(uint32_t * index) const135 bool GrVkRenderPass::colorAttachmentIndex(uint32_t* index) const {
136     *index = 0;
137     if (fAttachmentFlags & kColor_AttachmentFlag) {
138         return true;
139     }
140     return false;
141 }
142 
143 // Works under the assumption that resolve attachment will always be after the color attachment.
resolveAttachmentIndex(uint32_t * index) const144 bool GrVkRenderPass::resolveAttachmentIndex(uint32_t* index) const {
145     *index = 0;
146     if (fAttachmentFlags & kColor_AttachmentFlag) {
147         ++(*index);
148     }
149     if (fAttachmentFlags & kResolve_AttachmentFlag) {
150         return true;
151     }
152     return false;
153 }
154 
155 // Works under the assumption that stencil attachment will always be after the color and resolve
156 // attachment.
stencilAttachmentIndex(uint32_t * index) const157 bool GrVkRenderPass::stencilAttachmentIndex(uint32_t* index) const {
158     *index = 0;
159     if (fAttachmentFlags & kColor_AttachmentFlag) {
160         ++(*index);
161     }
162     if (fAttachmentFlags & kResolve_AttachmentFlag) {
163         ++(*index);
164     }
165     if (fAttachmentFlags & kStencil_AttachmentFlag) {
166         return true;
167     }
168     return false;
169 }
170 
getBeginInfo(const GrVkRenderTarget & target,VkRenderPassBeginInfo * beginInfo,VkSubpassContents * contents) const171 void GrVkRenderPass::getBeginInfo(const GrVkRenderTarget& target,
172                                   VkRenderPassBeginInfo* beginInfo,
173                                   VkSubpassContents* contents) const {
174     SkASSERT(this->isCompatible(target));
175 
176     VkRect2D renderArea;
177     renderArea.offset = { 0, 0 };
178     renderArea.extent = { (uint32_t)target.width(), (uint32_t)target.height() };
179 
180     memset(beginInfo, 0, sizeof(VkRenderPassBeginInfo));
181     beginInfo->sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
182     beginInfo->pNext = nullptr;
183     beginInfo->renderPass = fRenderPass;
184     beginInfo->framebuffer = target.framebuffer()->framebuffer();
185     beginInfo->renderArea = renderArea;
186     beginInfo->clearValueCount = 0;
187     beginInfo->pClearValues = nullptr;
188 
189     // Currently just assuming no secondary cmd buffers. This value will need to be update if we
190     // have them.
191     *contents = VK_SUBPASS_CONTENTS_INLINE;
192 }
193 
isCompatible(const GrVkRenderTarget & target) const194 bool GrVkRenderPass::isCompatible(const GrVkRenderTarget& target) const {
195     AttachmentsDescriptor desc;
196     AttachmentFlags flags;
197     target.getAttachmentsDescriptor(&desc, &flags);
198 
199     if (flags != fAttachmentFlags) {
200         return false;
201     }
202 
203     if (fAttachmentFlags & kColor_AttachmentFlag) {
204         if (fAttachmentsDescriptor.fColor != desc.fColor) {
205             return false;
206         }
207     }
208     if (fAttachmentFlags & kResolve_AttachmentFlag) {
209         if (fAttachmentsDescriptor.fResolve != desc.fResolve) {
210             return false;
211         }
212     }
213     if (fAttachmentFlags & kStencil_AttachmentFlag) {
214         if (fAttachmentsDescriptor.fStencil != desc.fStencil) {
215             return false;
216         }
217     }
218 
219     return true;
220 }
221