FCT
载入中...
搜索中...
未找到
VK_PassResource.cpp
浏览该文件的文档.
1//
2// Created by Administrator on 2025/4/14.
3//
4#include "../FCTAPI.h"
5namespace FCT
6{
11
13 {
14 for (auto& set : m_descriptorSets)
15 {
16 m_ctx->device().
17 freeDescriptorSets(
18 static_cast<RHI::VK_DescriptorPool*>(m_ctx->getDescriptorPool())->getPool(),set);
19 }
20 for (auto& layout : m_descriptorSetLayouts)
21 {
22 m_ctx->device().destroyDescriptorSetLayout(layout);
23 }
24 }
25
26
28 {
29 if (buffer) {
30 m_constBuffers.push_back(buffer);
33 }
34 }
35
37 {
38 if (sampler) {
39 m_samplers.emplace_back(sampler, element);
42 }
43 }
44
46 {
47 if (texture) {
48 m_textures[element] = texture;
51 }
52 }
53
55 {
56 if (texture) {
57 if (m_textures.find(element)!= m_textures.end())
58 {
59 } else
60 {
62 }
63 m_textures[element] = texture;
64 markDescriptorSetDirty(m_ctx->currentFrameIndex());
65 }
66 }
67
69 {
70 uint32_t maxFrames = m_ctx->maxFrameInFlight();
71 m_dirtyFlags.resize(maxFrames, true);
72 }
73
75 {
76 if (frameIdx < m_dirtyFlags.size()) {
77 m_dirtyFlags[frameIdx] = true;
78 }
79 }
81 std::vector<vk::DescriptorSetLayout>& outLayouts,
82 std::vector<vk::DescriptorSet>& outDescriptorSets)
83 {
84 vk::Device device = m_ctx->getDevice();
85 auto descriptorPool =
86 static_cast<RHI::VK_DescriptorPool*>(m_ctx->getDescriptorPool());
87
88 for (auto& layout : outLayouts) {
89 if (layout) {
90 device.destroyDescriptorSetLayout(layout);
91 layout = nullptr;
92 }
93 }
94
95 if (!outDescriptorSets.empty()) {
96 try {
97 device.freeDescriptorSets(descriptorPool->getPool(), outDescriptorSets);
98 outDescriptorSets.clear();
99 } catch (const vk::SystemError& e) {
100 }
101 }
102
103 std::map<uint32_t, std::vector<vk::DescriptorSetLayoutBinding>> setBindings;
104
105 for (auto* constBuffer : m_constBuffers) {
106 auto* vkConstBuffer = static_cast<RHI::VK_ConstBuffer*>(constBuffer);
107 auto uniformLayout = vkConstBuffer->layout();
108 auto [setIndex, binding] = m_ctx->getGenerator()->getLayoutBinding(uniformLayout);
109
110 vk::DescriptorSetLayoutBinding layoutBinding;
111 layoutBinding.setBinding(binding);
112 layoutBinding.setDescriptorType(vk::DescriptorType::eUniformBuffer);
113 layoutBinding.setDescriptorCount(1);
114 layoutBinding.setStageFlags(ConvertToVkShaderStageFlags(uniformLayout.getShaderStages()));
115
116 setBindings[setIndex].push_back(layoutBinding);
117 }
118
119 for (auto& [element, texture] : m_textures) {
120 auto [setIndex, binding] = m_ctx->getGenerator()->getTextureBinding(element);
121
122 vk::DescriptorSetLayoutBinding layoutBinding;
123 layoutBinding.setBinding(binding);
124 layoutBinding.setDescriptorType(vk::DescriptorType::eSampledImage);
125 layoutBinding.setDescriptorCount(1);
126 layoutBinding.setStageFlags(ConvertToVkShaderStageFlags(element.getShaderStages()));
127
128 setBindings[setIndex].push_back(layoutBinding);
129 }
130
131 for (auto& [sampler, element] : m_samplers) {
132 auto [setIndex, binding] = m_ctx->getGenerator()->getSamplerBinding(element);
133
134 vk::DescriptorSetLayoutBinding layoutBinding;
135 layoutBinding.setBinding(binding);
136 layoutBinding.setDescriptorType(vk::DescriptorType::eSampler);
137 layoutBinding.setDescriptorCount(1);
138 layoutBinding.setStageFlags(ConvertToVkShaderStageFlags(element.getShaderStages()));
139
140 setBindings[setIndex].push_back(layoutBinding);
141 }
142
143 if (setBindings.empty()) {
144 outLayouts.clear();
145 outDescriptorSets.clear();
146 return false;
147 }
148
149 uint32_t maxSetIndex = setBindings.rbegin()->first;
150
151 vk::DescriptorSetLayoutCreateInfo emptyLayoutInfo(
152 vk::DescriptorSetLayoutCreateFlags(),
153 0,
154 nullptr
155 );
156 vk::DescriptorSetLayout emptyLayout;
157 try {
158 emptyLayout = device.createDescriptorSetLayout(emptyLayoutInfo);
159 } catch (const vk::SystemError& e) {
160 throw std::runtime_error("Failed to create empty descriptor set layout: " + std::string(e.what()));
161 }
162
163 outLayouts.resize(maxSetIndex + 1, emptyLayout);
164
165 for (const auto& [setIndex, bindings] : setBindings) {
166 vk::DescriptorSetLayoutCreateInfo layoutInfo;
167 layoutInfo.setBindingCount(static_cast<uint32_t>(bindings.size()));
168 layoutInfo.setPBindings(bindings.data());
169
170 try {
171 if (outLayouts[setIndex] != emptyLayout) {
172 device.destroyDescriptorSetLayout(outLayouts[setIndex]);
173 }
174 outLayouts[setIndex] = device.createDescriptorSetLayout(layoutInfo);
175 } catch (const vk::SystemError& e) {
176 for (auto& layout : outLayouts) {
177 if (layout) {
178 device.destroyDescriptorSetLayout(layout);
179 layout = nullptr;
180 }
181 }
182 throw std::runtime_error("Failed to create descriptor set layout: " + std::string(e.what()));
183 }
184 }
185
186 vk::DescriptorSetAllocateInfo allocInfo;
187 allocInfo.setDescriptorPool(descriptorPool->getPool());
188 allocInfo.setDescriptorSetCount(static_cast<uint32_t>(outLayouts.size()));
189 allocInfo.setPSetLayouts(outLayouts.data());
190 try {
191 outDescriptorSets = device.allocateDescriptorSets(allocInfo);
192 } catch (const vk::SystemError& e) {
193 for (auto& layout : outLayouts) {
194 if (layout) {
195 device.destroyDescriptorSetLayout(layout);
196 layout = nullptr;
197 }
198 }
199 throw std::runtime_error("Failed to allocate descriptor sets for frame " +
200 std::to_string(frameIdx) + ": " + std::string(e.what()));
201 }
202
203 return true;
204 }
206 {
207 if (m_constBuffers.empty() && m_samplers.empty() && m_textures.empty()) {
208 return;
209 }
210
211 uint32_t maxFrames = m_ctx->maxFrameInFlight();
212
213 m_descriptorSets.resize(maxFrames);
214 m_dirtyFlags.resize(maxFrames, true);
215
216 for (uint32_t frameIdx = 0; frameIdx < maxFrames; ++frameIdx) {
219
220 m_dirtyFlags[frameIdx] = true;
222 }
223 }
224 }
225
227
228
229 if (frameIdx >= m_dirtyFlags.size() || !m_dirtyFlags[frameIdx]) {
230 return;
231 }
232
233 vk::Device device = m_ctx->getDevice();
234
235 std::vector<vk::WriteDescriptorSet> descriptorWrites;
236 descriptorWrites.reserve(m_constBuffers.size() + m_textures.size() + m_samplers.size());
237
238 std::vector<vk::DescriptorBufferInfo> bufferInfos;
239 bufferInfos.reserve(m_constBuffers.size());
240
241 std::vector<vk::DescriptorImageInfo> textureInfos;
242 textureInfos.reserve(m_textures.size());
243
244 std::vector<vk::DescriptorImageInfo> samplerInfos;
245 samplerInfos.reserve(m_samplers.size());
246
247 for (size_t i = 0; i < m_constBuffers.size(); ++i) {
248 auto* srcConstBuffer = m_constBuffers[i];
249 auto* constBuffer = static_cast<RHI::VK_ConstBuffer*>(srcConstBuffer);
250 auto uniformLayout = constBuffer->layout();
251 auto [setIndex, binding] = m_ctx->getGenerator()->getLayoutBinding(uniformLayout);
252
253 if (setIndex >= m_descriptorSets[frameIdx].size()) {
254 continue;
255 }
256
257 bufferInfos.push_back(constBuffer->currentBufferInfoWithoutUpdata());
258
259 vk::WriteDescriptorSet descriptorWrite;
260 descriptorWrite.setDstSet(m_descriptorSets[frameIdx][setIndex]);
261 descriptorWrite.setDstBinding(binding);
262 descriptorWrite.setDstArrayElement(0);
263 descriptorWrite.setDescriptorType(vk::DescriptorType::eUniformBuffer);
264 descriptorWrite.setDescriptorCount(1);
265 descriptorWrite.setPBufferInfo(&bufferInfos[bufferInfos.size() - 1]);
266
267 descriptorWrites.push_back(descriptorWrite);
268 }
269
270 for (auto& [element, texture ] : m_textures) {
271 auto* vkTexture = static_cast<RHI::VK_TextureView*>(texture->currentTextureView());
272 auto [setIndex, binding] = m_ctx->getGenerator()->getTextureBinding(element);
273
274 if (setIndex >= m_descriptorSets[frameIdx].size() || !vkTexture) {
275 continue;
276 }
277
278 vk::DescriptorImageInfo imageInfo;
279 imageInfo.setImageLayout(vk::ImageLayout::eShaderReadOnlyOptimal);
280 imageInfo.setImageView(vkTexture->view());
281 imageInfo.setSampler(nullptr);
282 textureInfos.push_back(imageInfo);
283
284 vk::WriteDescriptorSet descriptorWrite;
285 descriptorWrite.setDstSet(m_descriptorSets[frameIdx][setIndex]);
286 descriptorWrite.setDstBinding(binding);
287 descriptorWrite.setDstArrayElement(0);
288 descriptorWrite.setDescriptorType(vk::DescriptorType::eSampledImage);
289 descriptorWrite.setDescriptorCount(1);
290 descriptorWrite.setPImageInfo(&textureInfos[textureInfos.size() - 1]);
291
292 descriptorWrites.push_back(descriptorWrite);
293 }
294
295 for (size_t i = 0; i < m_samplers.size(); ++i) {
296 auto& [sampler, element] = m_samplers[i];
297 auto* vkSampler = static_cast<RHI::VK_Sampler*>(sampler);
298 auto [setIndex, binding] = m_ctx->getGenerator()->getSamplerBinding(element);
299
300 if (setIndex >= m_descriptorSets[frameIdx].size() || !vkSampler) {
301 continue;
302 }
303
304 vk::DescriptorImageInfo samplerInfo;
305 samplerInfo.setSampler(vkSampler->getSampler());
306 samplerInfo.setImageView(nullptr);
307 samplerInfo.setImageLayout(vk::ImageLayout::eUndefined);
308 samplerInfos.push_back(samplerInfo);
309
310 vk::WriteDescriptorSet descriptorWrite;
311 descriptorWrite.setDstSet(m_descriptorSets[frameIdx][setIndex]);
312 descriptorWrite.setDstBinding(binding);
313 descriptorWrite.setDstArrayElement(0);
314 descriptorWrite.setDescriptorType(vk::DescriptorType::eSampler);
315 descriptorWrite.setDescriptorCount(1);
316 descriptorWrite.setPImageInfo(&samplerInfos[samplerInfos.size() - 1]);
317
318 descriptorWrites.push_back(descriptorWrite);
319 }
320
321 if (!descriptorWrites.empty()) {
322 device.updateDescriptorSets(descriptorWrites, nullptr);
323 }
324
325 m_dirtyFlags[frameIdx] = false;
326 }
327 vk::DescriptorSet VK_PassResource::getDescriptorSet(uint32_t frameIdx, uint32_t setIndex)
328 {
331
332 if (frameIdx < m_descriptorSets.size() && setIndex < m_descriptorSets[frameIdx].size()) {
333 return m_descriptorSets[frameIdx][setIndex];
334 }
335
336 return nullptr;
337 }
339 {
340 uint32_t maxFrames = m_ctx->maxFrameInFlight();
341 m_needRecreate.resize(maxFrames, true);
342 for (auto frameIdx = 0; frameIdx < maxFrames; ++frameIdx)
343 {
344 m_needRecreate[frameIdx] = true;
345 }
346 }
348 {
349 if (frameIdx >= m_needRecreate.size() || !m_needRecreate[frameIdx])
350 {
351 return false;
352 }
355 fout << std::hex << m_descriptorSets[frameIdx].data() << " has been created" << std::endl;
356 m_needRecreate[frameIdx] = false;
357 m_dirtyFlags[frameIdx] = true;
358 return true;
359 }
360 return false;
361 }
362
364 {
365 uint32_t frameIdx = m_ctx->currentSubmitFrameIndex();
368 }
369
371 {
372
373 if (!srcPipeline || m_descriptorSets.empty()) {
374 return;
375 }
376
377 uint32_t frameIdx = m_ctx->currentSubmitFrameIndex();
378
382
383 auto vkCmdBuf = static_cast<RHI::VK_CommandBuffer*>(cmdBuf);
384 vk::CommandBuffer commandBuffer = vkCmdBuf->commandBuffer();
385
386 auto pipeline = static_cast<RHI::VK_RasterizationPipeline*>(srcPipeline);
387 vk::PipelineLayout pipelineLayout = pipeline->pipelineLayout();
388
389 vk::PipelineBindPoint bindPoint = vk::PipelineBindPoint::eGraphics;
390
391 if (!m_descriptorSets[frameIdx].empty()) {
392 commandBuffer.bindDescriptorSets(
393 bindPoint,
394 pipelineLayout,
395 0,
396 static_cast<uint32_t>(m_descriptorSets[frameIdx].size()),
397 m_descriptorSets[frameIdx].data(),
398 0,
399 nullptr
400 );
401 }
402 }
403
405 {
406 bool hasChange = false;
407 for (auto& it : m_textureViewHashes)
408 {
409 if (m_textures[it.first]->textureViewHash() != it.second)
410 {
411 hasChange = true;
412 it.second = m_textures[it.first]->textureViewHash();
413 }
414 }
415 if (hasChange)
417 }
418}
std::vector< std::pair< Sampler *, SamplerElement > > m_samplers
std::vector< RHI::ConstBuffer * > m_constBuffers
std::unordered_map< TextureElement, Image * > m_textures
void layout(const ConstLayout &layout)
bool createDescriptorSetsAndLayouts(uint32_t frameIdx, std::vector< vk::DescriptorSetLayout > &outLayouts, std::vector< vk::DescriptorSet > &outDescriptorSets)
std::vector< uint8_t > m_needRecreate
vk::DescriptorSet getDescriptorSet(uint32_t frameIdx, uint32_t setIndex)
std::unordered_map< TextureElement, size_t > m_textureViewHashes
void updateDescriptorSetsIfNeeded(uint32_t frameIdx)
VK_PassResource(VK_Context *ctx)
void bind(RHI::CommandBuffer *cmdBuf, RHI::Pipeline *pipeline) override
void setTexture(Image *texture, TextureElement element) override
void markDescriptorSetDirty(uint32_t frameIdx)
std::vector< vk::DescriptorSetLayout > m_descriptorSetLayouts
std::vector< uint8_t > m_dirtyFlags
void addConstBuffer(RHI::ConstBuffer *buffer) override
bool recreateDescriptorSetsIfNeeded(uint32_t frameIdx)
std::vector< std::vector< vk::DescriptorSet > > m_descriptorSets
void addTexture(Image *texture, TextureElement element) override
void addSampler(Sampler *sampler, SamplerElement element) override
std::ostream & fout
vk::ShaderStageFlags ConvertToVkShaderStageFlags(ShaderStages stages)