FCT
载入中...
搜索中...
未找到
CommandBufferGraph.cpp
浏览该文件的文档.
2#include "./Context.h"
3#include "./Context.hpp"
4#include "../UI/Window.h"
5namespace FCT {
7 {
8 if (frameIndex >= m_frameDirty.size() || !m_frameDirty[frameIndex]) {
9 return;
10 }
11
12 if (m_outputEdge && frameIndex < m_collectedImageAvailable.size()) {
13 auto* semaphore = m_outputEdge->getImageAvailableSemaphore(frameIndex);
14 m_collectedImageAvailable[frameIndex] = semaphore;
15
16 markFrameClean(frameIndex);
17 }
18 }
19
20 std::vector<RHI::Fence*> CommandBufferNodes::OutputToWindow::getCollectedFence(uint32_t frameIndex) const
21 {
22 if (frameIndex < m_collectedFences.size()) {
23 return m_collectedFences[frameIndex];
24 }
25 return std::vector<RHI::Fence*>{} ;
26 }
27
29 uint32_t frameIndex) const
30 {
31 if (frameIndex < m_collectedRenderFinished.size()) {
32 return m_collectedRenderFinished[frameIndex];
33 }
34 return std::vector<RHI::Semaphore*>{} ;
35 }
36
38 {
39 if (frameIndex >= m_frameDirty.size() || !m_frameDirty[frameIndex]) {
40 return;
41 }
42
43 if (frameIndex >= m_collectedFences.size() || frameIndex >= m_collectedRenderFinished.size()) {
44 return;
45 }
46
47 m_collectedFences[frameIndex].clear();
48 m_collectedRenderFinished[frameIndex].clear();
49
50 for (auto* edge : m_inputEdges) {
51 if (edge) {
52 auto* fence = edge->getFence(frameIndex);
53 auto* semaphore = edge->getRenderFinishedSemaphore(frameIndex);
54
55 if (fence) {
56 m_collectedFences[frameIndex].push_back(fence);
57 }
58 if (semaphore) {
59 m_collectedRenderFinished[frameIndex].push_back(semaphore);
60 }
61 }
62 }
63
64 markFrameClean(frameIndex);
65 }
66
71
73 {
74 if (m_cmdBuffers.size() != newMaxFrameInFlight) {
75 for (auto& cmdBuffer : m_cmdBuffers)
76 {
77 cmdBuffer->release();
78 }
79 m_cmdBuffers.clear();
80 m_cmdBuffers.reserve(newMaxFrameInFlight);
81 for (uint32_t i = 0; i < newMaxFrameInFlight; ++i) {
82 auto cmdBuf = m_pool->createCommandBuffer();
83 cmdBuf->create();
84 m_cmdBuffers.push_back(cmdBuf);
85 }
86 }
87 m_frameDirty.clear();
88 m_frameDirty.resize(newMaxFrameInFlight, 1);
89 }
90
92 {
93 std::fill(m_frameDirty.begin(), m_frameDirty.end(), true);
94 m_outputEdges.push_back(edge);
95 }
96
98 {
99 std::fill(m_frameDirty.begin(), m_frameDirty.end(), 1);
100 m_inputEdges.push_back(edge);
101 }
102
104 {
105 if (frameIndex < m_cmdBuffers.size()) {
106 return m_cmdBuffers[frameIndex];
107 }
108 return nullptr;
109 }
110
111
113 {
114 auto* cmdBuf = getCommandBuffer(frameIndex);
115 if (!cmdBuf || frameIndex >= m_frameDirty.size() || !m_frameDirty[frameIndex]) {
116 return;
117 }
118
119 cmdBuf->clearWaitSemaphores();
120 cmdBuf->signalSemaphores().clear();
121
122 for (auto* edge : m_inputEdges) {
123 if (auto* inputEdge = dynamic_cast<CommandBufferEdges::InputFromWindow*>(edge)) {
124 if (auto* semaphore = inputEdge->getImageAvailableSemaphore(frameIndex)) {
125 cmdBuf->addWaitSemaphore(semaphore, PipelineStage::colorAttachmentOutput);
126 }
127 }
128 // TODO: 处理其他类型的输入边
129 }
130
131 for (auto* edge : m_outputEdges) {
132 if (auto* outputEdge = dynamic_cast<CommandBufferEdges::OutputToWindow*>(edge)) {
133 auto* semaphore = outputEdge->getRenderFinishedSemaphore(frameIndex);
134 if (semaphore) {
135 cmdBuf->addSignalSemaphore(semaphore);
136 }
137
138 auto* fence = outputEdge->getFence(frameIndex);
139 if (fence) {
140 cmdBuf->fence(fence);
141 }
142 }
143 // TODO: 处理其他类型的输出边
144 }
145
146 m_frameDirty[frameIndex] = false;
147 }
148
150 {
151
152 if (m_imageAvailable.size() != newMaxFrameInFlight) {
153 for (auto& semaphore : m_imageAvailable)
154 {
155 semaphore->release();
156 }
157 m_imageAvailable.clear();
158 m_imageAvailable.reserve(newMaxFrameInFlight);
159 for (uint32_t i = 0; i < newMaxFrameInFlight; ++i) {
160 auto semaphore = m_semaphorePool->alloc();
161 semaphore->create();
162 m_imageAvailable.push_back(semaphore);
163 }
164 }
165 }
167 {
168 if (m_renderFinished.size() != newMaxFrameInFlight) {
169 for (auto& semaphore : m_renderFinished)
170 {
171 semaphore->release();
172 }
173 m_renderFinished.clear();
174 m_renderFinished.reserve(newMaxFrameInFlight);
175 for (uint32_t i = 0; i < newMaxFrameInFlight; ++i) {
176 auto semaphore = m_semaphorePool->alloc();
177 semaphore->create();
178 m_renderFinished.push_back(semaphore);
179 }
180 }
181
182 if (m_fences.size() != newMaxFrameInFlight) {
183 for (auto& fence : m_fences)
184 {
185 fence->release();
186 }
187 m_fences.clear();
188 m_fences.reserve(newMaxFrameInFlight);
189 for (uint32_t i = 0; i < newMaxFrameInFlight; ++i) {
190 auto fence = m_fencePool->alloc();
191 fence->createSignaled();
192 m_fences.push_back(fence);
193 }
194 }
195 }
196
205
207 {
208 m_windows.insert(window);
209 auto it = m_windowInputNodes.find(window);
210 if (it != m_windowInputNodes.end()) {
211 return it->second;
212 }
213
214 auto inputNode = std::make_unique<CommandBufferNodes::InputFromWindow>(window);
215 auto* nodePtr = inputNode.get();
216 nodePtr->updateSynchronization(m_maxFrameInFlight);
217 m_nodes.push_back(std::move(inputNode));
218 m_windowInputNodes[window] = nodePtr;
219 return nodePtr;
220 }
221
223 {
224 m_windows.insert(window);
225 auto it = m_windowOutputNodes.find(window);
226 if (it != m_windowOutputNodes.end()) {
227 return it->second;
228 }
229
230 auto outputNode = std::make_unique<CommandBufferNodes::OutputToWindow>(window);
231 auto* nodePtr = outputNode.get();
232 nodePtr->updateSynchronization(m_maxFrameInFlight);
233 m_nodes.push_back(std::move(outputNode));
234 m_windowOutputNodes[window] = nodePtr;
235 return nodePtr;
236 }
237
239 const std::vector<NodeRef>& predecessors)
240 {
241 for (const auto& pred : predecessors) {
242 if (pred.type == NodeRef::WindowType) {
243 connectWindowPredecessor(buffer, pred.window);
244 }
245 else if (pred.type == NodeRef::CommandBufferType) {
246 // CommandBuffer -> CommandBuffer
247 // todo:
248 // 创建CommandBuffer之间的边,并对CommandBuffers执行fillAllSynchronization
249 }
250 }
251 }
252
254 const std::vector<NodeRef>& successors)
255 {
256 for (const auto& succ : successors) {
257 if (succ.type == NodeRef::WindowType) {
258 connectWindowSuccessor(buffer, succ.window);
259 }
260 else if (succ.type == NodeRef::CommandBufferType) {
261 // CommandBuffer -> CommandBuffer
262 // todo:
263 // 创建CommandBuffer之间的边,并对CommandBuffers执行fillAllSynchronization
264 }
265 }
266 }
267
269 {
270 auto* windowInputNode = getOrCreateWindowInputNode(window);
271 auto edge = std::make_unique<CommandBufferEdges::InputFromWindow>(m_semaphorePool);
272 auto* edgePtr = edge.get();
273
274 edgePtr->setSourceNode(windowInputNode);
275 edgePtr->setTargetNode(buffer);
276 edgePtr->updateSynchronization(m_maxFrameInFlight);
277
278 windowInputNode->addOutputEdge(edgePtr);
279 buffer->addInputEdge(edgePtr);
280
281 m_edges.push_back(std::move(edge));
282
283 windowInputNode->fillAllSynchronization();
284 }
285
287 {
288 auto* windowOutputNode = getOrCreateWindowOutputNode(window);
289 auto edge = std::make_unique<CommandBufferEdges::OutputToWindow>(m_fencePool,m_semaphorePool);
290 auto* edgePtr = edge.get();
291
292 edgePtr->setSourceNode(buffer);
293 edgePtr->setTargetNode(windowOutputNode);
294 edgePtr->updateSynchronization(m_maxFrameInFlight);
295
296 buffer->addOutputEdge(edgePtr);
297 windowOutputNode->addInputEdge(edgePtr);
298
299 m_edges.push_back(std::move(edge));
300
301 windowOutputNode->fillAllSynchronization();
302 }
304 {
305 m_maxFrameInFlight = max;
306 for (auto& edge : m_edges) {
307 edge->updateSynchronization(m_maxFrameInFlight);
308 }
309 for (auto& node : m_nodes) {
310 node->updateSynchronization(m_maxFrameInFlight);
311 }
312 for (auto& node : m_nodes) {
313 node->fillAllSynchronization();
314 }
315 }
316
318 {
319 for (auto& wnd : m_windows)
320 {
321 if (m_windowOutputNodes.count(wnd))
322 {
323 wnd->clearRenderFinshSemaphores();
324 for (auto semaphore : m_windowOutputNodes[wnd]->getCollectedRenderFinishedSemaphores(m_frameIndex))
325 {
326 wnd->addRenderFinshSemaphore(semaphore);
327 }
328 }
329 }
331 for (auto& wnd : m_windows) {
332 if (m_windowInputNodes.count(wnd))
333 {
334 wnd->setPresentFinshSemaphore(m_windowInputNodes[wnd]->getCollectedImageAvailableSemaphore(m_frameIndex));
335 }
336 if (m_windowOutputNodes.count(wnd))
337 {
338 wnd->clearRenderFinshFences();
339 for (auto fence : m_windowOutputNodes[wnd]->getCollectedFences(m_frameIndex))
340 {
341 wnd->addRenderFinshFence(fence);
342 }
343 }
344 }
345 for (auto wnd : m_windows)
346 {
347 wnd->swapBuffers();
348 }
349 }
350
355
356 CommandBufferToken CommandBufferGraph::addBuffer(const std::vector<NodeRef>& predecessors,
357 const std::vector<NodeRef>& successors)
358 {
359 auto newBuffer = std::make_unique<CommandBufferNodes::CommandBuffer>(m_cmdPool);
360 auto* bufferPtr = newBuffer.get();
361 bufferPtr->updateSynchronization(m_maxFrameInFlight);
362 m_nodes.push_back(std::move(newBuffer));
363
364 connectPredecessors(bufferPtr, predecessors);
365 connectSuccessors(bufferPtr, successors);
366
367 bufferPtr->fillAllSynchronization();
368 return bufferPtr;
369 }
370} // FCT
void updateSynchronization(uint32_t newMaxFrameInFlight) override
std::vector< RHI::Semaphore * > m_imageAvailable
std::vector< RHI::Semaphore * > m_renderFinished
void updateSynchronization(uint32_t newMaxFrameInFlight) override
void connectWindowPredecessor(CommandBufferNodes::CommandBuffer *buffer, Window *window)
void connectSuccessors(CommandBufferNodes::CommandBuffer *buffer, const std::vector< NodeRef > &successors)
std::vector< std::unique_ptr< CommandBufferNodes::NodeBase > > m_nodes
void connectPredecessors(CommandBufferNodes::CommandBuffer *buffer, const std::vector< NodeRef > &predecessors)
CommandBufferToken addBuffer(const std::vector< NodeRef > &predecessors, const std::vector< NodeRef > &successors)
RHI::CommandBuffer * getCommandBuffer(CommandBufferToken token) const
CommandBufferNodes::OutputToWindow * getOrCreateWindowOutputNode(Window *window)
std::unordered_map< Window *, CommandBufferNodes::InputFromWindow * > m_windowInputNodes
std::vector< std::unique_ptr< CommandBufferEdges::EdgeBase > > m_edges
std::unordered_map< Window *, CommandBufferNodes::OutputToWindow * > m_windowOutputNodes
CommandBufferNodes::InputFromWindow * getOrCreateWindowInputNode(Window *window)
void connectWindowSuccessor(CommandBufferNodes::CommandBuffer *buffer, Window *window)
RHI::CommandBuffer * getCommandBuffer(uint32_t frameIndex) const
std::vector< CommandBufferEdges::EdgeBase * > m_outputEdges
void fillSynchronization(uint32_t frameIndex) override
void updateSynchronization(uint32_t newMaxFrameInFlight) override
std::vector< RHI::CommandBuffer * > m_cmdBuffers
std::vector< CommandBufferEdges::EdgeBase * > m_inputEdges
void addInputEdge(CommandBufferEdges::EdgeBase *edge) override
void addOutputEdge(CommandBufferEdges::EdgeBase *edge) override
void fillSynchronization(uint32_t frameIndex) override
CommandBufferEdges::InputFromWindow * m_outputEdge
std::vector< RHI::Semaphore * > m_collectedImageAvailable
void fillSynchronization(uint32_t frameIndex) override
std::vector< CommandBufferEdges::OutputToWindow * > m_inputEdges
std::vector< RHI::Fence * > getCollectedFence(uint32_t frameIndex) const
std::vector< std::vector< RHI::Semaphore * > > m_collectedRenderFinished
std::vector< std::vector< RHI::Fence * > > m_collectedFences
std::vector< RHI::Semaphore * > getCollectedRenderFinishedSemaphore(uint32_t frameIndex) const
T * createResource()
CommandBufferNodes::CommandBuffer * CommandBufferToken