1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "pipeline_create_functions_vk.h"
17
18 #include <algorithm>
19 #include <vulkan/vulkan_core.h>
20
21 #include <base/containers/array_view.h>
22 #include <base/containers/vector.h>
23 #include <base/math/mathf.h>
24 #include <render/device/pipeline_state_desc.h>
25 #include <render/namespace.h>
26
27 #include "nodecontext/render_command_list.h"
28 #include "util/log.h"
29 #include "vulkan/device_vk.h"
30 #include "vulkan/validate_vk.h"
31
32 using namespace BASE_NS;
33
34 RENDER_BEGIN_NAMESPACE()
35 namespace {
CreateAttachmentDescriptions(const array_view<const RenderPassDesc::AttachmentDesc> & attachments,const array_view<const LowLevelRenderPassCompatibilityDescVk::Attachment> & compatibilityAttachmentDescs,const array_view<const ImageLayout> & initialImageLayouts,const array_view<const ImageLayout> & finalImageLayouts,array_view<VkAttachmentDescription> newAttachments)36 void CreateAttachmentDescriptions(const array_view<const RenderPassDesc::AttachmentDesc>& attachments,
37 const array_view<const LowLevelRenderPassCompatibilityDescVk::Attachment>& compatibilityAttachmentDescs,
38 const array_view<const ImageLayout>& initialImageLayouts, const array_view<const ImageLayout>& finalImageLayouts,
39 array_view<VkAttachmentDescription> newAttachments)
40 {
41 PLUGIN_ASSERT(attachments.size() == compatibilityAttachmentDescs.size());
42 PLUGIN_ASSERT(attachments.size() <= newAttachments.size());
43 PLUGIN_ASSERT(attachments.size() <= initialImageLayouts.size());
44 PLUGIN_ASSERT(attachments.size() <= finalImageLayouts.size());
45 auto itNewAttachments = newAttachments.begin();
46 auto itInitialImageLayouts = initialImageLayouts.begin();
47 auto itFinalImageLayouts = finalImageLayouts.begin();
48 for (size_t idx = 0; idx < attachments.size(); ++idx) {
49 const auto& attachmentRef = attachments[idx];
50 const auto& compatibilityAttachmentRef = compatibilityAttachmentDescs[idx];
51 const ImageLayout initialLayout = *itInitialImageLayouts++;
52 const ImageLayout finalLayout = *itFinalImageLayouts++;
53 PLUGIN_ASSERT(compatibilityAttachmentRef.format != VkFormat::VK_FORMAT_UNDEFINED);
54
55 constexpr VkAttachmentDescriptionFlags attachmentDescriptionFlags { 0 };
56 *itNewAttachments++ = {
57 attachmentDescriptionFlags, // flags
58 compatibilityAttachmentRef.format, // format
59 compatibilityAttachmentRef.sampleCountFlags, // samples
60 (VkAttachmentLoadOp)attachmentRef.loadOp, // loadOp
61 (VkAttachmentStoreOp)attachmentRef.storeOp, // storeOp
62 (VkAttachmentLoadOp)attachmentRef.stencilLoadOp, // stencilLoadOp
63 (VkAttachmentStoreOp)attachmentRef.stencilStoreOp, // stencilStoreOp
64 (VkImageLayout)initialLayout, // initialLayout
65 (VkImageLayout)finalLayout, // finalLayout
66 };
67 }
68 }
69
CreateAttachmentDescriptions2(const array_view<const RenderPassDesc::AttachmentDesc> & attachments,const array_view<const LowLevelRenderPassCompatibilityDescVk::Attachment> & compatibilityAttachmentDescs,const array_view<const ImageLayout> & initialImageLayouts,const array_view<const ImageLayout> & finalImageLayouts,array_view<VkAttachmentDescription2KHR> newAttachments)70 void CreateAttachmentDescriptions2(const array_view<const RenderPassDesc::AttachmentDesc>& attachments,
71 const array_view<const LowLevelRenderPassCompatibilityDescVk::Attachment>& compatibilityAttachmentDescs,
72 const array_view<const ImageLayout>& initialImageLayouts, const array_view<const ImageLayout>& finalImageLayouts,
73 array_view<VkAttachmentDescription2KHR> newAttachments)
74 {
75 PLUGIN_ASSERT(attachments.size() == compatibilityAttachmentDescs.size());
76 PLUGIN_ASSERT(attachments.size() <= newAttachments.size());
77 PLUGIN_ASSERT(attachments.size() <= initialImageLayouts.size());
78 PLUGIN_ASSERT(attachments.size() <= finalImageLayouts.size());
79 auto itNewAttachments = newAttachments.begin();
80 auto itInitialImageLayouts = initialImageLayouts.begin();
81 auto itFinalImageLayouts = finalImageLayouts.begin();
82 for (size_t idx = 0; idx < attachments.size(); ++idx) {
83 const auto& attachmentRef = attachments[idx];
84 const auto& compatibilityAttachmentRef = compatibilityAttachmentDescs[idx];
85 const ImageLayout initialLayout = *itInitialImageLayouts++;
86 const ImageLayout finalLayout = *itFinalImageLayouts++;
87 PLUGIN_ASSERT(compatibilityAttachmentRef.format != VkFormat::VK_FORMAT_UNDEFINED);
88
89 constexpr VkAttachmentDescriptionFlags attachmentDescriptionFlags { 0 };
90 *itNewAttachments++ = {
91 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR, // sType
92 nullptr, // pNext
93 attachmentDescriptionFlags, // flags
94 compatibilityAttachmentRef.format, // format
95 compatibilityAttachmentRef.sampleCountFlags, // samples
96 (VkAttachmentLoadOp)attachmentRef.loadOp, // loadOp
97 (VkAttachmentStoreOp)attachmentRef.storeOp, // storeOp
98 (VkAttachmentLoadOp)attachmentRef.stencilLoadOp, // stencilLoadOp
99 (VkAttachmentStoreOp)attachmentRef.stencilStoreOp, // stencilStoreOp
100 (VkImageLayout)initialLayout, // initialLayout
101 (VkImageLayout)finalLayout, // finalLayout
102 };
103 }
104 }
105
CreateAttachmentDescriptionsCompatibility(const array_view<const RenderPassDesc::AttachmentDesc> & attachments,const array_view<const LowLevelRenderPassCompatibilityDescVk::Attachment> & compatibilityAttachmentDescs,array_view<VkAttachmentDescription> newAttachments)106 void CreateAttachmentDescriptionsCompatibility(const array_view<const RenderPassDesc::AttachmentDesc>& attachments,
107 const array_view<const LowLevelRenderPassCompatibilityDescVk::Attachment>& compatibilityAttachmentDescs,
108 array_view<VkAttachmentDescription> newAttachments)
109 {
110 PLUGIN_ASSERT(attachments.size() == compatibilityAttachmentDescs.size());
111 PLUGIN_ASSERT(attachments.size() <= newAttachments.size());
112 auto itNewAttachments = newAttachments.begin();
113 for (size_t idx = 0; idx < attachments.size(); ++idx) {
114 const auto& compatibilityAttachmentRef = compatibilityAttachmentDescs[idx];
115 PLUGIN_ASSERT(compatibilityAttachmentRef.format != VkFormat::VK_FORMAT_UNDEFINED);
116
117 constexpr VkAttachmentDescriptionFlags attachmentDescriptionFlags { 0 };
118 *itNewAttachments++ = {
119 attachmentDescriptionFlags, // flags
120 compatibilityAttachmentRef.format, // format
121 compatibilityAttachmentRef.sampleCountFlags, // samples
122 VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
123 VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp
124 VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
125 VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
126 VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
127 VkImageLayout::VK_IMAGE_LAYOUT_GENERAL, // finalLayout
128 };
129 }
130 }
131
CreateAttachmentDescriptionsCompatibility2(const array_view<const RenderPassDesc::AttachmentDesc> & attachments,const array_view<const LowLevelRenderPassCompatibilityDescVk::Attachment> & compatibilityAttachmentDescs,array_view<VkAttachmentDescription2KHR> newAttachments)132 void CreateAttachmentDescriptionsCompatibility2(const array_view<const RenderPassDesc::AttachmentDesc>& attachments,
133 const array_view<const LowLevelRenderPassCompatibilityDescVk::Attachment>& compatibilityAttachmentDescs,
134 array_view<VkAttachmentDescription2KHR> newAttachments)
135 {
136 PLUGIN_ASSERT(attachments.size() == compatibilityAttachmentDescs.size());
137 PLUGIN_ASSERT(attachments.size() <= newAttachments.size());
138 auto itNewAttachments = newAttachments.begin();
139 for (size_t idx = 0; idx < attachments.size(); ++idx) {
140 const auto& compatibilityAttachmentRef = compatibilityAttachmentDescs[idx];
141 PLUGIN_ASSERT(compatibilityAttachmentRef.format != VkFormat::VK_FORMAT_UNDEFINED);
142
143 constexpr VkAttachmentDescriptionFlags attachmentDescriptionFlags { 0 };
144 *itNewAttachments++ = {
145 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2_KHR, // sType
146 nullptr, // pNext
147 attachmentDescriptionFlags, // flags
148 compatibilityAttachmentRef.format, // format
149 compatibilityAttachmentRef.sampleCountFlags, // samples
150 VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // loadOp
151 VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp
152 VkAttachmentLoadOp::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
153 VkAttachmentStoreOp::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilStoreOp
154 VkImageLayout::VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
155 VkImageLayout::VK_IMAGE_LAYOUT_GENERAL, // finalLayout
156 };
157 }
158 }
159
CreateAttachmentReferences(const uint32_t * attachmentIndices,const ImageLayout * layouts,const uint32_t attachmentCount,const uint32_t attachmentStartIndex,const bool createCompatibility,VkAttachmentReference * newAttachments)160 void CreateAttachmentReferences(const uint32_t* attachmentIndices,
161 const ImageLayout* layouts, // can be null if compatibility
162 const uint32_t attachmentCount, const uint32_t attachmentStartIndex, const bool createCompatibility,
163 VkAttachmentReference* newAttachments)
164 {
165 PLUGIN_ASSERT(newAttachments);
166 VkImageLayout imageLayout = VkImageLayout::VK_IMAGE_LAYOUT_GENERAL;
167 for (uint32_t idx = 0; idx < attachmentCount; ++idx) {
168 const uint32_t attachmentIndex = attachmentIndices[idx];
169 if (!createCompatibility) {
170 imageLayout = (VkImageLayout)layouts[attachmentIndex];
171 }
172 newAttachments[attachmentStartIndex + idx] = {
173 attachmentIndex, // attachment
174 imageLayout, // layout
175 };
176 }
177 }
178
CreateAttachmentReferences2(const uint32_t * attachmentIndices,const ImageLayout * layouts,const uint32_t attachmentCount,const uint32_t attachmentStartIndex,const bool createCompatibility,VkAttachmentReference2KHR * newAttachments)179 void CreateAttachmentReferences2(const uint32_t* attachmentIndices,
180 const ImageLayout* layouts, // can be null if compatibility
181 const uint32_t attachmentCount, const uint32_t attachmentStartIndex, const bool createCompatibility,
182 VkAttachmentReference2KHR* newAttachments)
183 {
184 PLUGIN_ASSERT(newAttachments);
185 VkImageLayout imageLayout = VkImageLayout::VK_IMAGE_LAYOUT_GENERAL;
186 VkImageAspectFlags imageAspectFlags = 0;
187 for (uint32_t idx = 0; idx < attachmentCount; ++idx) {
188 const uint32_t attachmentIndex = attachmentIndices[idx];
189 if (!createCompatibility) {
190 const VkImageLayout imgLayout = (VkImageLayout)layouts[attachmentIndex];
191 imageLayout = imgLayout;
192 imageAspectFlags = ((imgLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) ||
193 (imgLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL))
194 ? (VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT |
195 VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT)
196 : VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT;
197 }
198 newAttachments[attachmentStartIndex + idx] = {
199 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2_KHR, // sType
200 nullptr, // pNext
201 attachmentIndex, // attachment
202 imageLayout, // layout
203 imageAspectFlags, // aspectMask
204 };
205 }
206 }
207
CreateRenderPassCombined(const DeviceVk & deviceVk,const RenderPassDesc & renderPassDesc,const LowLevelRenderPassDataVk & lowLevelRenderPassData,const array_view<const RenderPassSubpassDesc> & subpassDescs,const RenderPassAttachmentResourceStates * subpassResourceStates,const RenderPassAttachmentResourceStates * inputResourceStates,const RenderPassImageLayouts * imageLayouts,const uint32_t maxAttachmentReferenceCountPerSubpass,const bool createRenderPassCompatibility,RenderPassCreatorVk::RenderPassStorage1 & rps1)208 VkRenderPass CreateRenderPassCombined(const DeviceVk& deviceVk, const RenderPassDesc& renderPassDesc,
209 const LowLevelRenderPassDataVk& lowLevelRenderPassData, const array_view<const RenderPassSubpassDesc>& subpassDescs,
210 const RenderPassAttachmentResourceStates* subpassResourceStates, // null when using compatibility
211 const RenderPassAttachmentResourceStates* inputResourceStates, // null when using compatibility
212 const RenderPassImageLayouts* imageLayouts, // null when using compatibility
213 const uint32_t maxAttachmentReferenceCountPerSubpass, const bool createRenderPassCompatibility,
214 RenderPassCreatorVk::RenderPassStorage1& rps1)
215 {
216 const VkDevice device = (deviceVk.GetPlatformDataVk()).device;
217 const uint32_t attachmentCount = renderPassDesc.attachmentCount;
218 PLUGIN_ASSERT(attachmentCount <= PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT);
219
220 VkAttachmentDescription attachmentDescriptions[PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT];
221 {
222 // add all attachments to attachmentDescriptions array
223 const auto attachments = array_view(renderPassDesc.attachments, renderPassDesc.attachmentCount);
224 const auto compatibilityAttachments =
225 array_view(lowLevelRenderPassData.renderPassCompatibilityDesc.attachments, renderPassDesc.attachmentCount);
226 const auto descriptions = array_view(attachmentDescriptions, countof(attachmentDescriptions));
227 if (createRenderPassCompatibility) {
228 CreateAttachmentDescriptionsCompatibility(attachments, compatibilityAttachments, descriptions);
229 } else {
230 PLUGIN_ASSERT(imageLayouts);
231 const auto initialLayouts =
232 array_view(imageLayouts->attachmentInitialLayouts, renderPassDesc.attachmentCount);
233 const auto finalLayouts = array_view(imageLayouts->attachmentFinalLayouts, renderPassDesc.attachmentCount);
234 CreateAttachmentDescriptions(
235 attachments, compatibilityAttachments, initialLayouts, finalLayouts, descriptions);
236 }
237 }
238
239 // resize vector for all subpass references
240 const uint32_t subpassCount = renderPassDesc.subpassCount;
241 auto& subpassDescriptions = rps1.subpassDescriptions;
242 auto& subpassDependencies = rps1.subpassDependencies;
243 auto& attachmentReferences = rps1.attachmentReferences;
244 subpassDescriptions.resize(subpassCount);
245 subpassDependencies.resize(subpassCount);
246 attachmentReferences.resize(subpassCount * maxAttachmentReferenceCountPerSubpass);
247
248 uint32_t srcSubpass = VK_SUBPASS_EXTERNAL;
249 const RenderPassAttachmentResourceStates* srcResourceStates = inputResourceStates;
250 for (uint32_t subpassIdx = 0; subpassIdx < subpassCount; ++subpassIdx) {
251 const RenderPassSubpassDesc& subpassDesc = subpassDescs[subpassIdx];
252
253 const uint32_t startReferenceIndex = subpassIdx * maxAttachmentReferenceCountPerSubpass;
254 uint32_t referenceIndex = startReferenceIndex;
255
256 VkAttachmentReference* inputAttachments = nullptr;
257 const ImageLayout* layouts = subpassResourceStates ? subpassResourceStates[subpassIdx].layouts : nullptr;
258 if (subpassDesc.inputAttachmentCount > 0) {
259 inputAttachments = &attachmentReferences[referenceIndex];
260 CreateAttachmentReferences(subpassDesc.inputAttachmentIndices, layouts, subpassDesc.inputAttachmentCount,
261 referenceIndex, createRenderPassCompatibility, attachmentReferences.data());
262 referenceIndex += subpassDesc.inputAttachmentCount;
263 }
264
265 VkAttachmentReference* colorAttachments = nullptr;
266 if (subpassDesc.colorAttachmentCount > 0) {
267 colorAttachments = &attachmentReferences[referenceIndex];
268 CreateAttachmentReferences(subpassDesc.colorAttachmentIndices, layouts, subpassDesc.colorAttachmentCount,
269 referenceIndex, createRenderPassCompatibility, attachmentReferences.data());
270 referenceIndex += subpassDesc.colorAttachmentCount;
271 }
272
273 VkAttachmentReference* resolveAttachments = nullptr;
274 if (subpassDesc.resolveAttachmentCount > 0) {
275 resolveAttachments = &attachmentReferences[referenceIndex];
276 CreateAttachmentReferences(subpassDesc.resolveAttachmentIndices, layouts,
277 subpassDesc.resolveAttachmentCount, referenceIndex, createRenderPassCompatibility,
278 attachmentReferences.data());
279 referenceIndex += subpassDesc.resolveAttachmentCount;
280 }
281
282 // NOTE: preserve attachments
283 VkAttachmentReference* depthAttachment = nullptr;
284 if (subpassDesc.depthAttachmentCount > 0) {
285 depthAttachment = &attachmentReferences[referenceIndex];
286 CreateAttachmentReferences(&subpassDesc.depthAttachmentIndex, layouts, subpassDesc.depthAttachmentCount,
287 referenceIndex, createRenderPassCompatibility, attachmentReferences.data());
288 referenceIndex += subpassDesc.depthAttachmentCount;
289 }
290
291 constexpr VkSubpassDescriptionFlags subpassDescriptionFlags { 0 };
292 subpassDescriptions[subpassIdx] = {
293 subpassDescriptionFlags, // flags
294 VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
295 subpassDesc.inputAttachmentCount, // inputAttachmentCount
296 inputAttachments, // pInputAttachments
297 subpassDesc.colorAttachmentCount, // colorAttachmentCount
298 colorAttachments, // pColorAttachments
299 resolveAttachments, // pResolveAttachments
300 depthAttachment, // pDepthStencilAttachment
301 0, // preserveAttachmentCount
302 nullptr, // pPreserveAttachments
303 };
304
305 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
306 // for compatibility mode we just need to pass the validation layer with bottom stage
307 VkPipelineStageFlags dstStageMask =
308 createRenderPassCompatibility ? VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT : (VkFlags)0;
309 VkAccessFlags srcAccessMask = 0;
310 VkAccessFlags dstAccessMask = 0;
311 if (!createRenderPassCompatibility) {
312 PLUGIN_ASSERT(srcResourceStates);
313 const RenderPassAttachmentResourceStates& dstResourceStates = subpassResourceStates[subpassIdx];
314 for (uint32_t attachmentIdx = 0; attachmentIdx < attachmentCount; ++attachmentIdx) {
315 srcStageMask |= srcResourceStates->states[attachmentIdx].pipelineStageFlags;
316 srcAccessMask |= srcResourceStates->states[attachmentIdx].accessFlags;
317
318 dstStageMask |= dstResourceStates.states[attachmentIdx].pipelineStageFlags;
319 dstAccessMask |= dstResourceStates.states[attachmentIdx].accessFlags;
320 }
321
322 // store for next subpass
323 srcResourceStates = &dstResourceStates;
324 }
325
326 constexpr VkDependencyFlags dependencyFlags { VkDependencyFlagBits::VK_DEPENDENCY_BY_REGION_BIT };
327 const uint32_t dstSubpass = subpassIdx;
328 subpassDependencies[subpassIdx] = {
329 srcSubpass, // srcSubpass
330 subpassIdx, // dstSubpass
331 srcStageMask, // srcStageMask
332 dstStageMask, // dstStageMask
333 srcAccessMask, // srcAccessMask
334 dstAccessMask, // dstAccessMask
335 dependencyFlags, // dependencyFlags
336 };
337 srcSubpass = dstSubpass;
338 }
339
340 constexpr VkRenderPassCreateFlags renderPassCreateFlags { 0 };
341 const VkRenderPassCreateInfo renderPassCreateInfo {
342 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // sType
343 nullptr, // pNext
344 renderPassCreateFlags, // flags
345 attachmentCount, // attachmentCount
346 attachmentDescriptions, // pAttachments
347 (uint32_t)subpassDescriptions.size(), // subpassCount
348 subpassDescriptions.data(), // pSubpasses
349 (uint32_t)subpassDependencies.size(), // dependencyCount
350 subpassDependencies.data(), // pDependencies
351 };
352
353 VkRenderPass renderPass { VK_NULL_HANDLE };
354 VALIDATE_VK_RESULT(vkCreateRenderPass(device, // device
355 &renderPassCreateInfo, // pCreateInfo
356 nullptr, // pAllocator
357 &renderPass)); // pRenderPass
358
359 return renderPass;
360 }
361
CreateRenderPassCombined2(const DeviceVk & deviceVk,const RenderPassDesc & renderPassDesc,const LowLevelRenderPassDataVk & lowLevelRenderPassData,const array_view<const RenderPassSubpassDesc> & subpassDescs,const RenderPassAttachmentResourceStates * subpassResourceStates,const RenderPassAttachmentResourceStates * inputResourceStates,const RenderPassImageLayouts * imageLayouts,const uint32_t maxAttachmentReferenceCountPerSubpass,const bool createRenderPassCompatibility,RenderPassCreatorVk::RenderPassStorage2 & rps2)362 VkRenderPass CreateRenderPassCombined2(const DeviceVk& deviceVk, const RenderPassDesc& renderPassDesc,
363 const LowLevelRenderPassDataVk& lowLevelRenderPassData, const array_view<const RenderPassSubpassDesc>& subpassDescs,
364 const RenderPassAttachmentResourceStates* subpassResourceStates, // null when using compatibility
365 const RenderPassAttachmentResourceStates* inputResourceStates, // null when using compatibility
366 const RenderPassImageLayouts* imageLayouts, // null when using compatibility
367 const uint32_t maxAttachmentReferenceCountPerSubpass, const bool createRenderPassCompatibility,
368 RenderPassCreatorVk::RenderPassStorage2& rps2)
369 {
370 const VkDevice device = (deviceVk.GetPlatformDataVk()).device;
371 const uint32_t attachmentCount = renderPassDesc.attachmentCount;
372 PLUGIN_ASSERT(attachmentCount <= PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT);
373
374 VkAttachmentDescription2KHR attachmentDescriptions[PipelineStateConstants::MAX_RENDER_PASS_ATTACHMENT_COUNT];
375 {
376 // add all attachments to attachmentDescriptions array
377 const auto attachments = array_view(renderPassDesc.attachments, renderPassDesc.attachmentCount);
378 const auto compatibilityAttachments =
379 array_view(lowLevelRenderPassData.renderPassCompatibilityDesc.attachments, renderPassDesc.attachmentCount);
380 const auto descriptions = array_view(attachmentDescriptions, countof(attachmentDescriptions));
381 if (createRenderPassCompatibility) {
382 CreateAttachmentDescriptionsCompatibility2(attachments, compatibilityAttachments, descriptions);
383 } else {
384 PLUGIN_ASSERT(imageLayouts);
385 const auto initialLayouts =
386 array_view(imageLayouts->attachmentInitialLayouts, renderPassDesc.attachmentCount);
387 const auto finalLayouts = array_view(imageLayouts->attachmentFinalLayouts, renderPassDesc.attachmentCount);
388 CreateAttachmentDescriptions2(
389 attachments, compatibilityAttachments, initialLayouts, finalLayouts, descriptions);
390 }
391 }
392
393 // resize vector for all subpass references
394 const uint32_t subpassCount = renderPassDesc.subpassCount;
395 auto& subpassDescriptions = rps2.subpassDescriptions;
396 auto& subpassDependencies = rps2.subpassDependencies;
397 auto& subpassDescriptionsDepthStencilResolve = rps2.subpassDescriptionsDepthStencilResolve;
398 auto& attachmentReferences = rps2.attachmentReferences;
399 subpassDescriptions.resize(subpassCount);
400 subpassDependencies.resize(subpassCount);
401 subpassDescriptionsDepthStencilResolve.resize(subpassCount);
402 attachmentReferences.resize(subpassCount * maxAttachmentReferenceCountPerSubpass);
403
404 uint32_t srcSubpass = VK_SUBPASS_EXTERNAL;
405 const RenderPassAttachmentResourceStates* srcResourceStates = inputResourceStates;
406 for (uint32_t subpassIdx = 0; subpassIdx < subpassCount; ++subpassIdx) {
407 const RenderPassSubpassDesc& subpassDesc = subpassDescs[subpassIdx];
408
409 const uint32_t startReferenceIndex = subpassIdx * maxAttachmentReferenceCountPerSubpass;
410 uint32_t referenceIndex = startReferenceIndex;
411
412 VkAttachmentReference2KHR* inputAttachments = nullptr;
413 const ImageLayout* layouts = subpassResourceStates ? subpassResourceStates[subpassIdx].layouts : nullptr;
414 if (subpassDesc.inputAttachmentCount > 0) {
415 inputAttachments = &attachmentReferences[referenceIndex];
416 CreateAttachmentReferences2(subpassDesc.inputAttachmentIndices, layouts, subpassDesc.inputAttachmentCount,
417 referenceIndex, createRenderPassCompatibility, attachmentReferences.data());
418 referenceIndex += subpassDesc.inputAttachmentCount;
419 }
420
421 VkAttachmentReference2KHR* colorAttachments = nullptr;
422 if (subpassDesc.colorAttachmentCount > 0) {
423 colorAttachments = &attachmentReferences[referenceIndex];
424 CreateAttachmentReferences2(subpassDesc.colorAttachmentIndices, layouts, subpassDesc.colorAttachmentCount,
425 referenceIndex, createRenderPassCompatibility, attachmentReferences.data());
426 referenceIndex += subpassDesc.colorAttachmentCount;
427 }
428
429 VkAttachmentReference2KHR* resolveAttachments = nullptr;
430 if (subpassDesc.resolveAttachmentCount > 0) {
431 resolveAttachments = &attachmentReferences[referenceIndex];
432 CreateAttachmentReferences2(subpassDesc.resolveAttachmentIndices, layouts,
433 subpassDesc.resolveAttachmentCount, referenceIndex, createRenderPassCompatibility,
434 attachmentReferences.data());
435 referenceIndex += subpassDesc.resolveAttachmentCount;
436 }
437
438 // NOTE: preserve attachments
439 VkAttachmentReference2KHR* depthAttachment = nullptr;
440 VkSubpassDescriptionDepthStencilResolveKHR* subpassDescriptionDepthStencilResolve = nullptr;
441 if (subpassDesc.depthAttachmentCount > 0) {
442 depthAttachment = &attachmentReferences[referenceIndex];
443 CreateAttachmentReferences2(&subpassDesc.depthAttachmentIndex, layouts, subpassDesc.depthAttachmentCount,
444 referenceIndex, createRenderPassCompatibility, attachmentReferences.data());
445 referenceIndex += subpassDesc.depthAttachmentCount;
446 if (subpassDesc.depthResolveAttachmentCount > 0) {
447 VkAttachmentReference2KHR* depthResolveAttachment = nullptr;
448 depthResolveAttachment = &attachmentReferences[referenceIndex];
449 CreateAttachmentReferences2(&subpassDesc.depthResolveAttachmentIndex, layouts,
450 subpassDesc.depthResolveAttachmentCount, referenceIndex, createRenderPassCompatibility,
451 attachmentReferences.data());
452 referenceIndex += subpassDesc.depthResolveAttachmentCount;
453 subpassDescriptionDepthStencilResolve = &subpassDescriptionsDepthStencilResolve[subpassIdx];
454 subpassDescriptionDepthStencilResolve->sType =
455 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE_KHR;
456 subpassDescriptionDepthStencilResolve->pNext = nullptr;
457 // NOTE: acceptable values needs to be evaluated from the device
458 // independent resolve not yet supported
459 const VkResolveModeFlagBitsKHR depthStencilResolveMode =
460 (VkResolveModeFlagBitsKHR)subpassDesc.depthResolveModeFlagBit;
461 subpassDescriptionDepthStencilResolve->depthResolveMode = depthStencilResolveMode;
462 subpassDescriptionDepthStencilResolve->stencilResolveMode = depthStencilResolveMode;
463 subpassDescriptionDepthStencilResolve->pDepthStencilResolveAttachment = depthResolveAttachment;
464 }
465 }
466
467 constexpr VkSubpassDescriptionFlags subpassDescriptionFlags { 0 };
468 constexpr uint32_t viewMask { 0 };
469 subpassDescriptions[subpassIdx] = {
470 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2_KHR, // sType
471 subpassDescriptionDepthStencilResolve, // pNext
472 subpassDescriptionFlags, // flags
473 VkPipelineBindPoint::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
474 viewMask, // viewMask
475 subpassDesc.inputAttachmentCount, // inputAttachmentCount
476 inputAttachments, // pInputAttachments
477 subpassDesc.colorAttachmentCount, // colorAttachmentCount
478 colorAttachments, // pColorAttachments
479 resolveAttachments, // pResolveAttachments
480 depthAttachment, // pDepthStencilAttachment
481 0, // preserveAttachmentCount
482 nullptr, // pPreserveAttachments
483 };
484
485 VkPipelineStageFlags srcStageMask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
486 // for compatibility mode we just need to pass the validation layer with bottom stage
487 VkPipelineStageFlags dstStageMask =
488 createRenderPassCompatibility ? VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT : (VkFlags)0;
489 VkAccessFlags srcAccessMask = 0;
490 VkAccessFlags dstAccessMask = 0;
491 if (!createRenderPassCompatibility) {
492 PLUGIN_ASSERT(srcResourceStates);
493 const RenderPassAttachmentResourceStates& dstResourceStates = subpassResourceStates[subpassIdx];
494 for (uint32_t attachmentIdx = 0; attachmentIdx < attachmentCount; ++attachmentIdx) {
495 srcStageMask |= srcResourceStates->states[attachmentIdx].pipelineStageFlags;
496 srcAccessMask |= srcResourceStates->states[attachmentIdx].accessFlags;
497
498 dstStageMask |= dstResourceStates.states[attachmentIdx].pipelineStageFlags;
499 dstAccessMask |= dstResourceStates.states[attachmentIdx].accessFlags;
500 }
501
502 // store for next subpass
503 srcResourceStates = &dstResourceStates;
504 }
505
506 constexpr VkDependencyFlags dependencyFlags { VkDependencyFlagBits::VK_DEPENDENCY_BY_REGION_BIT };
507 const uint32_t dstSubpass = subpassIdx;
508 subpassDependencies[subpassIdx] = {
509 VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2_KHR, // sType
510 nullptr, // pNext
511 srcSubpass, // srcSubpass
512 subpassIdx, // dstSubpass
513 srcStageMask, // srcStageMask
514 dstStageMask, // dstStageMask
515 srcAccessMask, // srcAccessMask
516 dstAccessMask, // dstAccessMask
517 dependencyFlags, // dependencyFlags
518 0, // viewOffset
519 };
520 srcSubpass = dstSubpass;
521 }
522
523 constexpr VkRenderPassCreateFlags renderPassCreateFlags { 0 };
524 const VkRenderPassCreateInfo2KHR renderPassCreateInfo {
525 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2_KHR, // sType
526 nullptr, // pNext
527 renderPassCreateFlags, // flags
528 attachmentCount, // attachmentCount
529 attachmentDescriptions, // pAttachments
530 (uint32_t)subpassDescriptions.size(), // subpassCount
531 subpassDescriptions.data(), // pSubpasses
532 (uint32_t)subpassDependencies.size(), // dependencyCount
533 subpassDependencies.data(), // pDependencies
534 0u, // correlatedViewMaskCount
535 nullptr, // pCorrelatedViewMasks
536 };
537
538 VkRenderPass renderPass { VK_NULL_HANDLE };
539 const DeviceVk::ExtFunctions& extFunctions = deviceVk.GetExtFunctions();
540 PLUGIN_ASSERT(extFunctions.vkCreateRenderPass2KHR); // required here
541 VALIDATE_VK_RESULT(extFunctions.vkCreateRenderPass2KHR(device, // device
542 &renderPassCreateInfo, // pCreateInfo
543 nullptr, // pAllocator
544 &renderPass)); // pRenderPass
545
546 return renderPass;
547 }
548 } // namespace
549
CreateRenderPass(const DeviceVk & deviceVk,const RenderCommandBeginRenderPass & beginRenderPass,const LowLevelRenderPassDataVk & lowLevelRenderPassData)550 VkRenderPass RenderPassCreatorVk::CreateRenderPass(const DeviceVk& deviceVk,
551 const RenderCommandBeginRenderPass& beginRenderPass, const LowLevelRenderPassDataVk& lowLevelRenderPassData)
552 {
553 const uint32_t subpassCount = beginRenderPass.renderPassDesc.subpassCount;
554 uint32_t maxAttachmentReferenceCountPerSubpass = 0;
555 bool depthStencilResolve = false;
556 for (uint32_t subpassIdx = 0; subpassIdx < subpassCount; ++subpassIdx) {
557 const auto& subpassDesc = beginRenderPass.subpasses[subpassIdx];
558 maxAttachmentReferenceCountPerSubpass = Math::max(maxAttachmentReferenceCountPerSubpass,
559 subpassDesc.inputAttachmentCount + subpassDesc.colorAttachmentCount + subpassDesc.resolveAttachmentCount +
560 subpassDesc.depthAttachmentCount + subpassDesc.depthResolveAttachmentCount);
561 // cannot resolve mode NONE
562 if ((subpassDesc.depthResolveAttachmentCount > 0) &&
563 (subpassDesc.depthResolveModeFlagBit || subpassDesc.stencilResolveModeFlagBit)) {
564 depthStencilResolve = true;
565 }
566 }
567
568 const DeviceVk::CommonDeviceExtensions& deviceExtensions = deviceVk.GetCommonDeviceExtensions();
569 if (depthStencilResolve && deviceExtensions.renderPass2) {
570 return CreateRenderPassCombined2(deviceVk, beginRenderPass.renderPassDesc, lowLevelRenderPassData,
571 beginRenderPass.subpasses, beginRenderPass.subpassResourceStates.data(),
572 &beginRenderPass.inputResourceStates, &beginRenderPass.imageLayouts, maxAttachmentReferenceCountPerSubpass,
573 false, rps2_);
574 } else {
575 return CreateRenderPassCombined(deviceVk, beginRenderPass.renderPassDesc, lowLevelRenderPassData,
576 beginRenderPass.subpasses, beginRenderPass.subpassResourceStates.data(),
577 &beginRenderPass.inputResourceStates, &beginRenderPass.imageLayouts, maxAttachmentReferenceCountPerSubpass,
578 false, rps1_);
579 }
580 }
581
CreateRenderPassCompatibility(const DeviceVk & deviceVk,const RenderPassDesc & renderPassDesc,const LowLevelRenderPassDataVk & lowLevelRenderPassData,const array_view<const RenderPassSubpassDesc> & renderPassSubpassDescs)582 VkRenderPass RenderPassCreatorVk::CreateRenderPassCompatibility(const DeviceVk& deviceVk,
583 const RenderPassDesc& renderPassDesc, const LowLevelRenderPassDataVk& lowLevelRenderPassData,
584 const array_view<const RenderPassSubpassDesc>& renderPassSubpassDescs)
585 {
586 const uint32_t subpassCount = renderPassDesc.subpassCount;
587 uint32_t maxAttachmentReferenceCountPerSubpass = 0;
588 bool depthStencilResolve = false;
589 for (uint32_t subpassIdx = 0; subpassIdx < subpassCount; ++subpassIdx) {
590 const auto& subpassDesc = renderPassSubpassDescs[subpassIdx];
591 maxAttachmentReferenceCountPerSubpass = Math::max(maxAttachmentReferenceCountPerSubpass,
592 subpassDesc.inputAttachmentCount + subpassDesc.colorAttachmentCount + subpassDesc.resolveAttachmentCount +
593 subpassDesc.depthAttachmentCount + subpassDesc.depthResolveAttachmentCount);
594 // cannot resolve mode NONE
595 if ((subpassDesc.depthResolveAttachmentCount > 0) &&
596 (subpassDesc.depthResolveModeFlagBit || subpassDesc.stencilResolveModeFlagBit)) {
597 depthStencilResolve = true;
598 }
599 }
600
601 const DeviceVk::CommonDeviceExtensions& deviceExtensions = deviceVk.GetCommonDeviceExtensions();
602 if (depthStencilResolve && deviceExtensions.renderPass2) {
603 return CreateRenderPassCombined2(deviceVk, renderPassDesc, lowLevelRenderPassData, renderPassSubpassDescs,
604 nullptr, nullptr, nullptr, maxAttachmentReferenceCountPerSubpass, true, rps2_);
605 } else {
606 return CreateRenderPassCombined(deviceVk, renderPassDesc, lowLevelRenderPassData, renderPassSubpassDescs,
607 nullptr, nullptr, nullptr, maxAttachmentReferenceCountPerSubpass, true, rps1_);
608 }
609 }
610
DestroyRenderPass(VkDevice device,VkRenderPass renderPass)611 void RenderPassCreatorVk::DestroyRenderPass(VkDevice device, VkRenderPass renderPass)
612 {
613 PLUGIN_ASSERT(device);
614 PLUGIN_ASSERT(renderPass);
615
616 vkDestroyRenderPass(device, // device
617 renderPass, // renderPass
618 nullptr); // pAllocator
619 }
620
621 RENDER_END_NAMESPACE()
622