• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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