blob: cd622f276f9383f98efe9e264d22e8fd30e536fb [file] [log] [blame]
Jeremy Gebben88f58142021-06-01 10:07:52 -06001/* Copyright (c) 2015-2021 The Khronos Group Inc.
2 * Copyright (c) 2015-2021 Valve Corporation
3 * Copyright (c) 2015-2021 LunarG, Inc.
4 * Copyright (C) 2015-2021 Google Inc.
5 * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
20 * Author: Tobin Ehlis <tobine@google.com>
21 * Author: Chris Forbes <chrisf@ijw.co.nz>
22 * Author: Mark Lobodzinski <mark@lunarg.com>
23 * Author: Dave Houlton <daveh@lunarg.com>
24 * Author: John Zulauf <jzulauf@lunarg.com>
25 * Author: Tobias Hector <tobias.hector@amd.com>
26 * Author: Jeremy Gebben <jeremyg@lunarg.com>
27 */
28#include "render_pass_state.h"
29#include "convert_to_renderpass2.h"
30#include "image_state.h"
31
32static const VkImageLayout kInvalidLayout = VK_IMAGE_LAYOUT_MAX_ENUM;
33
John Zulaufbdcc9c62021-10-01 14:57:26 -060034static VkSubpassDependency2 ImplicitDependencyFromExternal(uint32_t subpass) {
35 VkSubpassDependency2 from_external = {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
36 nullptr,
37 VK_SUBPASS_EXTERNAL,
38 subpass,
39 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
40 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
41 0,
42 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
43 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
44 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
45 0,
46 0};
47 return from_external;
48}
49
50static VkSubpassDependency2 ImplicitDependencyToExternal(uint32_t subpass) {
51 VkSubpassDependency2 to_external = {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2,
52 nullptr,
53 subpass,
54 VK_SUBPASS_EXTERNAL,
55 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
56 VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
57 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
58 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
59 VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
60 0,
61 0,
62 0};
63 return to_external;
64}
Jeremy Gebbene83bd442021-09-02 11:18:03 -060065// NOTE: The functions below are only called from the RENDER_PASS_STATE constructor, and use const_cast<> to set up
66// members that never change after construction is finished.
Jeremy Gebben88f58142021-06-01 10:07:52 -060067static void RecordRenderPassDAG(const VkRenderPassCreateInfo2 *pCreateInfo, RENDER_PASS_STATE *render_pass) {
Jeremy Gebbene83bd442021-09-02 11:18:03 -060068 auto &subpass_to_node = const_cast<RENDER_PASS_STATE::DAGNodeVec &>(render_pass->subpass_to_node);
Jeremy Gebben88f58142021-06-01 10:07:52 -060069 subpass_to_node.resize(pCreateInfo->subpassCount);
Jeremy Gebbene83bd442021-09-02 11:18:03 -060070 auto &self_dependencies = const_cast<RENDER_PASS_STATE::SelfDepVec &>(render_pass->self_dependencies);
Jeremy Gebben88f58142021-06-01 10:07:52 -060071 self_dependencies.resize(pCreateInfo->subpassCount);
Jeremy Gebbene83bd442021-09-02 11:18:03 -060072 auto &subpass_dependencies = const_cast<RENDER_PASS_STATE::SubpassGraphVec &>(render_pass->subpass_dependencies);
Jeremy Gebben88f58142021-06-01 10:07:52 -060073 subpass_dependencies.resize(pCreateInfo->subpassCount);
74
75 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
76 subpass_to_node[i].pass = i;
77 self_dependencies[i].clear();
78 subpass_dependencies[i].pass = i;
79 }
80 for (uint32_t i = 0; i < pCreateInfo->dependencyCount; ++i) {
81 const auto &dependency = pCreateInfo->pDependencies[i];
82 const auto src_subpass = dependency.srcSubpass;
83 const auto dst_subpass = dependency.dstSubpass;
84 if ((dependency.srcSubpass != VK_SUBPASS_EXTERNAL) && (dependency.dstSubpass != VK_SUBPASS_EXTERNAL)) {
85 if (dependency.srcSubpass == dependency.dstSubpass) {
86 self_dependencies[dependency.srcSubpass].push_back(i);
87 } else {
88 subpass_to_node[dependency.dstSubpass].prev.push_back(dependency.srcSubpass);
89 subpass_to_node[dependency.srcSubpass].next.push_back(dependency.dstSubpass);
90 }
91 }
92 if (src_subpass == VK_SUBPASS_EXTERNAL) {
93 assert(dst_subpass != VK_SUBPASS_EXTERNAL); // this is invalid per VUID-VkSubpassDependency-srcSubpass-00865
94 subpass_dependencies[dst_subpass].barrier_from_external.emplace_back(&dependency);
95 } else if (dst_subpass == VK_SUBPASS_EXTERNAL) {
96 subpass_dependencies[src_subpass].barrier_to_external.emplace_back(&dependency);
97 } else if (dependency.srcSubpass != dependency.dstSubpass) {
98 // ignore self dependencies in prev and next
99 subpass_dependencies[src_subpass].next[&subpass_dependencies[dst_subpass]].emplace_back(&dependency);
100 subpass_dependencies[dst_subpass].prev[&subpass_dependencies[src_subpass]].emplace_back(&dependency);
101 }
102 }
103
John Zulaufbdcc9c62021-10-01 14:57:26 -0600104 // If no barriers to external are provided for a given subpass, add them.
105 for (auto &subpass_dep : subpass_dependencies) {
106 const uint32_t pass = subpass_dep.pass;
107 if (subpass_dep.barrier_from_external.size() == 0) {
108 // Add implicit from barrier if they're aren't any
109 subpass_dep.implicit_barrier_from_external =
110 layer_data::make_unique<VkSubpassDependency2>(ImplicitDependencyFromExternal(pass));
111 subpass_dep.barrier_from_external.emplace_back(subpass_dep.implicit_barrier_from_external.get());
112 }
113 if (subpass_dep.barrier_to_external.size() == 0) {
114 // Add implicit to barrier if they're aren't any
115 subpass_dep.implicit_barrier_to_external =
116 layer_data::make_unique<VkSubpassDependency2>(ImplicitDependencyToExternal(pass));
117 subpass_dep.barrier_to_external.emplace_back(subpass_dep.implicit_barrier_to_external.get());
118 }
119 }
120
Jeremy Gebben88f58142021-06-01 10:07:52 -0600121 //
122 // Determine "asynchrononous" subpassess
123 // syncronization is only interested in asyncronous stages *earlier* that the current one... so we'll only look towards those.
124 // NOTE: This is O(N^3), which we could shrink to O(N^2logN) using sets instead of arrays, but given that N is likely to be
125 // small and the K for |= from the prev is must less than for set, we'll accept the brute force.
126 std::vector<std::vector<bool>> pass_depends(pCreateInfo->subpassCount);
127 for (uint32_t i = 1; i < pCreateInfo->subpassCount; ++i) {
128 auto &depends = pass_depends[i];
129 depends.resize(i);
130 auto &subpass_dep = subpass_dependencies[i];
131 for (const auto &prev : subpass_dep.prev) {
132 const auto prev_pass = prev.first->pass;
133 const auto &prev_depends = pass_depends[prev_pass];
134 for (uint32_t j = 0; j < prev_pass; j++) {
Nico Weber51279392021-10-08 11:19:55 -0400135 depends[j] = depends[j] || prev_depends[j];
Jeremy Gebben88f58142021-06-01 10:07:52 -0600136 }
137 depends[prev_pass] = true;
138 }
139 for (uint32_t pass = 0; pass < subpass_dep.pass; pass++) {
140 if (!depends[pass]) {
141 subpass_dep.async.push_back(pass);
142 }
143 }
144 }
145}
146
Jeremy Gebben88f58142021-06-01 10:07:52 -0600147struct AttachmentTracker { // This is really only of local interest, but a bit big for a lambda
148 RENDER_PASS_STATE *const rp;
Jeremy Gebbene83bd442021-09-02 11:18:03 -0600149 RENDER_PASS_STATE::SubpassVec &first;
150 RENDER_PASS_STATE::FirstIsTransitionVec &first_is_transition;
151 RENDER_PASS_STATE::SubpassVec &last;
152 RENDER_PASS_STATE::TransitionVec &subpass_transitions;
153 RENDER_PASS_STATE::FirstReadMap &first_read;
Jeremy Gebben88f58142021-06-01 10:07:52 -0600154 const uint32_t attachment_count;
155 std::vector<VkImageLayout> attachment_layout;
156 std::vector<std::vector<VkImageLayout>> subpass_attachment_layout;
157 explicit AttachmentTracker(RENDER_PASS_STATE *render_pass)
158 : rp(render_pass),
Jeremy Gebbene83bd442021-09-02 11:18:03 -0600159 first(const_cast<RENDER_PASS_STATE::SubpassVec &>(rp->attachment_first_subpass)),
160 first_is_transition(const_cast<RENDER_PASS_STATE::FirstIsTransitionVec &>(rp->attachment_first_is_transition)),
161 last(const_cast<RENDER_PASS_STATE::SubpassVec &>(rp->attachment_last_subpass)),
162 subpass_transitions(const_cast<RENDER_PASS_STATE::TransitionVec &>(rp->subpass_transitions)),
163 first_read(const_cast<RENDER_PASS_STATE::FirstReadMap &>(rp->attachment_first_read)),
Jeremy Gebben88f58142021-06-01 10:07:52 -0600164 attachment_count(rp->createInfo.attachmentCount),
165 attachment_layout(),
166 subpass_attachment_layout() {
167 first.resize(attachment_count, VK_SUBPASS_EXTERNAL);
168 first_is_transition.resize(attachment_count, false);
169 last.resize(attachment_count, VK_SUBPASS_EXTERNAL);
170 subpass_transitions.resize(rp->createInfo.subpassCount + 1); // Add an extra for EndRenderPass
171 attachment_layout.reserve(attachment_count);
172 subpass_attachment_layout.resize(rp->createInfo.subpassCount);
173 for (auto &subpass_layouts : subpass_attachment_layout) {
174 subpass_layouts.resize(attachment_count, kInvalidLayout);
175 }
176
177 for (uint32_t j = 0; j < attachment_count; j++) {
178 attachment_layout.push_back(rp->createInfo.pAttachments[j].initialLayout);
179 }
180 }
181
182 void Update(uint32_t subpass, const VkAttachmentReference2 *attach_ref, uint32_t count, bool is_read) {
183 if (nullptr == attach_ref) return;
184 for (uint32_t j = 0; j < count; ++j) {
185 const auto attachment = attach_ref[j].attachment;
186 if (attachment != VK_ATTACHMENT_UNUSED) {
187 const auto layout = attach_ref[j].layout;
188 // Take advantage of the fact that insert won't overwrite, so we'll only write the first time.
189 first_read.emplace(attachment, is_read);
190 if (first[attachment] == VK_SUBPASS_EXTERNAL) {
191 first[attachment] = subpass;
192 const auto initial_layout = rp->createInfo.pAttachments[attachment].initialLayout;
193 if (initial_layout != layout) {
194 subpass_transitions[subpass].emplace_back(VK_SUBPASS_EXTERNAL, attachment, initial_layout, layout);
195 first_is_transition[attachment] = true;
196 }
197 }
198 last[attachment] = subpass;
199
200 for (const auto &prev : rp->subpass_dependencies[subpass].prev) {
201 const auto prev_pass = prev.first->pass;
202 const auto prev_layout = subpass_attachment_layout[prev_pass][attachment];
203 if ((prev_layout != kInvalidLayout) && (prev_layout != layout)) {
204 subpass_transitions[subpass].emplace_back(prev_pass, attachment, prev_layout, layout);
205 }
206 }
207 attachment_layout[attachment] = layout;
208 }
209 }
210 }
211 void FinalTransitions() {
212 auto &final_transitions = subpass_transitions[rp->createInfo.subpassCount];
213
214 for (uint32_t attachment = 0; attachment < attachment_count; ++attachment) {
215 const auto final_layout = rp->createInfo.pAttachments[attachment].finalLayout;
216 // Add final transitions for attachments that were used and change layout.
217 if ((last[attachment] != VK_SUBPASS_EXTERNAL) && final_layout != attachment_layout[attachment]) {
218 final_transitions.emplace_back(last[attachment], attachment, attachment_layout[attachment], final_layout);
219 }
220 }
221 }
222};
223
224static void InitRenderPassState(RENDER_PASS_STATE *render_pass) {
225 auto create_info = render_pass->createInfo.ptr();
226
227 RecordRenderPassDAG(create_info, render_pass);
228
229 AttachmentTracker attachment_tracker(render_pass);
230
231 for (uint32_t subpass_index = 0; subpass_index < create_info->subpassCount; ++subpass_index) {
232 const VkSubpassDescription2 &subpass = create_info->pSubpasses[subpass_index];
233 attachment_tracker.Update(subpass_index, subpass.pColorAttachments, subpass.colorAttachmentCount, false);
234 attachment_tracker.Update(subpass_index, subpass.pResolveAttachments, subpass.colorAttachmentCount, false);
235 attachment_tracker.Update(subpass_index, subpass.pDepthStencilAttachment, 1, false);
236 attachment_tracker.Update(subpass_index, subpass.pInputAttachments, subpass.inputAttachmentCount, true);
237 }
238 attachment_tracker.FinalTransitions();
Jeremy Gebben88f58142021-06-01 10:07:52 -0600239}
240
241RENDER_PASS_STATE::RENDER_PASS_STATE(VkRenderPass rp, VkRenderPassCreateInfo2 const *pCreateInfo)
amhagana448ea52021-11-02 14:09:14 -0400242 : BASE_NODE(rp, kVulkanObjectTypeRenderPass), use_dynamic_rendering(false), use_dynamic_rendering_inherited(false), createInfo(pCreateInfo) {
Jeremy Gebben88f58142021-06-01 10:07:52 -0600243 InitRenderPassState(this);
244}
245
Jeremy Gebbene83bd442021-09-02 11:18:03 -0600246static safe_VkRenderPassCreateInfo2 ConvertCreateInfo(const VkRenderPassCreateInfo &create_info) {
247 safe_VkRenderPassCreateInfo2 create_info_2;
248 ConvertVkRenderPassCreateInfoToV2KHR(create_info, &create_info_2);
249 return create_info_2;
250}
251
Jeremy Gebben88f58142021-06-01 10:07:52 -0600252RENDER_PASS_STATE::RENDER_PASS_STATE(VkRenderPass rp, VkRenderPassCreateInfo const *pCreateInfo)
amhagana448ea52021-11-02 14:09:14 -0400253 : BASE_NODE(rp, kVulkanObjectTypeRenderPass), use_dynamic_rendering(false), use_dynamic_rendering_inherited(false), createInfo(ConvertCreateInfo(*pCreateInfo)) {
Jeremy Gebben88f58142021-06-01 10:07:52 -0600254 InitRenderPassState(this);
255}
256
amhagana448ea52021-11-02 14:09:14 -0400257const VkPipelineRenderingCreateInfoKHR VkPipelineRenderingCreateInfoKHR_default = {
258 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
259 nullptr,
260 0,
261 0,
262 nullptr,
263 VK_FORMAT_UNDEFINED,
264 VK_FORMAT_UNDEFINED
265};
266
267RENDER_PASS_STATE::RENDER_PASS_STATE(VkPipelineRenderingCreateInfoKHR const *pPipelineRenderingCreateInfo)
268 : BASE_NODE(static_cast<VkRenderPass>(VK_NULL_HANDLE), kVulkanObjectTypeRenderPass),
269 use_dynamic_rendering(true),
270 use_dynamic_rendering_inherited(false),
Aaron Hagan92a44f82021-11-19 09:34:56 -0500271 dynamic_rendering_pipeline_create_info(pPipelineRenderingCreateInfo ? pPipelineRenderingCreateInfo
272 : &VkPipelineRenderingCreateInfoKHR_default) {}
amhagana448ea52021-11-02 14:09:14 -0400273
Jeremy Gebben11af9792021-08-20 10:20:09 -0600274bool RENDER_PASS_STATE::UsesColorAttachment(uint32_t subpass_num) const {
275 bool result = false;
276
277 if (subpass_num < createInfo.subpassCount) {
278 const auto &subpass = createInfo.pSubpasses[subpass_num];
279
280 for (uint32_t i = 0; i < subpass.colorAttachmentCount; ++i) {
281 if (subpass.pColorAttachments[i].attachment != VK_ATTACHMENT_UNUSED) {
282 result = true;
283 break;
284 }
285 }
286 }
287 return result;
288}
289
290bool RENDER_PASS_STATE::UsesDepthStencilAttachment(uint32_t subpass_num) const {
291 bool result = false;
292 if (subpass_num < createInfo.subpassCount) {
293 const auto &subpass = createInfo.pSubpasses[subpass_num];
294 if (subpass.pDepthStencilAttachment && subpass.pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
295 result = true;
296 }
297 }
298 return result;
299}
300
amhagana448ea52021-11-02 14:09:14 -0400301RENDER_PASS_STATE::RENDER_PASS_STATE(VkRenderingInfoKHR const *pRenderingInfo)
302 : BASE_NODE(static_cast<VkRenderPass>(VK_NULL_HANDLE), kVulkanObjectTypeRenderPass),
303 use_dynamic_rendering(true),
304 use_dynamic_rendering_inherited(false),
Aaron Hagan92a44f82021-11-19 09:34:56 -0500305 dynamic_rendering_begin_rendering_info(pRenderingInfo) {}
amhagana448ea52021-11-02 14:09:14 -0400306
307RENDER_PASS_STATE::RENDER_PASS_STATE(VkCommandBufferInheritanceRenderingInfoKHR const* pInheritanceRenderingInfo)
308 : BASE_NODE(static_cast<VkRenderPass>(VK_NULL_HANDLE), kVulkanObjectTypeRenderPass),
309 use_dynamic_rendering(true),
310 use_dynamic_rendering_inherited(true),
311 inheritance_rendering_info(pInheritanceRenderingInfo) {}
312
Jeremy Gebben88f58142021-06-01 10:07:52 -0600313FRAMEBUFFER_STATE::FRAMEBUFFER_STATE(VkFramebuffer fb, const VkFramebufferCreateInfo *pCreateInfo,
314 std::shared_ptr<RENDER_PASS_STATE> &&rpstate,
315 std::vector<std::shared_ptr<IMAGE_VIEW_STATE>> &&attachments)
Jeremy Gebbene83bd442021-09-02 11:18:03 -0600316 : BASE_NODE(fb, kVulkanObjectTypeFramebuffer),
317 createInfo(pCreateInfo),
318 rp_state(rpstate),
319 attachments_view_state(std::move(attachments)) {
320 for (auto &a : attachments_view_state) {
Jeremy Gebben88f58142021-06-01 10:07:52 -0600321 a->AddParent(this);
322 }
Jeremy Gebben88f58142021-06-01 10:07:52 -0600323}
324
325void FRAMEBUFFER_STATE::Destroy() {
amhagana448ea52021-11-02 14:09:14 -0400326 for (auto &view : attachments_view_state) {
Jeremy Gebben88f58142021-06-01 10:07:52 -0600327 view->RemoveParent(this);
328 }
329 attachments_view_state.clear();
330 BASE_NODE::Destroy();
331}