-
Notifications
You must be signed in to change notification settings - Fork 70
Expand file tree
/
Copy pathIFramebuffer.h
More file actions
222 lines (198 loc) · 14.8 KB
/
IFramebuffer.h
File metadata and controls
222 lines (198 loc) · 14.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#ifndef _NBL_ASSET_I_FRAMBEBUFFER_H_INCLUDED_
#define _NBL_ASSET_I_FRAMBEBUFFER_H_INCLUDED_
#include "nbl/asset/IImageView.h"
#include "nbl/asset/IRenderpass.h"
namespace nbl::asset
{
template <typename RenderpassType, typename ImageViewType>
class IFramebuffer
{
public:
using renderpass_t = RenderpassType;
template<bool Creation>
struct SCreationParamsBase
{
using attachment_ptr_t = std::conditional_t<Creation,ImageViewType*const *,core::smart_refctd_ptr<ImageViewType>*>;
core::smart_refctd_ptr<renderpass_t> renderpass;
attachment_ptr_t depthStencilAttachments = nullptr;
attachment_ptr_t colorAttachments = nullptr;
uint32_t width;
uint32_t height;
uint32_t layers = 1;
};
struct SCreationParams : SCreationParamsBase<true>
{
using base_t = SCreationParamsBase<true>;
inline bool validate() const
{
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-width-00885
if (!base_t::width)
return false;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-width-00887
if (!base_t::height)
return false;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-width-00889
if (!base_t::layers)
return false;
const auto* const rp = base_t::renderpass.get();
if (!rp)
return false;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-renderPass-02531
if (rp->hasViewMasks() && base_t::layers!=1)
return false;
auto invalidUsageForLayout = [](const IImage::LAYOUT layout, const core::bitflag<IImage::E_USAGE_FLAGS> usages) -> bool
{
switch (layout)
{
case IImage::LAYOUT::READ_ONLY_OPTIMAL:
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBeginRenderPass2KHR.html#VUID-vkCmdBeginRenderPass2-initialLayout-03097
if (!(usages&(IImage::E_USAGE_FLAGS::EUF_SAMPLED_BIT|IImage::E_USAGE_FLAGS::EUF_INPUT_ATTACHMENT_BIT)))
return true;
break;
case IImage::LAYOUT::ATTACHMENT_OPTIMAL:
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBeginRenderPass2KHR.html#VUID-vkCmdBeginRenderPass2-initialLayout-03094
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBeginRenderPass2KHR.html#VUID-vkCmdBeginRenderPass2-initialLayout-03096
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBeginRenderPass2KHR.html#VUID-vkCmdBeginRenderPass2-initialLayout-02844
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBeginRenderPass2KHR.html#VUID-vkCmdBeginRenderPass2-stencilInitialLayout-02845
if (!usages.hasFlags(IImage::E_USAGE_FLAGS::EUF_RENDER_ATTACHMENT_BIT))
return true;
break;
case IImage::LAYOUT::TRANSFER_SRC_OPTIMAL:
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBeginRenderPass2KHR.html#VUID-vkCmdBeginRenderPass2-initialLayout-03098
if (!usages.hasFlags(IImage::E_USAGE_FLAGS::EUF_TRANSFER_SRC_BIT))
return true;
break;
case IImage::LAYOUT::TRANSFER_DST_OPTIMAL:
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBeginRenderPass2KHR.html#VUID-vkCmdBeginRenderPass2-initialLayout-03099
if (!usages.hasFlags(IImage::E_USAGE_FLAGS::EUF_TRANSFER_DST_BIT))
return true;
break;
// TODO: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBeginRenderPass2KHR.html#VUID-vkCmdBeginRenderPass2-initialLayout-07002
// TODO: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/vkCmdBeginRenderPass2KHR.html#VUID-vkCmdBeginRenderPass2-initialLayout-07003
default:
break;
}
return false;
};
// upgrade to 32bit on purpose
const int32_t viewMaskMSB = rp->getViewMaskMSB();
/*
* If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments that is used as a color
attachment or resolve attachment by renderPass must have been created with a usage value including VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
* If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments that is used as a depth/stencil attachment
by renderPass must have been created with a usage value including VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
* If flags does not include VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT, each element of pAttachments that is used as an input attachment
by renderPass must have been created with a usage value including VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
*/
auto invalidAttachments = [&](const uint32_t presentAttachments, const auto* const attachmentDesc, const ImageViewType* const* const attachments) -> bool
{
for (uint32_t i=0u; i<presentAttachments; ++i)
{
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-flags-02778
if (!attachments[i])
return true;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-commonparent
if (!rp->isCompatibleDevicewise(attachments[i]))
return true;
const auto& viewParams = attachments[i]->getCreationParameters();
const auto& imgParams = viewParams.image->getCreationParameters();
const auto& subresourceRange = viewParams.subresourceRange;
const int32_t layerCount = static_cast<int32_t>(subresourceRange.layerCount!=ImageViewType::remaining_array_layers ? subresourceRange.layerCount:imgParams.arrayLayers);
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-flags-04535
if (static_cast<uint32_t>(layerCount)<base_t::layers)
return true;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-renderPass-04536
if (layerCount<=viewMaskMSB)
return true;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-pAttachments-00883
const auto levelCount = subresourceRange.levelCount!=ImageViewType::remaining_mip_levels ? subresourceRange.levelCount:imgParams.mipLevels;
if (levelCount!=1)
return true;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-pAttachments-00884
if (viewParams.components!=typename ImageViewType::SComponentMapping())
return true;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-flags-04533
if (imgParams.extent.width<base_t::width)
return true;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-flags-04534
if (imgParams.extent.height<base_t::height)
return true;
const auto& desc = attachmentDesc[i];
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-pAttachments-00880
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-pAttachments-00881
if (viewParams.format!=desc.format || imgParams.samples!=desc.samples)
return true;
const auto usages = viewParams.actualUsages();
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-pAttachments-00877
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-pAttachments-02633
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-pAttachments-02634
if (!usages.hasFlags(IImage::EUF_RENDER_ATTACHMENT_BIT))
return true;
if constexpr (std::is_same_v<decltype(desc),const IRenderpass::SCreationParams::SDepthStencilAttachmentDescription&>)
{
if (invalidUsageForLayout(desc.initialLayout.actualStencilLayout(),usages) || invalidUsageForLayout(desc.initialLayout.depth,usages))
return true;
if (invalidUsageForLayout(desc.finalLayout.actualStencilLayout(),usages) || invalidUsageForLayout(desc.finalLayout.depth,usages))
return true;
const auto viewType = viewParams.viewType;
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-pAttachments-00891
if (imgParams.type==IImage::ET_3D && (viewType==ImageViewType::ET_2D||viewType==ImageViewType::ET_2D_ARRAY))
return true;
}
else
{
static_assert(std::is_same_v<decltype(desc),const IRenderpass::SCreationParams::SColorAttachmentDescription&>);
if (invalidUsageForLayout(desc.initialLayout,usages) || invalidUsageForLayout(desc.finalLayout,usages))
return true;
}
}
return false;
};
const auto& rpParams = rp->getCreationParameters();
if (invalidAttachments(rp->getDepthStencilAttachmentCount(),rpParams.depthStencilAttachments,base_t::depthStencilAttachments))
return false;
if (invalidAttachments(rp->getColorAttachmentCount(),rpParams.colorAttachments,base_t::colorAttachments))
return false;
for (auto j=0u; j<rp->getSubpassCount(); j++)
{
const IRenderpass::SCreationParams::SSubpassDescription& desc = rp->getCreationParameters().subpasses[j];
bool valid = true;
core::visit_token_terminated_array(desc.inputAttachments,IRenderpass::SCreationParams::SSubpassDescription::InputAttachmentsEnd,[&](const IRenderpass::SCreationParams::SSubpassDescription::SInputAttachmentRef& ia)->bool
{
const auto& viewParams = (ia.isColor() ? base_t::colorAttachments[ia.asColor.attachmentIndex]:base_t::depthStencilAttachments[ia.asDepthStencil.attachmentIndex])->getCreationParameters();
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-pAttachments-00879
if (viewParams.actualUsages().hasFlags(IImage::EUF_INPUT_ATTACHMENT_BIT))
return (valid=false);
//TODO: https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFramebufferCreateInfo.html#VUID-VkFramebufferCreateInfo-samples-07009
return true;
});
if (!valid)
return false;
}
return true;
}
};
using SCachedCreationParams = SCreationParamsBase<false>;
const SCachedCreationParams& getCreationParameters() const { return m_params; }
protected:
explicit IFramebuffer(const SCreationParams& params) : m_params{std::move(params.renderpass),nullptr,nullptr,params.width,params.height,params.layers}
{
const auto* const rp = m_params.renderpass.get();
const auto depthStencilCount = rp->getDepthStencilAttachmentCount();
const auto colorCount = rp->getColorAttachmentCount();
m_attachments = core::make_refctd_dynamic_array<attachments_array_t>(depthStencilCount+colorCount);
m_params.depthStencilAttachments = m_attachments->data();
m_params.colorAttachments = m_params.depthStencilAttachments+depthStencilCount;
for (uint32_t i=0; i<depthStencilCount; i++)
m_params.depthStencilAttachments[i] = core::smart_refctd_ptr<ImageViewType>(params.depthStencilAttachments[i]);
for (uint32_t i=0; i<colorCount; i++)
m_params.colorAttachments[i] = core::smart_refctd_ptr<ImageViewType>(params.colorAttachments[i]);
}
virtual ~IFramebuffer() = default;
SCachedCreationParams m_params;
using attachments_array_t = core::smart_refctd_dynamic_array<core::smart_refctd_ptr<ImageViewType>>;
// storage for m_params.attachments
attachments_array_t m_attachments;
};
}
#endif