1 /*
2 * Copyright 2018 Collabora Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "zink_render_pass.h"
25
26 #include "zink_screen.h"
27
28 #include "util/u_memory.h"
29 #include "util/u_string.h"
30
31 static VkRenderPass
create_render_pass(struct zink_screen * screen,struct zink_render_pass_state * state,struct zink_render_pass_pipeline_state * pstate)32 create_render_pass(struct zink_screen *screen, struct zink_render_pass_state *state, struct zink_render_pass_pipeline_state *pstate)
33 {
34
35 VkAttachmentReference color_refs[PIPE_MAX_COLOR_BUFS], zs_ref;
36 VkAttachmentReference input_attachments[PIPE_MAX_COLOR_BUFS];
37 VkAttachmentDescription attachments[PIPE_MAX_COLOR_BUFS + 1];
38 VkPipelineStageFlags dep_pipeline = 0;
39 VkAccessFlags dep_access = 0;
40 unsigned input_count = 0;
41
42 pstate->num_attachments = state->num_cbufs;
43 for (int i = 0; i < state->num_cbufs; i++) {
44 struct zink_rt_attrib *rt = state->rts + i;
45 attachments[i].flags = 0;
46 pstate->attachments[i].format = attachments[i].format = rt->format;
47 pstate->attachments[i].samples = attachments[i].samples = rt->samples;
48 attachments[i].loadOp = rt->clear_color ? VK_ATTACHMENT_LOAD_OP_CLEAR :
49 state->swapchain_init && rt->swapchain ?
50 VK_ATTACHMENT_LOAD_OP_DONT_CARE :
51 VK_ATTACHMENT_LOAD_OP_LOAD;
52 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
53 attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
54 attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
55 /* if layout changes are ever handled here, need VkAttachmentSampleLocationsEXT */
56 VkImageLayout layout = rt->fbfetch ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
57 attachments[i].initialLayout = layout;
58 attachments[i].finalLayout = layout;
59 color_refs[i].attachment = i;
60 color_refs[i].layout = layout;
61 dep_pipeline |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
62 if (rt->fbfetch)
63 memcpy(&input_attachments[input_count++], &color_refs[i], sizeof(VkAttachmentReference));
64 dep_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
65 if (attachments[i].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
66 dep_access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
67 }
68
69 int num_attachments = state->num_cbufs;
70 if (state->have_zsbuf) {
71 struct zink_rt_attrib *rt = state->rts + state->num_cbufs;
72 bool has_clear = rt->clear_color || rt->clear_stencil;
73 VkImageLayout layout = rt->needs_write || has_clear ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
74 attachments[num_attachments].flags = 0;
75 pstate->attachments[num_attachments].format = attachments[num_attachments].format = rt->format;
76 pstate->attachments[num_attachments].samples = attachments[num_attachments].samples = rt->samples;
77 attachments[num_attachments].loadOp = rt->clear_color ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
78 attachments[num_attachments].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
79 attachments[num_attachments].stencilLoadOp = rt->clear_stencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
80 attachments[num_attachments].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
81 /* if layout changes are ever handled here, need VkAttachmentSampleLocationsEXT */
82 attachments[num_attachments].initialLayout = layout;
83 attachments[num_attachments].finalLayout = layout;
84
85 dep_pipeline |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
86 if (layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
87 dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
88 if (attachments[num_attachments].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ||
89 attachments[num_attachments].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
90 dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
91
92 zs_ref.attachment = num_attachments++;
93 zs_ref.layout = layout;
94 pstate->num_attachments++;
95 }
96
97 VkSubpassDependency deps[] = {
98 [0] = {VK_SUBPASS_EXTERNAL, 0, dep_pipeline, dep_pipeline, 0, dep_access, VK_DEPENDENCY_BY_REGION_BIT},
99 [1] = {0, VK_SUBPASS_EXTERNAL, dep_pipeline, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, dep_access, 0, VK_DEPENDENCY_BY_REGION_BIT}
100 };
101
102 VkSubpassDescription subpass = {0};
103 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
104 subpass.colorAttachmentCount = state->num_cbufs;
105 subpass.pColorAttachments = color_refs;
106 subpass.pDepthStencilAttachment = state->have_zsbuf ? &zs_ref : NULL;
107 subpass.inputAttachmentCount = input_count;
108 subpass.pInputAttachments = input_attachments;
109
110 VkRenderPassCreateInfo rpci = {0};
111 rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
112 rpci.attachmentCount = num_attachments;
113 rpci.pAttachments = attachments;
114 rpci.subpassCount = 1;
115 rpci.pSubpasses = &subpass;
116 rpci.dependencyCount = 2;
117 rpci.pDependencies = deps;
118
119 VkRenderPass render_pass;
120 if (VKSCR(CreateRenderPass)(screen->dev, &rpci, NULL, &render_pass) != VK_SUCCESS) {
121 mesa_loge("ZINK: vkCreateRenderPass failed");
122 return VK_NULL_HANDLE;
123 }
124
125 return render_pass;
126 }
127
128 static VkRenderPass
create_render_pass2(struct zink_screen * screen,struct zink_render_pass_state * state,struct zink_render_pass_pipeline_state * pstate)129 create_render_pass2(struct zink_screen *screen, struct zink_render_pass_state *state, struct zink_render_pass_pipeline_state *pstate)
130 {
131
132 VkAttachmentReference2 color_refs[PIPE_MAX_COLOR_BUFS], color_resolves[PIPE_MAX_COLOR_BUFS], zs_ref, zs_resolve;
133 VkAttachmentReference2 input_attachments[PIPE_MAX_COLOR_BUFS];
134 VkAttachmentDescription2 attachments[2 * (PIPE_MAX_COLOR_BUFS + 1)];
135 VkPipelineStageFlags dep_pipeline = 0;
136 VkAccessFlags dep_access = 0;
137 unsigned input_count = 0;
138 const unsigned cresolve_offset = state->num_cbufs + state->have_zsbuf;
139 const unsigned zsresolve_offset = cresolve_offset + state->num_cresolves;
140
141 pstate->num_attachments = state->num_cbufs;
142 pstate->num_cresolves = state->num_cresolves;
143 pstate->num_zsresolves = state->num_zsresolves;
144 for (int i = 0; i < state->num_cbufs; i++) {
145 struct zink_rt_attrib *rt = state->rts + i;
146 attachments[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
147 attachments[i].pNext = NULL;
148 attachments[i].flags = 0;
149 pstate->attachments[i].format = attachments[i].format = rt->format;
150 pstate->attachments[i].samples = attachments[i].samples = rt->samples;
151 attachments[i].loadOp = rt->clear_color ? VK_ATTACHMENT_LOAD_OP_CLEAR :
152 /* TODO: need replicate EXT */
153 //rt->resolve || (state->swapchain_init && rt->swapchain) ?
154 state->swapchain_init && rt->swapchain ?
155 VK_ATTACHMENT_LOAD_OP_DONT_CARE :
156 VK_ATTACHMENT_LOAD_OP_LOAD;
157
158 /* TODO: need replicate EXT */
159 //attachments[i].storeOp = rt->resolve ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
160 attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
161 attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
162 attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
163 /* if layout changes are ever handled here, need VkAttachmentSampleLocationsEXT */
164 VkImageLayout layout = rt->fbfetch ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
165 attachments[i].initialLayout = layout;
166 attachments[i].finalLayout = layout;
167 color_refs[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
168 color_refs[i].pNext = NULL;
169 color_refs[i].attachment = i;
170 color_refs[i].layout = layout;
171 color_refs[i].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
172 dep_pipeline |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
173 if (rt->fbfetch)
174 memcpy(&input_attachments[input_count++], &color_refs[i], sizeof(VkAttachmentReference2));
175 dep_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
176 if (attachments[i].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
177 dep_access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
178
179 if (rt->resolve) {
180 memcpy(&attachments[cresolve_offset + i], &attachments[i], sizeof(VkAttachmentDescription2));
181 attachments[cresolve_offset + i].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
182 attachments[cresolve_offset + i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
183 attachments[cresolve_offset + i].samples = 1;
184 memcpy(&color_resolves[i], &color_refs[i], sizeof(VkAttachmentReference2));
185 color_resolves[i].attachment = cresolve_offset + i;
186 if (attachments[cresolve_offset + i].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
187 dep_access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
188 }
189 }
190
191 int num_attachments = state->num_cbufs;
192 if (state->have_zsbuf) {
193 struct zink_rt_attrib *rt = state->rts + state->num_cbufs;
194 bool has_clear = rt->clear_color || rt->clear_stencil;
195 VkImageLayout layout = rt->needs_write || has_clear ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
196 attachments[num_attachments].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2;
197 attachments[num_attachments].pNext = NULL;
198 attachments[num_attachments].flags = 0;
199 pstate->attachments[num_attachments].format = attachments[num_attachments].format = rt->format;
200 pstate->attachments[num_attachments].samples = attachments[num_attachments].samples = rt->samples;
201 attachments[num_attachments].loadOp = rt->clear_color ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
202 attachments[num_attachments].stencilLoadOp = rt->clear_stencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
203 /* TODO: need replicate EXT */
204 //attachments[num_attachments].storeOp = rt->resolve ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
205 //attachments[num_attachments].stencilStoreOp = rt->resolve ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE;
206 attachments[num_attachments].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
207 attachments[num_attachments].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
208 /* if layout changes are ever handled here, need VkAttachmentSampleLocationsEXT */
209 attachments[num_attachments].initialLayout = layout;
210 attachments[num_attachments].finalLayout = layout;
211
212 dep_pipeline |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
213 if (layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
214 dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
215 if (attachments[num_attachments].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ||
216 attachments[num_attachments].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
217 dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
218
219 zs_ref.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2;
220 zs_ref.pNext = NULL;
221 zs_ref.attachment = num_attachments++;
222 zs_ref.layout = layout;
223 if (rt->resolve) {
224 memcpy(&attachments[zsresolve_offset], &attachments[num_attachments], sizeof(VkAttachmentDescription2));
225 attachments[zsresolve_offset].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
226 attachments[zsresolve_offset].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
227 attachments[zsresolve_offset].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
228 attachments[zsresolve_offset].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
229 attachments[zsresolve_offset].samples = 1;
230 memcpy(&zs_resolve, &zs_ref, sizeof(VkAttachmentReference2));
231 zs_ref.attachment = zsresolve_offset;
232 if (attachments[zsresolve_offset].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD ||
233 attachments[zsresolve_offset].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD)
234 dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
235 }
236 pstate->num_attachments++;
237 }
238
239 VkSubpassDependency2 deps[] = {
240 [0] = {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, NULL, VK_SUBPASS_EXTERNAL, 0, dep_pipeline, dep_pipeline, 0, dep_access, VK_DEPENDENCY_BY_REGION_BIT, 0},
241 [1] = {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, NULL, 0, VK_SUBPASS_EXTERNAL, dep_pipeline, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, dep_access, 0, VK_DEPENDENCY_BY_REGION_BIT, 0}
242 };
243
244 VkSubpassDescription2 subpass = {0};
245 VkSubpassDescriptionDepthStencilResolve zsresolve;
246 subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2;
247 subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
248 subpass.colorAttachmentCount = state->num_cbufs;
249 subpass.pColorAttachments = color_refs;
250 subpass.pDepthStencilAttachment = state->have_zsbuf ? &zs_ref : NULL;
251 subpass.inputAttachmentCount = input_count;
252 subpass.pInputAttachments = input_attachments;
253 if (state->num_cresolves)
254 subpass.pResolveAttachments = color_resolves;
255 if (state->num_zsresolves) {
256 subpass.pNext = &zsresolve;
257 zsresolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE;
258 zsresolve.pNext = NULL;
259 zsresolve.depthResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
260 zsresolve.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
261 zsresolve.pDepthStencilResolveAttachment = &zs_resolve;
262 } else
263 subpass.pNext = NULL;
264
265 VkRenderPassCreateInfo2 rpci = {0};
266 rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2;
267 rpci.attachmentCount = num_attachments + state->num_cresolves + state->num_zsresolves;
268 rpci.pAttachments = attachments;
269 rpci.subpassCount = 1;
270 rpci.pSubpasses = &subpass;
271 rpci.dependencyCount = 2;
272 rpci.pDependencies = deps;
273
274 VkRenderPass render_pass;
275 if (VKSCR(CreateRenderPass2)(screen->dev, &rpci, NULL, &render_pass) != VK_SUCCESS) {
276 mesa_loge("ZINK: vkCreateRenderPass2 failed");
277 return VK_NULL_HANDLE;
278 }
279
280 return render_pass;
281 }
282
283 struct zink_render_pass *
zink_create_render_pass(struct zink_screen * screen,struct zink_render_pass_state * state,struct zink_render_pass_pipeline_state * pstate)284 zink_create_render_pass(struct zink_screen *screen,
285 struct zink_render_pass_state *state,
286 struct zink_render_pass_pipeline_state *pstate)
287 {
288 struct zink_render_pass *rp = CALLOC_STRUCT(zink_render_pass);
289 if (!rp)
290 goto fail;
291
292 rp->render_pass = screen->vk_version >= VK_MAKE_VERSION(1,2,0) ?
293 create_render_pass2(screen, state, pstate) : create_render_pass(screen, state, pstate);
294 if (!rp->render_pass)
295 goto fail;
296 memcpy(&rp->state, state, sizeof(struct zink_render_pass_state));
297 return rp;
298
299 fail:
300 if (rp)
301 zink_destroy_render_pass(screen, rp);
302 return NULL;
303 }
304
305 void
zink_destroy_render_pass(struct zink_screen * screen,struct zink_render_pass * rp)306 zink_destroy_render_pass(struct zink_screen *screen,
307 struct zink_render_pass *rp)
308 {
309 VKSCR(DestroyRenderPass)(screen->dev, rp->render_pass, NULL);
310 FREE(rp);
311 }
312
313 VkImageLayout
zink_render_pass_attachment_get_barrier_info(const struct zink_render_pass * rp,unsigned idx,VkPipelineStageFlags * pipeline,VkAccessFlags * access)314 zink_render_pass_attachment_get_barrier_info(const struct zink_render_pass *rp, unsigned idx,
315 VkPipelineStageFlags *pipeline, VkAccessFlags *access)
316 {
317 *access = 0;
318 assert(idx < rp->state.num_rts);
319 const struct zink_rt_attrib *rt = &rp->state.rts[idx];
320 if (idx < rp->state.num_cbufs) {
321 *pipeline = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
322 *access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
323 if (!rt->clear_color && (!rp->state.swapchain_init || !rt->swapchain))
324 *access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
325 return rt->fbfetch ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
326 }
327
328 assert(rp->state.have_zsbuf);
329 *pipeline = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
330 if (!rp->state.rts[idx].clear_color && !rp->state.rts[idx].clear_stencil)
331 *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
332 if (!rp->state.rts[idx].clear_color && !rp->state.rts[idx].clear_stencil && !rp->state.rts[idx].needs_write)
333 return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
334 *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
335 return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
336 }
337