FCT
载入中...
搜索中...
未找到
CommandBufferGraph.h
浏览该文件的文档.
1#ifndef COMMANDBUFFERGRAPH_H
2#define COMMANDBUFFERGRAPH_H
5
6namespace FCT
7{
8 class Device;
9 class SemaphorePool;
10 class FencePool;
11 class Window;
12 class Context;
13 namespace RHI
14 {
15 class Semaphore;
16 class Fence;
17 class CommandPool;
18 class CommandBuffer;
19 }
21 {
22 class EdgeBase;
23 }
25 {
26 class NodeBase;
27 class InputFromWindow;
28 class OutputToWindow;
29 class CommandBuffer;
30 }
31 namespace CommandBufferEdges
32 {
34 {
35 public:
36 virtual ~EdgeBase() = default;
37 EdgeBase(SemaphorePool* semaphorePool) : m_semaphorePool(semaphorePool) {}
38 virtual void updateSynchronization(uint32_t newMaxFrameInFlight) = 0;
39 protected:
41 };
43 {
44 public:
45 InputFromWindow(SemaphorePool* semaphorePool) : EdgeBase(semaphorePool) {}
46
50 void updateSynchronization(uint32_t newMaxFrameInFlight) override;
51
55
62
63 RHI::Semaphore* getImageAvailableSemaphore(uint32_t frameIndex) const {
64 if (frameIndex < m_imageAvailable.size()) {
65 return m_imageAvailable[frameIndex];
66 }
67 return nullptr;
68 }
69 private:
70 std::vector<RHI::Semaphore*> m_imageAvailable;
73 };
74 class OutputToWindow : public EdgeBase
75 {
76 public:
77 OutputToWindow(FencePool* fencePool,SemaphorePool* semaphorePool) : EdgeBase(semaphorePool),
78 m_fencePool(fencePool) {}
82
89
93
94 RHI::Semaphore* getRenderFinishedSemaphore(uint32_t frameIndex) const {
95 if (frameIndex < m_renderFinished.size()) {
96 return m_renderFinished[frameIndex];
97 }
98 return nullptr;
99 }
100
101 RHI::Fence* getFence(uint32_t frameIndex) const {
102 if (frameIndex < m_fences.size()) {
103 return m_fences[frameIndex];
104 }
105 return nullptr;
106 }
107 void updateSynchronization(uint32_t newMaxFrameInFlight) override;
108 private:
110 std::vector<RHI::Semaphore*> m_renderFinished;
111 std::vector<RHI::Fence*> m_fences;
114 };
115 }
116 namespace CommandBufferNodes
117 {
118 class NodeBase {
119 public:
120 virtual ~NodeBase() = default;
125 virtual void updateSynchronization(uint32_t newMaxFrameInFlight) = 0;
128 virtual void fillSynchronization(uint32_t frameIndex) {}
131
135 virtual void fillAllSynchronization() {
136 for (uint32_t i = 0; i < m_frameDirty.size(); ++i) {
138 }
139 }
140 void markFrameDirty(uint32_t frameIndex) {
141 if (frameIndex < m_frameDirty.size()) {
142 m_frameDirty[frameIndex] = 1;
143 }
144 }
145
146 void markFrameClean(uint32_t frameIndex) {
147 if (frameIndex < m_frameDirty.size()) {
148 m_frameDirty[frameIndex] = 0;
149 }
150 }
151
153 std::fill(m_frameDirty.begin(), m_frameDirty.end(), 1);
154 }
155 protected:
156 std::vector<uint8_t> m_frameDirty;
157 };
158 class InputFromWindow : public NodeBase {
159 public:
160 InputFromWindow(Window* window) : m_window(window) {}
161 void updateSynchronization(uint32_t newMaxFrameInFlight) override
162 {
164 m_collectedImageAvailable.resize(newMaxFrameInFlight, nullptr);
165 m_frameDirty.clear();
166 m_frameDirty.resize(newMaxFrameInFlight, 1);
167 }
170 if (auto* inputEdge = dynamic_cast<CommandBufferEdges::InputFromWindow*>(edge)) {
171 if (m_outputEdge != nullptr) {
172 throw std::runtime_error("InputFromWindow node can only have one output edge");
173 }
174 m_outputEdge = inputEdge;
175 return;
176 }
177 throw std::runtime_error("InputFromWindow node can only accept InputFromWindow edge type");
178 }
179
182 throw std::runtime_error("InputFromWindow node cannot accept input edges");
183 }
185 if (edge == m_outputEdge) {
186 m_outputEdge = nullptr;
188 }
189 }
190
191 void fillSynchronization(uint32_t frameIndex) override;
192
194 if (frameIndex < m_collectedImageAvailable.size()) {
195 return m_collectedImageAvailable[frameIndex];
196 }
197 return nullptr;
198 }
199 private:
202 std::vector<RHI::Semaphore*> m_collectedImageAvailable;
203 };
205 {
206 public:
207 OutputToWindow(Window* window) : m_window(window) {}
208 void updateSynchronization(uint32_t newMaxFrameInFlight) override {
209 m_collectedFences.clear();
210 m_collectedFences.resize(newMaxFrameInFlight);
212 m_collectedRenderFinished.resize(newMaxFrameInFlight);
213
214 m_frameDirty.clear();
215 m_frameDirty.resize(newMaxFrameInFlight, 1);
216 }
217
220 if (auto* outputEdge = dynamic_cast<CommandBufferEdges::OutputToWindow*>(edge)) {
221 m_inputEdges.push_back(outputEdge);
222 return;
223 }
224 throw std::runtime_error("OutputToWindow node can only accept OutputToWindow edge type");
225 }
226
229 throw std::runtime_error("OutputToWindow node cannot accept output edges");
230 }
231
232 std::vector<RHI::Fence*> getCollectedFence(uint32_t frameIndex) const;
233 std::vector<RHI::Semaphore*> getCollectedRenderFinishedSemaphore(uint32_t frameIndex) const;
234 void fillSynchronization(uint32_t frameIndex) override;
235
236 const std::vector<RHI::Fence*>& getCollectedFences(uint32_t frameIndex) const {
237 static const std::vector<RHI::Fence*> empty;
238 if (frameIndex < m_collectedFences.size()) {
239 return m_collectedFences[frameIndex];
240 }
241 return empty;
242 }
244 {
245 for (auto it = m_inputEdges.begin(); it!= m_inputEdges.end(); ++it) {
246 if (*it == edge) {
247 m_inputEdges.erase(it);
249 return;
250 }
251 }
252 throw std::runtime_error("OutputToWindow node does not have the specified input edge");
253 }
254
255 const std::vector<RHI::Semaphore*>& getCollectedRenderFinishedSemaphores(uint32_t frameIndex) const {
256 static const std::vector<RHI::Semaphore*> empty;
257 if (frameIndex < m_collectedRenderFinished.size()) {
258 return m_collectedRenderFinished[frameIndex];
259 }
260 return empty;
261 }
262
263 private:
265 std::vector<CommandBufferEdges::OutputToWindow*> m_inputEdges;
266 std::vector<std::vector<RHI::Fence*>> m_collectedFences; // 收集的每帧的所有fence
267 std::vector<std::vector<RHI::Semaphore*>> m_collectedRenderFinished; // 收集的每帧的所有renderFinished信号量
268 };
269
270 class CommandBuffer : public NodeBase
271 {
272 public:
274 ~CommandBuffer() override;
275 void updateSynchronization(uint32_t newMaxFrameInFlight) override;
276 void addOutputEdge(CommandBufferEdges::EdgeBase* edge) override;
277 void addInputEdge(CommandBufferEdges::EdgeBase* edge) override;
278 RHI::CommandBuffer* getCommandBuffer(uint32_t frameIndex) const;
279 void fillSynchronization(uint32_t frameIndex) override;
280
281 std::vector<CommandBufferEdges::EdgeBase*>& getOutputEdges() {
282 return m_outputEdges;
283 }
284
285 std::vector<CommandBufferEdges::EdgeBase*>& getInputEdges() {
286 return m_inputEdges;
287 }
289 {
290 auto it = std::find(m_inputEdges.begin(), m_inputEdges.end(), edge);
291 if (it != m_inputEdges.end()) {
292 m_inputEdges.erase(it);
294 }
295 }
297 {
298 auto it = std::find(m_outputEdges.begin(), m_outputEdges.end(), edge);
299 if (it != m_outputEdges.end()) {
300 m_outputEdges.erase(it);
302 }
303 }
304 private:
305 std::vector<CommandBufferEdges::EdgeBase*> m_outputEdges;
306 std::vector<CommandBufferEdges::EdgeBase*> m_inputEdges;
307 std::vector<RHI::CommandBuffer*> m_cmdBuffers;
309 };
310 }
313 {
314 private:
318
319 std::unordered_set<CommandBufferNodes::NodeBase*> m_nodes;
320 std::unordered_set<std::unique_ptr<CommandBufferEdges::EdgeBase>> m_edges;
321
322 std::unordered_map<Window*, CommandBufferNodes::InputFromWindow*> m_windowInputNodes;
323 std::unordered_map<Window*, CommandBufferNodes::OutputToWindow*> m_windowOutputNodes;
324 std::set<Window*> m_windows;
325 uint32_t m_maxFrameInFlight = 0;
327
328 public:
329 CommandBufferGraph(Device* device);
346 const std::vector<NodeRef>& predecessors,
347 const std::vector<NodeRef>& successors);
350 void maxFrameInFlight(uint32_t max);
351 void swapBuffer();
353
354 private:
357 void connectPredecessors(CommandBufferNodes::CommandBuffer* buffer, const std::vector<NodeRef>& predecessors);
358 void connectSuccessors(CommandBufferNodes::CommandBuffer* buffer, const std::vector<NodeRef>& successors);
361 size_t m_frameIndex = 0;
362 };
363
364
365
366} // FCT
367
368#endif //COMMANDBUFFERGRAPH_H
virtual void updateSynchronization(uint32_t newMaxFrameInFlight)=0
EdgeBase(SemaphorePool *semaphorePool)
CommandBufferNodes::CommandBuffer * m_targetNode
void setSourceNode(CommandBufferNodes::InputFromWindow *source)
RHI::Semaphore * getImageAvailableSemaphore(uint32_t frameIndex) const
void setTargetNode(CommandBufferNodes::CommandBuffer *target)
CommandBufferNodes::CommandBuffer * getTargetNode() const
void updateSynchronization(uint32_t newMaxFrameInFlight) override
std::vector< RHI::Semaphore * > m_imageAvailable
CommandBufferNodes::InputFromWindow * getSourceNode() const
CommandBufferNodes::InputFromWindow * m_sourceNode
CommandBufferNodes::CommandBuffer * m_sourceNode
RHI::Fence * getFence(uint32_t frameIndex) const
void setTargetNode(CommandBufferNodes::OutputToWindow *target)
std::vector< RHI::Semaphore * > m_renderFinished
CommandBufferNodes::CommandBuffer * getSourceNode() const
RHI::Semaphore * getRenderFinishedSemaphore(uint32_t frameIndex) const
void setSourceNode(CommandBufferNodes::CommandBuffer *source)
void updateSynchronization(uint32_t newMaxFrameInFlight) override
CommandBufferNodes::OutputToWindow * m_targetNode
OutputToWindow(FencePool *fencePool, SemaphorePool *semaphorePool)
CommandBufferNodes::OutputToWindow * getTargetNode() const
void connectWindowPredecessor(CommandBufferNodes::CommandBuffer *buffer, Window *window)
void connectSuccessors(CommandBufferNodes::CommandBuffer *buffer, const std::vector< NodeRef > &successors)
std::unordered_set< CommandBufferNodes::NodeBase * > m_nodes
void connectPredecessors(CommandBufferNodes::CommandBuffer *buffer, const std::vector< NodeRef > &predecessors)
void removeBuffer(CommandBufferToken token)
void removeEdge(CommandBufferEdges::EdgeBase *edge)
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::unordered_map< Window *, CommandBufferNodes::OutputToWindow * > m_windowOutputNodes
CommandBufferNodes::InputFromWindow * getOrCreateWindowInputNode(Window *window)
void connectWindowSuccessor(CommandBufferNodes::CommandBuffer *buffer, Window *window)
std::unordered_set< std::unique_ptr< CommandBufferEdges::EdgeBase > > m_edges
std::vector< CommandBufferEdges::EdgeBase * > & getInputEdges()
std::vector< CommandBufferEdges::EdgeBase * > & getOutputEdges()
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
void removeOutputEdge(CommandBufferEdges::EdgeBase *edge) override
void removeInputEdge(CommandBufferEdges::EdgeBase *edge) 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
void removeOutputEdge(CommandBufferEdges::EdgeBase *edge) override
void addInputEdge(CommandBufferEdges::EdgeBase *edge) override
CommandBufferEdges::InputFromWindow * m_outputEdge
void addOutputEdge(CommandBufferEdges::EdgeBase *edge) override
void updateSynchronization(uint32_t newMaxFrameInFlight) override
std::vector< RHI::Semaphore * > m_collectedImageAvailable
RHI::Semaphore * getCollectedImageAvailableSemaphore(uint32_t frameIndex) const
virtual void removeOutputEdge(CommandBufferEdges::EdgeBase *edge)
virtual void fillAllSynchronization()
更新边的变化
virtual void updateSynchronization(uint32_t newMaxFrameInFlight)=0
virtual void addOutputEdge(CommandBufferEdges::EdgeBase *edge)
virtual void removeInputEdge(CommandBufferEdges::EdgeBase *edge)
virtual void fillSynchronization(uint32_t frameIndex)
virtual void addInputEdge(CommandBufferEdges::EdgeBase *edge)
void fillSynchronization(uint32_t frameIndex) override
std::vector< CommandBufferEdges::OutputToWindow * > m_inputEdges
void addOutputEdge(CommandBufferEdges::EdgeBase *edge) override
std::vector< RHI::Fence * > getCollectedFence(uint32_t frameIndex) const
void updateSynchronization(uint32_t newMaxFrameInFlight) override
void addInputEdge(CommandBufferEdges::EdgeBase *edge) override
void removeInputEdge(CommandBufferEdges::EdgeBase *edge) override
std::vector< std::vector< RHI::Semaphore * > > m_collectedRenderFinished
const std::vector< RHI::Semaphore * > & getCollectedRenderFinishedSemaphores(uint32_t frameIndex) const
const std::vector< RHI::Fence * > & getCollectedFences(uint32_t frameIndex) const
std::vector< std::vector< RHI::Fence * > > m_collectedFences
std::vector< RHI::Semaphore * > getCollectedRenderFinishedSemaphore(uint32_t frameIndex) const
CommandBufferNodes::CommandBuffer * CommandBufferToken
NodeRef(CommandBufferNodes::CommandBuffer *cb)
CommandBufferNodes::CommandBuffer * commandBuffer