FCT
载入中...
搜索中...
未找到
RenderGraph.cpp
浏览该文件的文档.
1#include "../UI/Window.h"
2#include "./Context.h"
3#include "./Context.hpp"
4#include "../RHI/PassGroup.h"
5
6namespace FCT
7{
9 {
10 return m_window->getCurrentTarget()->targetImage();
11 }
12
14 {
15 return m_window->getCurrentTarget()->depthStencilBuffer();
16 }
17
19 {
20 m_commandBufferToken = nullptr;
21 auto& submitGraph = m_flowControl->submitTickers();
22 submitGraph[RenderGraphTickers::RenderGraphSubmit] = {[this]()
23 {
24 auto cmdGraph = m_commandBufferGraph;
25 auto cmdBuf = cmdGraph->getCommandBuffer(m_commandBufferToken);
26 cmdBuf->reset();
27 cmdBuf->begin();
29 cmdBuf->end();
30 cmdBuf->submit();
31 },{},
33 };
34 submitGraph.update();
35 }
36
38 {
39 auto cmdGraph = m_commandBufferGraph;
40
42 {
48 }
49 std::vector<CommandBufferGraph::NodeRef> windowNodes;
50
51 for (const auto& [imageName, imageNode] : m_imageNodes) {
52 Window* window = nullptr;
53
54 auto* windowTargetNode = dynamic_cast<RenderGraphWindowTargetNode*>(imageNode.get());
55 if (windowTargetNode && windowTargetNode->isValidWindowTarget()) {
56 window = windowTargetNode->getWindow();
57 }
58
59 if (!window) {
60 auto* windowDepthNode = dynamic_cast<RenderGraphWindowDepthStencilNode*>(imageNode.get());
61 if (windowDepthNode && windowDepthNode->isValidWindowDepthStencil()) {
62 window = windowDepthNode->getWindow();
63 }
64 }
65
66 if (window) {
67 bool alreadyAdded = false;
68 for (const auto& node : windowNodes) {
69 if (node.type == CommandBufferGraph::NodeRef::WindowType && node.window == window) {
70 alreadyAdded = true;
71 break;
72 }
73 }
74 if (!alreadyAdded) {
75 windowNodes.emplace_back(window);
76 }
77 }
78 }
79
80 m_commandBufferToken = cmdGraph->addBuffer(windowNodes, windowNodes);
81 }
82
83 RenderGraph::RenderGraph(Device* device, FlowControl* flowControl, CommandBufferGraph* commandBufferGraph,
84 ResourceManager* resourceManager)
85 {
86 m_resourceDevice = device;
87 m_flowControl = flowControl;
88 m_commandBufferGraph = commandBufferGraph;
89 m_resourceManager = resourceManager;
91 }
92
93 RenderGraphImageNode* RenderGraph::getOrCreateImageNode(const std::string& name, const Texture& texture)
94 {
95 auto it = m_imageNodes.find(name);
96 if (it != m_imageNodes.end()) {
97 *(it->second) |= texture;
98 return it->second.get();
99 } else {
100 auto node = std::make_unique<RenderGraphBufferNode>(texture);
101 RenderGraphImageNode* nodePtr = node.get();
102 m_imageNodes[name] = std::move(node);
103 return nodePtr;
104 }
105 }
106
107 RenderGraphImageNode* RenderGraph::getOrCreateImageNode(const std::string& name, const Target& target)
108 {
109 auto it = m_imageNodes.find(name);
110 if (it != m_imageNodes.end()) {
111 *(it->second) |= target;
112 return it->second.get();
113 } else {
114 if (target.isWindow) {
115 auto node = std::make_unique<RenderGraphWindowTargetNode>(target);
116 RenderGraphImageNode* nodePtr = node.get();
117 m_imageNodes[name] = std::move(node);
118 return nodePtr;
119 } else {
120 auto node = std::make_unique<RenderGraphBufferNode>(target);
121 RenderGraphImageNode* nodePtr = node.get();
122 m_imageNodes[name] = std::move(node);
123 return nodePtr;
124 }
125 }
126 }
127
129 {
130 auto it = m_imageNodes.find(name);
131 if (it != m_imageNodes.end()) {
132 *(it->second) |= depthStencil;
133 return it->second.get();
134 } else {
135 if (depthStencil.isWindow) {
136 auto node = std::make_unique<RenderGraphWindowDepthStencilNode>(depthStencil);
137 RenderGraphImageNode* nodePtr = node.get();
138 m_imageNodes[name] = std::move(node);
139 return nodePtr;
140 } else {
141 auto node = std::make_unique<RenderGraphBufferNode>(depthStencil);
142 RenderGraphImageNode* nodePtr = node.get();
143 m_imageNodes[name] = std::move(node);
144 return nodePtr;
145 }
146 }
147 }
148
149 void RenderGraph::createTextureEdge(const std::string& passName, const std::string& textureName,
150 const Texture& texture)
151 {
152 auto& pass = m_passNodes[passName];
153
154 auto edge = std::make_unique<TextureEdge>();
155 edge->size = texture.size;
156 edge->fromImage = textureName;
157 edge->toPass = passName;
158 edge->stage = getEarliestStage(texture.stages);
159
160 TextureEdge* edgePtr = edge.get();
161
162 auto imageNodeIt = m_imageNodes.find(textureName);
163 if (imageNodeIt != m_imageNodes.end()) {
164 imageNodeIt->second->addOutgoingEdge(edgePtr);
165 }
166 pass.addIncomingEdge(edgePtr);
167
168 m_edges.push_back(std::move(edge));
169 }
170
171 void RenderGraph::createTargetEdge(const std::string& passName, const std::string& targetName, const Target& target)
172 {
173 auto& pass = m_passNodes[passName];
174
175 auto edge = std::make_unique<TargetEdge>();
176 edge->fromPass = passName;
177 edge->toImage = targetName;
178
179 TargetEdge* edgePtr = edge.get();
180
181 auto imageNodeIt = m_imageNodes.find(targetName);
182 if (imageNodeIt != m_imageNodes.end()) {
183 imageNodeIt->second->addIncomingEdge(edgePtr);
184 }
185 pass.addOutgoingEdge(edgePtr);
186
187 m_edges.push_back(std::move(edge));
188 }
189
190 void RenderGraph::createDepthStencilEdge(const std::string& passName, const std::string& depthStencilName,
192 {
193 auto& pass = m_passNodes[passName];
194
195 auto edge = std::make_unique<DepthStencilEdge>();
196 edge->fromPass = passName;
197 edge->toImage = depthStencilName;
198
199 DepthStencilEdge* edgePtr = edge.get();
200
201 auto imageNodeIt = m_imageNodes.find(depthStencilName);
202 if (imageNodeIt != m_imageNodes.end()) {
203 imageNodeIt->second->addIncomingEdge(edgePtr);
204 }
205 pass.addOutgoingEdge(edgePtr);
206
207 m_edges.push_back(std::move(edge));
208 }
209
211 {
212 m_passNodes[desc.name] = desc.name;
213 auto& pass = m_passNodes[desc.name];
214
215 pass.applyPassDesc(desc);
216
217 for (auto& texture : desc.textures)
218 {
219 getOrCreateImageNode(texture.name, texture);
220 createTextureEdge(desc.name, texture.name, texture);
221 }
222
223 std::vector<RenderGraphImageNode*> renderTargetNodes;
224
225 for (auto& target : desc.targets)
226 {
227 auto* node = getOrCreateImageNode(target.name, target);
228 renderTargetNodes.push_back(node);
229 createTargetEdge(desc.name, target.name, target);
230 }
231
232 for (auto& depthStencil : desc.depthStencils)
233 {
235 renderTargetNodes.push_back(node);
237 }
238
239 if (renderTargetNodes.size() > 1) {
240 RenderGraphImageNode* firstNode = renderTargetNodes[0];
241 for (size_t i = 1; i < renderTargetNodes.size(); ++i) {
242 firstNode->unite(renderTargetNodes[i]);
243 }
244 }
245 }
246
248 {
249
250 }
251
253 {
254 for (auto& [passName, pass] : m_passNodes) {
255 std::vector<RenderGraphImageNode*> referenceNodes;
256
257 for (auto* targetEdge : pass.getTargetOutgoingEdges()) {
258 auto imageNodeIt = m_imageNodes.find(targetEdge->toImage);
259 if (imageNodeIt != m_imageNodes.end()) {
260 referenceNodes.push_back(imageNodeIt->second.get());
261 }
262 }
263
264 for (auto* depthStencilEdge : pass.getDepthStencilOutgoingEdges()) {
265 auto imageNodeIt = m_imageNodes.find(depthStencilEdge->toImage);
266 if (imageNodeIt != m_imageNodes.end()) {
267 referenceNodes.push_back(imageNodeIt->second.get());
268 }
269 }
270
271 if (referenceNodes.empty()) {
272 continue;
273 }
274
275 RenderGraphImageNode* referenceNode = referenceNodes[0];
276
277 for (auto* textureEdge : pass.getTextureIncomingEdges()) {
278 auto imageNodeIt = m_imageNodes.find(textureEdge->fromImage);
279 if (imageNodeIt == m_imageNodes.end()) {
280 continue;
281 }
282
283 RenderGraphImageNode* textureNode = imageNodeIt->second.get();
284
285 if (textureEdge->size.type == TextureSize::Type::Undefined) {
286 if (!textureNode->isSizeDetermined()) {//
287 textureEdge->size = TextureSize(Fraction(),Fraction());
288 //textureNode->unite(referenceNode);
289 }
290 }
291 if (textureEdge->size.type == TextureSize::Type::Relative) {
292 FractionScale2D scale(textureEdge->size.relativeWidth, textureEdge->size.relativeHeight);
293 textureNode->unite(referenceNode, scale);
294 }
295 }
296 }
297 }
298
300 {
301 for (const auto& [passName, passNode] : m_passNodes) {
302 m_passesUnions.unite(passName, passName);
303 }
304
305 for (const auto& [passName, passNode] : m_passNodes) {
306 for (auto* textureEdge : passNode.getTextureIncomingEdges()) {
307 std::string imageName = textureEdge->fromImage;
308
309 auto imageIt = m_imageNodes.find(imageName);
310 if (imageIt == m_imageNodes.end()) continue;
311
312 RenderGraphImageNode* imageNode = imageIt->second.get();
313
314 RenderGraphImageNode* passRenderTarget = nullptr;
315
316 for (auto* targetEdge : passNode.getTargetOutgoingEdges()) {
317 auto targetIt = m_imageNodes.find(targetEdge->toImage);
318 if (targetIt != m_imageNodes.end()) {
319 passRenderTarget = targetIt->second.get();
320 break;
321 }
322 }
323
324 if (!passRenderTarget) {
325 for (auto* depthEdge : passNode.getDepthStencilOutgoingEdges()) {
326 auto depthIt = m_imageNodes.find(depthEdge->toImage);
327 if (depthIt != m_imageNodes.end()) {
328 passRenderTarget = depthIt->second.get();
329 break;
330 }
331 }
332 }
333
334 if (passRenderTarget && imageNode->isSameSize(passRenderTarget)) {
335 for (auto* targetEdge : imageNode->getTargetIncomingEdges()) {
336 m_passesUnions.unite(passName, targetEdge->fromPass);
337 }
338
339 for (auto* depthEdge : imageNode->getDepthStencilIncomingEdges()) {
340 m_passesUnions.unite(passName, depthEdge->fromPass);
341 }
342 }
343 }
344 }
345
346 for (const auto& [imageName, imageNode] : m_imageNodes) {
347 std::vector<std::string> targetPasses;
348 std::vector<std::string> depthStencilPasses;
349
350 for (auto* targetEdge : imageNode->getTargetIncomingEdges()) {
351 targetPasses.push_back(targetEdge->fromPass);
352 }
353
354 for (auto* depthEdge : imageNode->getDepthStencilIncomingEdges()) {
355 depthStencilPasses.push_back(depthEdge->fromPass);
356 }
357
358 for (size_t i = 1; i < targetPasses.size(); i++) {
359 m_passesUnions.unite(targetPasses[0], targetPasses[i]);
360 }
361
362 for (size_t i = 1; i < depthStencilPasses.size(); i++) {
363 m_passesUnions.unite(depthStencilPasses[0], depthStencilPasses[i]);
364 }
365
366 if (!targetPasses.empty() && !depthStencilPasses.empty()) {
367 m_passesUnions.unite(targetPasses[0], depthStencilPasses[0]);
368 }
369 }
370 }
371
372
373
375 {
376 for (auto& [name, imageNode] : m_imageNodes) {
377 imageNode->fillDefaultData();
378 }
379 auto* resourceManager = m_resourceManager;
380 if (!resourceManager) {
381 throw std::runtime_error("ResourceManager not available");
382 }
383
384 std::set<const SizeNode*> processedRoots;
385
386 for (auto& [name, imageNode] : m_imageNodes) {
387 auto* bufferNode = dynamic_cast<RenderGraphBufferNode*>(imageNode.get());
388 if (!bufferNode || !bufferNode->isFilled()) {
389 continue;
390 }
391
392 const SizeNode* root = bufferNode->getRoot();
393
394 if (root == bufferNode && processedRoots.find(root) == processedRoots.end()) {
395 processedRoots.insert(root);
396
397 uint32_t width, height;
398 bool hasFixedSize = bufferNode->getComputedSize(width, height);
399
400 if (hasFixedSize) {
401 TargetDesc targetDesc;
402 targetDesc.width = static_cast<int>(width);
403 targetDesc.height = static_cast<int>(height);
404 targetDesc.samples = bufferNode->getSamples();
405 targetDesc.format = bufferNode->getFormat();
406 targetDesc.usage = bufferNode->getUsage();
407
408 Image* allocatedImage = resourceManager->allocateTarget(name, targetDesc);
409 bufferNode->setAllocatedImage(allocatedImage); // 调用setAllocatedImage保存图像
410 m_allocatedImages[name] = allocatedImage; // 存储分配的图像
411 } else {
412 throw std::runtime_error("Root node has no fixed size: " + name);
413 }
414 }
415 }
416
417 for (auto& [name, imageNode] : m_imageNodes) {
418 auto* bufferNode = dynamic_cast<RenderGraphBufferNode*>(imageNode.get());
419 if (!bufferNode || !bufferNode->isFilled()) {
420 continue;
421 }
422
423 const SizeNode* root = bufferNode->getRoot();
424
425 if (root != bufferNode) {
426 ImageDesc imageDesc;
427 imageDesc.format = bufferNode->getFormat();
428 imageDesc.samples = bufferNode->getSamples();
429 imageDesc.usage = bufferNode->getUsage();
430
431 Image* allocatedImage = nullptr;
432
433 std::string dependencyName;
434 for (auto& [otherName, otherNode] : m_imageNodes) {
435 if (otherNode->getRoot() == root && otherNode->getRoot() == otherNode.get()) {
436 dependencyName = otherName;
437 break;
438 }
439 }
440
441 if (!dependencyName.empty()) {
442 auto* windowTargetNode = dynamic_cast<RenderGraphWindowTargetNode*>(
443 m_imageNodes[dependencyName].get());
444 auto* windowDepthNode = dynamic_cast<RenderGraphWindowDepthStencilNode*>(
445 m_imageNodes[dependencyName].get());
446
447 if (windowTargetNode && windowTargetNode->isValidWindowTarget()) {
448 allocatedImage = resourceManager->allocateImage(
449 name, windowTargetNode->getWindow(), imageDesc);
450 } else if (windowDepthNode && windowDepthNode->isValidWindowDepthStencil()) {
451 allocatedImage = resourceManager->allocateImage(
452 name, windowDepthNode->getWindow(), imageDesc);
453 } else {
454 allocatedImage = resourceManager->allocateImage(
455 name, dependencyName, imageDesc);
456 }
457
458 bufferNode->setAllocatedImage(allocatedImage);
459 m_allocatedImages[name] = allocatedImage;
460 } else {
461 throw std::runtime_error("Cannot determine dependency for image: " + name);
462 }
463 }
464 }
465 }
466
468 for (const auto& [passName, passNode] : m_passNodes) {
469 RHI::Pass* rhiPass = m_resourceDevice->createResource<RHI::Pass>();
470
471 const EnablePassClear& clearInfo = passNode.getClearInfo();
472 if (clearInfo.types) {
473 rhiPass->enableClear(clearInfo.types, clearInfo.color, clearInfo.depth, clearInfo.stencil);
474 }
475
476 const auto& targetEdges = passNode.getTargetOutgoingEdges();
477 for (size_t i = 0; i < targetEdges.size(); ++i) {
478 const auto& edge = targetEdges[i];
479 auto imageNodeIt = m_imageNodes.find(edge->toImage);
480 if (imageNodeIt != m_imageNodes.end()) {
481 Image* image = imageNodeIt->second->getImage();
482 if (image) {
483 rhiPass->bindTarget(static_cast<int>(i), image);
484 }
485 }
486 }
487
488 const auto& depthStencilEdges = passNode.getDepthStencilOutgoingEdges();
489 for (const auto& edge : depthStencilEdges) {
490 auto imageNodeIt = m_imageNodes.find(edge->toImage);
491 if (imageNodeIt != m_imageNodes.end()) {
492 Image* image = imageNodeIt->second->getImage();
493 if (image) {
494 rhiPass->depthStencil(image);
495 }
496 }
497 }
498
499 m_allocatedPasses[passName] = rhiPass;
500 }
501 }
503 const std::string& groupLeader,
504 const std::vector<std::string>& groupMembers,
505 std::map<std::string, std::set<std::string>>& dependencies
506) const {
507 if (dependencies.find(groupLeader) == dependencies.end()) {
508 dependencies[groupLeader] = std::set<std::string>();
509 }
510
511 for (const std::string& passName : groupMembers) {
512 auto passNodeIt = m_passNodes.find(passName);
513 if (passNodeIt == m_passNodes.end()) continue;
514
515 const auto& passNode = passNodeIt->second;
516
517 for (const auto* textureEdge : passNode.getTextureIncomingEdges()) {
518 auto imageNodeIt = m_imageNodes.find(textureEdge->fromImage);
519 if (imageNodeIt == m_imageNodes.end()) continue;
520
521 const auto& imageNode = imageNodeIt->second;
522
523 for (const auto* targetEdge : imageNode->getTargetIncomingEdges()) {
524 std::string producerPass = targetEdge->fromPass;
525
526 auto allGroups = m_passesUnions.getGroups();
527 for (const auto& [otherGroupLeader, otherGroupMembers] : allGroups) {
528 if (otherGroupLeader != groupLeader &&
529 std::find(otherGroupMembers.begin(), otherGroupMembers.end(), producerPass) != otherGroupMembers.end()) {
530 dependencies[groupLeader].insert(otherGroupLeader);
531 break;
532 }
533 }
534 }
535
536 for (const auto* depthEdge : imageNode->getDepthStencilIncomingEdges()) {
537 std::string producerPass = depthEdge->fromPass;
538
539 auto allGroups = m_passesUnions.getGroups();
540 for (const auto& [otherGroupLeader, otherGroupMembers] : allGroups) {
541 if (otherGroupLeader != groupLeader &&
542 std::find(otherGroupMembers.begin(), otherGroupMembers.end(), producerPass) != otherGroupMembers.end()) {
543 dependencies[groupLeader].insert(otherGroupLeader);
544 break;
545 }
546 }
547 }
548 }
549 }
550 }
551
552 std::vector<std::string> RenderGraph::topologicalSort(
553 const std::map<std::string, std::set<std::string>>& dependencies
554 ) const {
555 std::vector<std::string> result;
556 std::map<std::string, int> inDegree;
557 std::queue<std::string> queue;
558
559 for (const auto& [node, deps] : dependencies) {
560 inDegree[node] = 0;
561 }
562
563 for (const auto& [node, deps] : dependencies) {
564 for (const std::string& dep : deps) {
565 if (inDegree.find(dep) != inDegree.end()) {
566 inDegree[node]++;
567 }
568 }
569 }
570
571 for (const auto& [node, degree] : inDegree) {
572 if (degree == 0) {
573 queue.push(node);
574 }
575 }
576
577 while (!queue.empty()) {
578 std::string current = queue.front();
579 queue.pop();
580 result.push_back(current);
581
582 for (const auto& [node, deps] : dependencies) {
583 if (deps.find(current) != deps.end()) {
584 inDegree[node]--;
585 if (inDegree[node] == 0) {
586 queue.push(node);
587 }
588 }
589 }
590 }
591
592 if (result.size() != dependencies.size()) {
593 throw std::runtime_error("Circular dependency detected in PassGroups");
594 }
595
596 return result;
597 }
598
600 auto passGroups = m_passesUnions.getGroups();
601 std::map<std::string, std::set<std::string>> dependencies;
602
603 for (const auto& [groupLeader, groupMembers] : passGroups) {
604 analyzePassGroupDependencies(groupLeader, groupMembers, dependencies);
605 }
606
608
610 }
611
612
614 auto passGroups = m_passesUnions.getGroups();
615
616 for (const auto& [groupLeader, groupMembers] : passGroups) {
617 RHI::PassGroup* passGroup = m_resourceDevice->createResource<RHI::PassGroup>();
618
619 std::vector<std::string> orderedPassNames;
620
621 for (const std::string& passName : groupMembers) {
622 auto passIt = m_allocatedPasses.find(passName);
623 if (passIt == m_allocatedPasses.end()) continue;
624
625 RHI::Pass* currentPass = passIt->second;
626 std::vector<RHI::PassNeighbors> predecessors;
627 std::vector<RHI::PassNeighbors> successors;
628
629 auto passNodeIt = m_passNodes.find(passName);
630 if (passNodeIt != m_passNodes.end()) {
631 const auto& passNode = passNodeIt->second;
632
633 bool outputsToWindow = false;
634 //判断 target和depth是否窗口
635 for (const auto* targetEdge : passNode.getTargetOutgoingEdges()) {
636 auto imageNodeIt = m_imageNodes.find(targetEdge->toImage);
637 if (imageNodeIt != m_imageNodes.end()) {
638 auto* windowTargetNode = dynamic_cast<RenderGraphWindowTargetNode*>(
639 imageNodeIt->second.get());
640 if (windowTargetNode && windowTargetNode->isValidWindowTarget()) {
641 outputsToWindow = true;
642 break;
643 }
644 }
645 }
646
647 if (!outputsToWindow) {
648 for (const auto* depthEdge : passNode.getDepthStencilOutgoingEdges()) {
649 auto imageNodeIt = m_imageNodes.find(depthEdge->toImage);
650 if (imageNodeIt != m_imageNodes.end()) {
651 auto* windowDepthNode = dynamic_cast<RenderGraphWindowDepthStencilNode*>(
652 imageNodeIt->second.get());
653 if (windowDepthNode && windowDepthNode->isValidWindowDepthStencil()) {
654 outputsToWindow = true;
655 break;
656 }
657 }
658 }
659 }
660
661 if (outputsToWindow) {
662 successors.emplace_back(
664 );
665 }
666
667 for (const auto* textureEdge : passNode.getTextureIncomingEdges()) {
668 auto imageNodeIt = m_imageNodes.find(textureEdge->fromImage);
669 if (imageNodeIt != m_imageNodes.end()) {
670 const auto& imageNode = imageNodeIt->second;
671
672 // 检查Target边
673 for (const auto* targetEdge : imageNode->getTargetIncomingEdges()) {
674 if (std::find(groupMembers.begin(), groupMembers.end(), targetEdge->fromPass) != groupMembers.end()) {
675 auto predecessorPassIt = m_allocatedPasses.find(targetEdge->fromPass);
676 if (predecessorPassIt != m_allocatedPasses.end()) {
677 predecessors.emplace_back(
678 predecessorPassIt->second,
681 convertShaderStageToPipelineStage(textureEdge->stage),
683 );
684 }
685 }
686 }
687
688 // 检查DepthStencil边
689 for (const auto* depthEdge : imageNode->getDepthStencilIncomingEdges()) {
690 if (std::find(groupMembers.begin(), groupMembers.end(), depthEdge->fromPass) != groupMembers.end()) {
691 auto predecessorPassIt = m_allocatedPasses.find(depthEdge->fromPass);
692 if (predecessorPassIt != m_allocatedPasses.end()) {
693 predecessors.emplace_back(
694 predecessorPassIt->second,
697 convertShaderStageToPipelineStage(textureEdge->stage),
699 );
700 }
701 }
702 }
703 }
704 }
705 }
706
707 orderedPassNames.push_back(passName);
708
709 passGroup->addPass({
710 currentPass,
711 predecessors,
712 successors
713 });
714 }
715
716 m_passGroupOrders[groupLeader] = std::move(orderedPassNames);
717
718 passGroup->create();
719
720 m_allocatedPassGroups[groupLeader] = passGroup;
721 }
722 }
724 const std::string& groupLeader) {
725 auto passGroup = m_allocatedPassGroups.at(groupLeader);
726 auto orderIt = m_passGroupOrders.find(groupLeader);
727 if (orderIt == m_passGroupOrders.end()) {
728 return;
729 }
730
731 const std::vector<std::string>& orderedPassNames = orderIt->second;
732
733 passGroup->beginSubmit(cmdBuffer);
734
735 for (size_t i = 0; i < orderedPassNames.size(); ++i) {
736 const std::string& passName = orderedPassNames[i];
737
738 PassSubmitEvent env;
739 env.passName = passName;
740 env.cmdBuf = cmdBuffer;
741 trigger(env);
742
743 if (i < orderedPassNames.size() - 1) {
744 passGroup->nextPass(cmdBuffer);
745 }
746 }
747
748 passGroup->endSubmit(cmdBuffer);
749 }
751 auto passGroups = m_passesUnions.getGroups();
752 std::unordered_map<Image*, ImageState> imageStates;
753
754 for (const auto& [imageName, imageNode] : m_imageNodes) {
755 Image* image = imageNode->getImage();
756 if (image) {
757 imageStates[image] = ImageState{};
758 }
759 }
760
761 for (const std::string& groupLeader : m_passGroupExecutionOrder) {
762 auto groupIt = passGroups.find(groupLeader);
763 if (groupIt == passGroups.end()) continue;
764
765 const auto& groupMembers = groupIt->second;
766
767 std::vector<BarrierInfo> barriers = checkBarriersBeforePassGroup(groupLeader, groupMembers, imageStates);
768
769 if (!barriers.empty()) {
770 m_passGroupBarriers[groupLeader] = std::move(barriers);
771 }
772
773 simulatePassGroupExecution(groupLeader, groupMembers, imageStates);
774 }
775 }
776
777 std::vector<RenderGraph::BarrierInfo> RenderGraph::checkBarriersBeforePassGroup(
778 const std::string& groupLeader,
779 const std::vector<std::string>& groupMembers,
780 const std::unordered_map<Image*, ImageState>& imageStates) {
781
782 std::vector<BarrierInfo> barriers;
783 std::set<Image*> processedImages;
784
785 for (const std::string& passName : groupMembers) {
786 auto passIt = m_passNodes.find(passName);
787 if (passIt == m_passNodes.end()) continue;
788
789 const auto& passNode = passIt->second;
790
791 for (const auto* textureEdge : passNode.getTextureIncomingEdges()) {
792 auto imageNodeIt = m_imageNodes.find(textureEdge->fromImage);
793 if (imageNodeIt == m_imageNodes.end()) continue;
794
795 Image* image = imageNodeIt->second->getImage();
796 if (!image || processedImages.count(image)) continue;
797
798 auto stateIt = imageStates.find(image);
799 if (stateIt == imageStates.end()) continue;
800
801 const ImageState& currentState = stateIt->second;
802
803 PipelineStage requiredStage = convertShaderStageToPipelineStage(textureEdge->stage);
804 AccessFlag requiredAccess = AccessFlag::shaderRead;
806
807 bool needsBarrier = false;
808
809 if (currentState.currentLayout != requiredLayout &&
810 currentState.currentLayout != ImageLayout::undefined) {
811 needsBarrier = true;
812 }
813
814 if (!currentState.lastWriterGroup.empty() &&
815 currentState.lastWriterGroup != groupLeader &&
817 needsBarrier = true;
818 }
819
820 if (needsBarrier) {
821 BarrierInfo barrier;
822 barrier.image = image;
823 barrier.oldLayout = currentState.currentLayout;
824 barrier.newLayout = requiredLayout;
825 barrier.srcStage = currentState.lastStage;
826 barrier.dstStage = requiredStage;
827 barrier.srcAccess = currentState.lastAccess;
828 barrier.dstAccess = requiredAccess;
829
832 barrier.aspect = ImageAspect::depth;
833 } else {
834 barrier.aspect = ImageAspect::color;
835 }
836
837 barriers.push_back(barrier);
838 processedImages.insert(image);
839 }
840 }
841 }
842
843 return barriers;
844 }
845
847 const std::string& groupLeader,
848 const std::vector<std::string>& groupMembers,
849 std::unordered_map<Image*, ImageState>& imageStates) {
850
851 for (const std::string& passName : groupMembers) {
852 auto passIt = m_passNodes.find(passName);
853 if (passIt == m_passNodes.end()) continue;
854
855 const auto& passNode = passIt->second;
856
857 for (const auto* targetEdge : passNode.getTargetOutgoingEdges()) {
858 auto imageNodeIt = m_imageNodes.find(targetEdge->toImage);
859 if (imageNodeIt == m_imageNodes.end()) continue;
860
861 Image* image = imageNodeIt->second->getImage();
862 if (!image) continue;
863
864 ImageState& state = imageStates[image];
868 state.lastWriterGroup = groupLeader;
869 }
870
871 for (const auto* depthEdge : passNode.getDepthStencilOutgoingEdges()) {
872 auto imageNodeIt = m_imageNodes.find(depthEdge->toImage);
873 if (imageNodeIt == m_imageNodes.end()) continue;
874
875 Image* image = imageNodeIt->second->getImage();
876 if (!image) continue;
877
878 ImageState& state = imageStates[image];
882 state.lastWriterGroup = groupLeader;
883 }
884
885 for (const auto* textureEdge : passNode.getTextureIncomingEdges()) {
886 auto imageNodeIt = m_imageNodes.find(textureEdge->fromImage);
887 if (imageNodeIt == m_imageNodes.end()) continue;
888
889 Image* image = imageNodeIt->second->getImage();
890 if (!image) continue;
891
892 ImageState& state = imageStates[image];
895 state.lastStage = convertShaderStageToPipelineStage(textureEdge->stage);
897 }
898 }
899 }
900 }
913 void RenderGraph::executeBarriers(RHI::CommandBuffer* cmdBuffer, const std::vector<BarrierInfo>& barriers) {
914 for (const auto& barrier : barriers) {
915 cmdBuffer->barrier(
916 barrier.image,
917 barrier.oldLayout,
918 barrier.newLayout,
919 barrier.srcStage,
920 barrier.dstStage,
921 barrier.srcAccess,
922 barrier.dstAccess,
923 barrier.aspect
924 );
925 }
926 }
928 {
929 for (const std::string& groupLeader : m_passGroupExecutionOrder) {
930 auto barrierIt = m_passGroupBarriers.find(groupLeader);
931 if (barrierIt != m_passGroupBarriers.end()) {
932 executeBarriers(cmdBuffer, barrierIt->second);
933 }
934 submitPassGroup(cmdBuffer, groupLeader);
935 }
936 }
937
938 RHI::Pass* RenderGraph::getPass(const std::string& name) const
939 {
940 return m_allocatedPasses.at(name);
941 }
942
943 Image* RenderGraph::getImage(const std::string& name) const
944 {
945 auto imageNodeIt = m_imageNodes.find(name);
946 if (imageNodeIt!= m_imageNodes.end()) {
947 return imageNodeIt->second->getImage();
948 }
949 return nullptr;
950 }
951
952 std::vector<TextureEdge*> RenderGraph::getTextureEdges(const std::string& passName) const
953 {
954 auto passNodeIt = m_passNodes.find(passName);
955 if (passNodeIt!= m_passNodes.end()) {
956 return passNodeIt->second.getTextureIncomingEdges();
957 }
958 return {};
959 }
960
961}// FCT
virtual Image * getImage() const
定义 Image.h:70
virtual void barrier(FCT::Image *image, ImageLayout oldLayout, ImageLayout newLayout, PipelineStages srcStage, PipelineStages dstStage, AccessFlags srcAccess, AccessFlags dstAccess, ImageAspects aspectMask=ImageAspect::color)=0
void addPass(Pass *pass)
virtual void create()=0
void depthStencil(FCT::Image *depthStencil)
定义 Pass.h:40
static constexpr Pass * present
定义 Pass.h:25
void enableClear(ClearTypes type, Vec4 color, float depth=1.0f, uint8_t stencil=0)
定义 Pass.h:49
void bindTarget(uint32_t index, FCT::Image *target)
定义 Pass.h:32
void simulateExecutionAndAnalyzeBarriers()
void simulatePassGroupExecution(const std::string &groupLeader, const std::vector< std::string > &groupMembers, std::unordered_map< Image *, ImageState > &imageStates)
RenderGraph(Device *device, FlowControl *flowControl, CommandBufferGraph *commandBufferGraph, ResourceManager *resourceManager)
void createTextureEdge(const std::string &passName, const std::string &textureName, const Texture &texture)
std::unordered_map< std::string, Image * > m_allocatedImages
std::unordered_map< std::string, std::unique_ptr< RenderGraphImageNode > > m_imageNodes
FlowControl * m_flowControl
std::vector< TextureEdge * > getTextureEdges(const std::string &passName) const
RenderGraphImageNode * getOrCreateImageNode(const std::string &name, const Texture &texture)
void addPass(const PassDesc &desc)
void submitPassGroup(RHI::CommandBuffer *cmdBuffer, const std::string &groupLeader)
RHI::Pass * getPass(const std::string &name) const
void executeBarriers(RHI::CommandBuffer *cmdBuffer, const std::vector< BarrierInfo > &barriers)
CommandBufferGraph * m_commandBufferGraph
Image * getImage(const std::string &name) const
std::unordered_map< std::string, RHI::PassGroup * > m_allocatedPassGroups
std::unordered_map< std::string, RenderGraphPassNode > m_passNodes
ResourceManager * m_resourceManager
std::vector< std::string > m_passGroupExecutionOrder
std::vector< std::unique_ptr< Edge > > m_edges
UnionFind< std::string, char > m_passesUnions
std::unordered_map< std::string, std::vector< BarrierInfo > > m_passGroupBarriers
void executeAllPassGroups(RHI::CommandBuffer *cmdBuffer)
PipelineStage convertShaderStageToPipelineStage(ShaderStage stage) const
std::vector< std::string > topologicalSort(const std::map< std::string, std::set< std::string > > &dependencies) const
std::vector< BarrierInfo > checkBarriersBeforePassGroup(const std::string &groupLeader, const std::vector< std::string > &groupMembers, const std::unordered_map< Image *, ImageState > &imageStates)
std::unordered_map< std::string, RHI::Pass * > m_allocatedPasses
void createDepthStencilEdge(const std::string &passName, const std::string &depthStencilName, const DepthStencil &depthStencil)
void analyzePassGroupDependencies(const std::string &groupLeader, const std::vector< std::string > &groupMembers, std::map< std::string, std::set< std::string > > &dependencies) const
void createTargetEdge(const std::string &passName, const std::string &targetName, const Target &target)
std::unordered_map< std::string, std::vector< std::string > > m_passGroupOrders
CommandBufferToken m_commandBufferToken
const std::vector< TargetEdge * > & getTargetIncomingEdges() const
const std::vector< DepthStencilEdge * > & getDepthStencilIncomingEdges() const
Image * getImage() const override
constexpr const char * RenderGraphSubmit
constexpr const char * SwapBufferSubmitTicker
ShaderStage getEarliestStage(ShaderStages stages)
std::vector< Texture > textures
std::vector< Target > targets
std::vector< DepthStencil > depthStencils
RHI::CommandBuffer * cmdBuf
const SizeNode * getRoot() const noexcept
bool isSizeDetermined() const noexcept
bool isSameSize(const SizeNode *other) const noexcept
bool unite(SizeNode *other, const FractionScale2D &scale=FractionScale2D()) const noexcept