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