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;
121 virtual void updateSynchronization(uint32_t newMaxFrameInFlight) = 0;
124 virtual void fillSynchronization(uint32_t frameIndex) {}
125 virtual void fillAllSynchronization() {
126 for (uint32_t i = 0; i < m_frameDirty.size(); ++i) {
128 }
129 }
130 void markFrameDirty(uint32_t frameIndex) {
131 if (frameIndex < m_frameDirty.size()) {
132 m_frameDirty[frameIndex] = 1;
133 }
134 }
135
136 void markFrameClean(uint32_t frameIndex) {
137 if (frameIndex < m_frameDirty.size()) {
138 m_frameDirty[frameIndex] = 0;
139 }
140 }
141
143 std::fill(m_frameDirty.begin(), m_frameDirty.end(), 1);
144 }
145 protected:
146 std::vector<uint8_t> m_frameDirty;
147 };
148 class InputFromWindow : public NodeBase {
149 public:
150 InputFromWindow(Window* window) : m_window(window) {}
151 void updateSynchronization(uint32_t newMaxFrameInFlight) override
152 {
154 m_collectedImageAvailable.resize(newMaxFrameInFlight, nullptr);
155 m_frameDirty.clear();
156 m_frameDirty.resize(newMaxFrameInFlight, 1);
157 }
160 if (auto* inputEdge = dynamic_cast<CommandBufferEdges::InputFromWindow*>(edge)) {
161 if (m_outputEdge != nullptr) {
162 throw std::runtime_error("InputFromWindow node can only have one output edge");
163 }
164 m_outputEdge = inputEdge;
165 return;
166 }
167 throw std::runtime_error("InputFromWindow node can only accept InputFromWindow edge type");
168 }
169
172 throw std::runtime_error("InputFromWindow node cannot accept input edges");
173 }
174
175 void fillSynchronization(uint32_t frameIndex) override;
176
178 if (frameIndex < m_collectedImageAvailable.size()) {
179 return m_collectedImageAvailable[frameIndex];
180 }
181 return nullptr;
182 }
183 private:
186 std::vector<RHI::Semaphore*> m_collectedImageAvailable;
187 };
189 {
190 public:
191 OutputToWindow(Window* window) : m_window(window) {}
192 void updateSynchronization(uint32_t newMaxFrameInFlight) override {
193 m_collectedFences.clear();
194 m_collectedFences.resize(newMaxFrameInFlight);
196 m_collectedRenderFinished.resize(newMaxFrameInFlight);
197
198 m_frameDirty.clear();
199 m_frameDirty.resize(newMaxFrameInFlight, 1);
200 }
201
204 if (auto* outputEdge = dynamic_cast<CommandBufferEdges::OutputToWindow*>(edge)) {
205 m_inputEdges.push_back(outputEdge);
206 return;
207 }
208 throw std::runtime_error("OutputToWindow node can only accept OutputToWindow edge type");
209 }
210
213 throw std::runtime_error("OutputToWindow node cannot accept output edges");
214 }
215
216 std::vector<RHI::Fence*> getCollectedFence(uint32_t frameIndex) const;
217 std::vector<RHI::Semaphore*> getCollectedRenderFinishedSemaphore(uint32_t frameIndex) const;
218 void fillSynchronization(uint32_t frameIndex) override;
219
220 const std::vector<RHI::Fence*>& getCollectedFences(uint32_t frameIndex) const {
221 static const std::vector<RHI::Fence*> empty;
222 if (frameIndex < m_collectedFences.size()) {
223 return m_collectedFences[frameIndex];
224 }
225 return empty;
226 }
227
228 const std::vector<RHI::Semaphore*>& getCollectedRenderFinishedSemaphores(uint32_t frameIndex) const {
229 static const std::vector<RHI::Semaphore*> empty;
230 if (frameIndex < m_collectedRenderFinished.size()) {
231 return m_collectedRenderFinished[frameIndex];
232 }
233 return empty;
234 }
235
236 private:
238 std::vector<CommandBufferEdges::OutputToWindow*> m_inputEdges;
239 std::vector<std::vector<RHI::Fence*>> m_collectedFences; // 收集的每帧的所有fence
240 std::vector<std::vector<RHI::Semaphore*>> m_collectedRenderFinished; // 收集的每帧的所有renderFinished信号量
241 };
242
243 class CommandBuffer : public NodeBase
244 {
245 public:
247 void updateSynchronization(uint32_t newMaxFrameInFlight) override;
248 void addOutputEdge(CommandBufferEdges::EdgeBase* edge) override;
249 void addInputEdge(CommandBufferEdges::EdgeBase* edge) override;
250 RHI::CommandBuffer* getCommandBuffer(uint32_t frameIndex) const;
251 void fillSynchronization(uint32_t frameIndex) override;
252 private:
253 std::vector<CommandBufferEdges::EdgeBase*> m_outputEdges;
254 std::vector<CommandBufferEdges::EdgeBase*> m_inputEdges;
255 std::vector<RHI::CommandBuffer*> m_cmdBuffers;
257 };
258 }
261 {
262 private:
266
267 std::vector<std::unique_ptr<CommandBufferNodes::NodeBase>> m_nodes;
268 std::vector<std::unique_ptr<CommandBufferEdges::EdgeBase>> m_edges;
269
270 std::unordered_map<Window*, CommandBufferNodes::InputFromWindow*> m_windowInputNodes;
271 std::unordered_map<Window*, CommandBufferNodes::OutputToWindow*> m_windowOutputNodes;
272 std::set<Window*> m_windows;
273 uint32_t m_maxFrameInFlight = 0;
275
276 public:
277 CommandBufferGraph(Device* device);
294 const std::vector<NodeRef>& predecessors,
295 const std::vector<NodeRef>& successors);
296 void maxFrameInFlight(uint32_t max);
297 void swapBuffer();
299
300 private:
303 void connectPredecessors(CommandBufferNodes::CommandBuffer* buffer, const std::vector<NodeRef>& predecessors);
304 void connectSuccessors(CommandBufferNodes::CommandBuffer* buffer, const std::vector<NodeRef>& successors);
307 size_t m_frameIndex = 0;
308 };
309
310
311
312} // FCT
313
314#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::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
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 updateSynchronization(uint32_t newMaxFrameInFlight)=0
virtual void addOutputEdge(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
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