1use super::*;
2use super::{RenderGraphExternalImageId, RenderGraphImageSpecification};
3use crate::graph::graph_image::{PhysicalImageId, RenderGraphImageUser, VirtualImageId};
4use crate::graph::graph_node::RenderGraphNodeId;
5use crate::graph::{RenderGraphBuilder, RenderGraphImageConstraint, RenderGraphImageUsageId};
6use crate::render_features::RenderPhaseIndex;
7use crate::{BufferResource, GraphicsPipelineRenderTargetMeta};
8use crate::{ImageViewResource, ResourceArc};
9use fnv::{FnvHashMap, FnvHashSet};
10use rafx_api::{RafxFormat, RafxLoadOp, RafxResourceState, RafxSampleCount, RafxStoreOp};
11
12fn visit_node(
16 graph: &RenderGraphBuilder,
17 node_id: RenderGraphNodeId,
18 visited: &mut Vec<bool>,
19 visiting: &mut Vec<bool>,
20 visiting_stack: &mut Vec<RenderGraphNodeId>,
21 ordered_list: &mut Vec<RenderGraphNodeId>,
22) {
23 if visited[node_id.0] {
25 return;
26 }
27
28 if visiting[node_id.0] {
31 log::warn!("Found cycle in graph");
32 log::warn!("{:?}", graph.node(node_id));
33 for v in visiting_stack.iter().rev() {
34 log::warn!("{:?}", graph.node(*v));
35 }
36 panic!("Graph has a cycle");
37 }
38
39 visiting[node_id.0] = true;
42 visiting_stack.push(node_id);
43
44 let node = graph.node(node_id);
49
50 for read in &node.image_reads {
54 let upstream_node = graph.image_version_info(read.image).creator_node;
55 visit_node(
56 graph,
57 upstream_node,
58 visited,
59 visiting,
60 visiting_stack,
61 ordered_list,
62 );
63 }
64
65 for modify in &node.image_modifies {
66 let upstream_node = graph.image_version_info(modify.input).creator_node;
67 visit_node(
68 graph,
69 upstream_node,
70 visited,
71 visiting,
72 visiting_stack,
73 ordered_list,
74 );
75 }
76
77 for read in &node.buffer_reads {
78 let upstream_node = graph.buffer_version_info(read.buffer).creator_node;
79 visit_node(
80 graph,
81 upstream_node,
82 visited,
83 visiting,
84 visiting_stack,
85 ordered_list,
86 );
87 }
88
89 for modify in &node.buffer_modifies {
90 let upstream_node = graph.buffer_version_info(modify.input).creator_node;
91 visit_node(
92 graph,
93 upstream_node,
94 visited,
95 visiting,
96 visiting_stack,
97 ordered_list,
98 );
99 }
100
101 for &explicit_dependency in &node.explicit_dependencies {
102 visit_node(
103 graph,
104 explicit_dependency,
105 visited,
106 visiting,
107 visiting_stack,
108 ordered_list,
109 );
110 }
111
112 ordered_list.push(node_id);
115 visited[node_id.0] = true;
116
117 visiting_stack.pop();
120 visiting[node_id.0] = false;
121}
122
123#[profiling::function]
128fn determine_node_order(graph: &RenderGraphBuilder) -> Vec<RenderGraphNodeId> {
129 let mut visiting = vec![false; graph.nodes.len()];
132 let mut visiting_stack = Vec::default();
133
134 let mut visited = vec![false; graph.nodes.len()];
137 let mut ordered_list = Vec::default();
138
139 for external_image in &graph.external_images {
142 if let Some(output_usage) = external_image.output_usage {
143 let output_node = graph.image_version_info(output_usage).creator_node;
145 log::trace!(
146 "Traversing dependencies of output image created by node {:?} {:?}",
147 output_node,
148 graph.node(output_node).name()
149 );
150
151 visit_node(
152 graph,
153 output_node,
154 &mut visited,
155 &mut visiting,
156 &mut visiting_stack,
157 &mut ordered_list,
158 );
159 }
160 }
161
162 for external_buffer in &graph.external_buffers {
165 if let Some(output_usage) = external_buffer.output_usage {
166 let output_node = graph.buffer_version_info(output_usage).creator_node;
168 log::trace!(
169 "Traversing dependencies of output buffer created by node {:?} {:?}",
170 output_node,
171 graph.node(output_node).name()
172 );
173
174 visit_node(
175 graph,
176 output_node,
177 &mut visited,
178 &mut visiting,
179 &mut visiting_stack,
180 &mut ordered_list,
181 );
182 }
183 }
184
185 for node in &graph.nodes {
186 if !node.can_be_culled {
187 visit_node(
188 graph,
189 node.id(),
190 &mut visited,
191 &mut visiting,
192 &mut visiting_stack,
193 &mut ordered_list,
194 );
195 }
196 }
197
198 ordered_list
199}
200
201pub struct DetermineConstraintsResult {
203 images: FnvHashMap<RenderGraphImageUsageId, RenderGraphImageSpecification>,
204 buffers: FnvHashMap<RenderGraphBufferUsageId, RenderGraphBufferSpecification>,
205}
206
207impl DetermineConstraintsResult {
208 pub fn image_specification(
209 &self,
210 image: RenderGraphImageUsageId,
211 ) -> Option<&RenderGraphImageSpecification> {
212 self.images.get(&image)
213 }
214
215 pub fn buffer_specification(
216 &self,
217 buffer: RenderGraphBufferUsageId,
218 ) -> Option<&RenderGraphBufferSpecification> {
219 self.buffers.get(&buffer)
220 }
221}
222
223#[profiling::function]
233fn determine_constraints(
234 graph: &RenderGraphBuilder,
235 node_execution_order: &[RenderGraphNodeId],
236 swapchain_surface_info: &SwapchainSurfaceInfo,
237) -> DetermineConstraintsResult {
238 let mut image_version_states: FnvHashMap<RenderGraphImageUsageId, RenderGraphImageConstraint> =
239 Default::default();
240
241 let mut buffer_version_states: FnvHashMap<
242 RenderGraphBufferUsageId,
243 RenderGraphBufferConstraint,
244 > = Default::default();
245
246 log::trace!("Propagating constraints");
247
248 log::trace!(" Set up input images");
249
250 for external_image in &graph.external_images {
255 if let Some(input_usage) = external_image.input_usage {
256 log::trace!(
257 " Image {:?} {:?}",
258 input_usage,
259 graph.image_resource(input_usage).name
260 );
261 debug_assert_eq!(graph.image_version_create_usage(input_usage), input_usage);
262 image_version_states
263 .entry(input_usage)
264 .or_default()
265 .set(&external_image.specification);
266
267 }
269 }
270
271 log::trace!(" Set up input buffers");
272
273 for external_buffer in &graph.external_buffers {
278 if let Some(input_usage) = external_buffer.input_usage {
279 log::trace!(
280 " Buffer {:?} {:?}",
281 input_usage,
282 graph.buffer_resource(input_usage).name
283 );
284 debug_assert_eq!(graph.buffer_version_create_usage(input_usage), input_usage);
285 buffer_version_states
286 .entry(input_usage)
287 .or_default()
288 .set(&external_buffer.specification);
289
290 }
292 }
293
294 log::trace!(" Propagate constraints FORWARD");
295
296 for node_id in node_execution_order.iter() {
303 let node = graph.node(*node_id);
304 log::trace!(" node {:?} {:?}", node_id, node.name());
305
306 for image_create in &node.image_creates {
310 log::trace!(
319 " Create image {:?} {:?}",
320 image_create.image,
321 graph.image_resource(image_create.image).name
322 );
323
324 let version_state = image_version_states
325 .entry(graph.image_version_create_usage(image_create.image))
326 .or_default();
327
328 if !version_state.try_merge(&image_create.constraint) {
329 panic!("Unexpected constraints on image being created");
331 }
332
333 log::trace!(
334 " Forward propagate constraints {:?} {:?}",
335 image_create.image,
336 version_state
337 );
338
339 }
341
342 for buffer_create in &node.buffer_creates {
346 log::trace!(
355 " Create buffer {:?} {:?}",
356 buffer_create.buffer,
357 graph.buffer_resource(buffer_create.buffer).name
358 );
359
360 let version_state = buffer_version_states
361 .entry(graph.buffer_version_create_usage(buffer_create.buffer))
362 .or_default();
363
364 if !version_state.try_merge(&buffer_create.constraint) {
365 panic!("Unexpected constraints on buffer being created");
367 }
368
369 log::trace!(
370 " Forward propagate constraints {:?} {:?}",
371 buffer_create.buffer,
372 version_state
373 );
374
375 }
377
378 fn propagate_image_constraints_forward(
381 graph: &RenderGraphBuilder,
382 image_version_states: &mut FnvHashMap<
383 RenderGraphImageUsageId,
384 RenderGraphImageConstraint,
385 >,
386 input: RenderGraphImageUsageId,
387 output: RenderGraphImageUsageId,
388 constraint: &RenderGraphImageConstraint,
389 operation_name: &str,
390 ) {
391 log::trace!(
392 " {} image {:?} {:?} -> {:?} {:?}",
393 operation_name,
394 input,
395 graph.image_resource(input).name,
396 output,
397 graph.image_resource(output).name
398 );
399
400 let input_state = image_version_states
403 .entry(graph.image_version_create_usage(input))
404 .or_default();
405 let mut image_modify_constraint = constraint.clone();
406
407 image_modify_constraint.partial_merge(&input_state);
409
410 let output_state = image_version_states
411 .entry(graph.image_version_create_usage(output))
412 .or_default();
413
414 output_state.partial_merge(&image_modify_constraint);
416
417 log::trace!(" Forward propagate constraints {:?}", output_state);
418 }
419
420 fn propagate_buffer_constraints_forward(
421 graph: &RenderGraphBuilder,
422 buffer_version_states: &mut FnvHashMap<
423 RenderGraphBufferUsageId,
424 RenderGraphBufferConstraint,
425 >,
426 input: RenderGraphBufferUsageId,
427 output: RenderGraphBufferUsageId,
428 constraint: &RenderGraphBufferConstraint,
429 operation_name: &str,
430 ) {
431 log::trace!(
432 " {} buffer {:?} {:?} -> {:?} {:?}",
433 operation_name,
434 input,
435 graph.buffer_resource(input).name,
436 output,
437 graph.buffer_resource(output).name
438 );
439
440 let input_state = buffer_version_states
443 .entry(graph.buffer_version_create_usage(input))
444 .or_default();
445 let mut buffer_modify_constraint = constraint.clone();
446
447 buffer_modify_constraint.partial_merge(&input_state);
449
450 let output_state = buffer_version_states
451 .entry(graph.buffer_version_create_usage(output))
452 .or_default();
453
454 output_state.partial_merge(&buffer_modify_constraint);
456
457 log::trace!(" Forward propagate constraints {:?}", output_state);
458 }
459
460 for image_modify in &node.image_modifies {
464 propagate_image_constraints_forward(
465 graph,
466 &mut image_version_states,
467 image_modify.input,
468 image_modify.output,
469 &image_modify.constraint,
470 "Modify",
471 );
472 }
473
474 for image_modify in &node.image_copies {
475 propagate_image_constraints_forward(
476 graph,
477 &mut image_version_states,
478 image_modify.input,
479 image_modify.output,
480 &image_modify.constraint,
481 "Modify",
482 );
483 }
484
485 for buffer_modify in &node.buffer_modifies {
489 propagate_buffer_constraints_forward(
490 graph,
491 &mut buffer_version_states,
492 buffer_modify.input,
493 buffer_modify.output,
494 &buffer_modify.constraint,
495 "Modify",
496 );
497 }
498
499 for buffer_modify in &node.buffer_copies {
500 propagate_buffer_constraints_forward(
501 graph,
502 &mut buffer_version_states,
503 buffer_modify.input,
504 buffer_modify.output,
505 &buffer_modify.constraint,
506 "Modify",
507 );
508 }
509 }
510
511 log::trace!(" Set up output images");
512
513 for external_image in &graph.external_images {
517 if let Some(output_usage) = external_image.output_usage {
518 log::trace!(
519 " Image {:?} {:?}",
520 output_usage,
521 graph.image_resource(output_usage).name
522 );
523 let output_image_version_state = image_version_states
524 .entry(graph.image_version_create_usage(output_usage))
525 .or_default();
526 let output_constraint = external_image.specification.clone().into();
527 output_image_version_state.partial_merge(&output_constraint);
528
529 image_version_states.insert(output_usage, external_image.specification.clone().into());
530 }
531 }
532
533 for external_buffer in &graph.external_buffers {
537 if let Some(output_usage) = external_buffer.output_usage {
538 log::trace!(
539 " Buffer {:?} {:?}",
540 output_usage,
541 graph.buffer_resource(output_usage).name
542 );
543 let output_buffer_version_state = buffer_version_states
544 .entry(graph.buffer_version_create_usage(output_usage))
545 .or_default();
546 let output_constraint = external_buffer.specification.clone().into();
547 output_buffer_version_state.partial_merge(&output_constraint);
548
549 buffer_version_states
550 .insert(output_usage, external_buffer.specification.clone().into());
551 }
552 }
553
554 log::trace!(" Propagate constraints BACKWARD");
555
556 for node_id in node_execution_order.iter().rev() {
561 let node = graph.node(*node_id);
562 log::trace!(" node {:?} {:?}", node_id, node.name());
563
564 for image_read in &node.image_reads {
570 log::trace!(
571 " Read image {:?} {:?}",
572 image_read.image,
573 graph.image_resource(image_read.image).name
574 );
575
576 let version_state = image_version_states
577 .entry(graph.image_version_create_usage(image_read.image))
578 .or_default();
579 version_state.partial_merge(&image_read.constraint);
580
581 let mut image_read_constraint = image_read.constraint.clone();
587 image_read_constraint.partial_merge(&version_state);
588 log::trace!(
589 " Read constraints will be {:?}",
590 image_read_constraint
591 );
592 if let Some(spec) =
593 image_read_constraint.try_convert_to_specification(swapchain_surface_info)
594 {
595 image_version_states.insert(image_read.image, spec.into());
596 } else {
597 panic!(
598 "Not enough information in the graph to determine the specification for image {:?} {:?} being read by node {:?} {:?}. Constraints are: {:?}",
599 image_read.image,
600 graph.image_resource(image_read.image).name,
601 node.id(),
602 node.name(),
603 image_version_states.get(&image_read.image)
604 );
605 }
606 }
607
608 for buffer_read in &node.buffer_reads {
612 log::trace!(
613 " Read buffer {:?} {:?}",
614 buffer_read.buffer,
615 graph.buffer_resource(buffer_read.buffer).name
616 );
617
618 let version_state = buffer_version_states
619 .entry(graph.buffer_version_create_usage(buffer_read.buffer))
620 .or_default();
621 version_state.partial_merge(&buffer_read.constraint);
622
623 let mut buffer_read_constraint = buffer_read.constraint.clone();
629 buffer_read_constraint.partial_merge(&version_state);
630 log::trace!(
631 " Read constraints will be {:?}",
632 buffer_read_constraint
633 );
634 if let Some(spec) = buffer_read_constraint.try_convert_to_specification() {
635 buffer_version_states.insert(buffer_read.buffer, spec.into());
636 } else {
637 panic!(
638 "Not enough information in the graph to determine the specification for buffer {:?} {:?} being read by node {:?} {:?}. Constraints are: {:?}",
639 buffer_read.buffer,
640 graph.buffer_resource(buffer_read.buffer).name,
641 node.id(),
642 node.name(),
643 buffer_version_states.get(&buffer_read.buffer)
644 );
645 }
646 }
647
648 fn propagate_image_constraints_backward(
649 graph: &RenderGraphBuilder,
650 image_version_states: &mut FnvHashMap<
651 RenderGraphImageUsageId,
652 RenderGraphImageConstraint,
653 >,
654 input: RenderGraphImageUsageId,
655 output: RenderGraphImageUsageId,
656 operation_name: &str,
657 ) {
658 log::trace!(
659 " {} image {:?} {:?} <- {:?} {:?}",
660 operation_name,
661 input,
662 graph.image_resource(input).name,
663 output,
664 graph.image_resource(output).name
665 );
666 let output_image_constraint = image_version_states
669 .entry(graph.image_version_create_usage(output))
670 .or_default()
671 .clone();
672 let input_state = image_version_states
673 .entry(graph.image_version_create_usage(input))
674 .or_default();
675 input_state.partial_merge(&output_image_constraint);
676
677 image_version_states.insert(input, output_image_constraint.clone());
678 }
679
680 fn propagate_buffer_constraints_backward(
681 graph: &RenderGraphBuilder,
682 buffer_version_states: &mut FnvHashMap<
683 RenderGraphBufferUsageId,
684 RenderGraphBufferConstraint,
685 >,
686 input: RenderGraphBufferUsageId,
687 output: RenderGraphBufferUsageId,
688 operation_name: &str,
689 ) {
690 log::trace!(
691 " {} buffer {:?} {:?} <- {:?} {:?}",
692 operation_name,
693 input,
694 graph.buffer_resource(input).name,
695 output,
696 graph.buffer_resource(output).name
697 );
698 let output_buffer_constraint = buffer_version_states
701 .entry(graph.buffer_version_create_usage(output))
702 .or_default()
703 .clone();
704 let input_state = buffer_version_states
705 .entry(graph.buffer_version_create_usage(input))
706 .or_default();
707 input_state.partial_merge(&output_buffer_constraint);
708
709 buffer_version_states.insert(input, output_buffer_constraint.clone());
710 }
711
712 for image_modify in &node.image_modifies {
716 propagate_image_constraints_backward(
717 graph,
718 &mut image_version_states,
719 image_modify.input,
720 image_modify.output,
721 "Modify",
722 );
723 }
724
725 for image_copy in &node.image_copies {
726 propagate_image_constraints_backward(
727 graph,
728 &mut image_version_states,
729 image_copy.input,
730 image_copy.output,
731 "Copy",
732 );
733 }
734
735 for buffer_modify in &node.buffer_modifies {
736 propagate_buffer_constraints_backward(
737 graph,
738 &mut buffer_version_states,
739 buffer_modify.input,
740 buffer_modify.output,
741 "Modify",
742 );
743 }
744
745 for buffer_copy in &node.buffer_copies {
746 propagate_buffer_constraints_backward(
747 graph,
748 &mut buffer_version_states,
749 buffer_copy.input,
750 buffer_copy.output,
751 "Copy",
752 );
753 }
754 }
755
756 let mut image_specs = FnvHashMap::default();
757 for (k, v) in image_version_states {
758 image_specs.insert(
759 k,
760 v.try_convert_to_specification(swapchain_surface_info)
761 .unwrap(),
762 );
763 }
764
765 let mut buffer_specs = FnvHashMap::default();
766 for (k, v) in buffer_version_states {
767 buffer_specs.insert(k, v.try_convert_to_specification().unwrap());
768 }
769
770 DetermineConstraintsResult {
771 images: image_specs,
772 buffers: buffer_specs,
773 }
774}
775
776#[profiling::function]
782fn insert_resolves(
783 graph: &mut RenderGraphBuilder,
784 node_execution_order: &[RenderGraphNodeId],
785 constraint_results: &mut DetermineConstraintsResult,
786) {
787 log::trace!("Insert resolves in graph where necessary");
788 for node_id in node_execution_order {
789 let mut resolves_to_add = Vec::default();
790
791 let node = graph.node(*node_id);
792 log::trace!(" node {:?} {:?}", node_id, node.name);
793 for (color_attachment_index, color_attachment) in node.color_attachments.iter().enumerate()
795 {
796 if let Some(color_attachment) = color_attachment {
797 log::trace!(" color attachment {}", color_attachment_index);
798 if let Some(write_image) = color_attachment.write_image {
800 let write_spec = constraint_results.image_specification(write_image).unwrap();
803 if write_spec.samples == RafxSampleCount::SampleCount1 {
804 log::trace!(" already non-MSAA");
805 continue;
806 }
807
808 let mut resolve_spec = write_spec.clone();
810 resolve_spec.samples = RafxSampleCount::SampleCount1;
811
812 let mut usages_to_move = vec![];
813
814 for (usage_index, read_usage) in graph
816 .image_version_info(write_image)
817 .read_usages
818 .iter()
819 .enumerate()
820 {
821 log::trace!(
822 " usage {}, {:?} {:?}",
823 usage_index,
824 read_usage,
825 graph.image_usages[read_usage.0].usage_type
826 );
827 let read_spec =
828 constraint_results.image_specification(*read_usage).unwrap();
829 if *read_spec == *write_spec {
830 continue;
831 } else if *read_spec == resolve_spec {
832 usages_to_move.push(*read_usage);
833 } else {
834 log::trace!(
835 " incompatibility cannot be fixed via renderpass resolve"
836 );
837 log::trace!(" resolve: {:?}", resolve_spec);
838 log::trace!(" read : {:?}", read_spec);
839 }
840 }
841
842 if !usages_to_move.is_empty() {
843 resolves_to_add.push((
844 color_attachment_index,
845 resolve_spec,
846 usages_to_move,
847 ));
848 }
849 }
850 }
851 }
852
853 for (resolve_attachment_index, resolve_spec, usages_to_move) in resolves_to_add {
854 log::trace!(
855 " ADDING RESOLVE FOR NODE {:?} ATTACHMENT {}",
856 node_id,
857 resolve_attachment_index
858 );
859 let image = graph.create_resolve_attachment(
860 *node_id,
861 resolve_attachment_index,
862 resolve_spec.clone().into(),
863 Default::default(),
864 );
865 constraint_results.images.insert(image, resolve_spec);
866
867 for usage in usages_to_move {
868 let from = graph.image_usages[usage.0].version;
869 let to = graph.image_usages[image.0].version;
870 log::trace!(
871 " MOVE USAGE {:?} from {:?} to {:?}",
872 usage,
873 from,
874 to
875 );
876 graph.redirect_image_usage(usage, from, to)
877 }
878 }
879 }
880}
881
882#[derive(Debug)]
885pub struct AssignVirtualResourcesResult {
886 image_usage_to_virtual: FnvHashMap<RenderGraphImageUsageId, VirtualImageId>,
887 buffer_usage_to_virtual: FnvHashMap<RenderGraphBufferUsageId, VirtualBufferId>,
888}
889
890#[derive(Default)]
891struct VirtualImageIdAllocator {
892 next_id: usize,
893}
894
895impl VirtualImageIdAllocator {
896 fn allocate(&mut self) -> VirtualImageId {
897 let id = VirtualImageId(self.next_id);
898 self.next_id += 1;
899 id
900 }
901}
902
903#[derive(Default)]
904struct VirtualBufferIdAllocator {
905 next_id: usize,
906}
907
908impl VirtualBufferIdAllocator {
909 fn allocate(&mut self) -> VirtualBufferId {
910 let id = VirtualBufferId(self.next_id);
911 self.next_id += 1;
912 id
913 }
914}
915
916#[profiling::function]
924fn assign_virtual_resources(
925 graph: &RenderGraphBuilder,
926 node_execution_order: &[RenderGraphNodeId],
927 constraint_results: &mut DetermineConstraintsResult,
928) -> AssignVirtualResourcesResult {
929 let mut image_usage_to_virtual: FnvHashMap<RenderGraphImageUsageId, VirtualImageId> =
930 FnvHashMap::default();
931 let mut buffer_usage_to_virtual: FnvHashMap<RenderGraphBufferUsageId, VirtualBufferId> =
932 FnvHashMap::default();
933
934 let mut virtual_image_id_allocator = VirtualImageIdAllocator::default();
935 let mut virtual_buffer_id_allocator = VirtualBufferIdAllocator::default();
936
937 log::trace!("Associate input images with virtual images");
938 for external_image in &graph.external_images {
939 if let Some(input_usage) = external_image.input_usage {
940 let virtual_image = virtual_image_id_allocator.allocate();
942 log::trace!(
943 " External image {:?} used as input will use image {:?}",
944 input_usage,
945 virtual_image
946 );
947 image_usage_to_virtual.insert(input_usage, virtual_image);
948
949 propagate_virtual_image_id(
951 graph,
952 constraint_results,
953 &mut image_usage_to_virtual,
954 &mut virtual_image_id_allocator,
955 input_usage,
956 );
957 }
958 }
959
960 log::trace!("Associate input buffers with virtual buffers");
961 for external_buffer in &graph.external_buffers {
962 if let Some(input_usage) = external_buffer.input_usage {
963 let virtual_buffer = virtual_buffer_id_allocator.allocate();
965 log::trace!(
966 " External buffer {:?} used as input will use buffer {:?}",
967 external_buffer.external_buffer_id,
968 virtual_buffer
969 );
970 buffer_usage_to_virtual.insert(input_usage, virtual_buffer);
971
972 propagate_virtual_buffer_id(
974 graph,
975 constraint_results,
976 &mut buffer_usage_to_virtual,
977 &mut virtual_buffer_id_allocator,
978 input_usage,
979 );
980 }
981 }
982
983 log::trace!("Associate images written by nodes with virtual images");
985 for node in node_execution_order.iter() {
986 let node = graph.node(*node);
987 log::trace!(" node {:?} {:?}", node.id().0, node.name());
988
989 for image_create in &node.image_creates {
997 let virtual_image = virtual_image_id_allocator.allocate();
1000 log::trace!(
1001 " Create {:?} will use image {:?}",
1002 image_create.image,
1003 virtual_image
1004 );
1005 image_usage_to_virtual.insert(image_create.image, virtual_image);
1006 propagate_virtual_image_id(
1008 graph,
1009 constraint_results,
1010 &mut image_usage_to_virtual,
1011 &mut virtual_image_id_allocator,
1012 image_create.image,
1013 );
1014 }
1015
1016 for buffer_create in &node.buffer_creates {
1020 let virtual_buffer = virtual_buffer_id_allocator.allocate();
1023 log::trace!(
1024 " Create {:?} will use buffer {:?}",
1025 buffer_create.buffer,
1026 virtual_buffer
1027 );
1028 buffer_usage_to_virtual.insert(buffer_create.buffer, virtual_buffer);
1029 propagate_virtual_buffer_id(
1031 graph,
1032 constraint_results,
1033 &mut buffer_usage_to_virtual,
1034 &mut virtual_buffer_id_allocator,
1035 buffer_create.buffer,
1036 );
1037 }
1038
1039 for image_modify in &node.image_modifies {
1043 assert_eq!(
1046 constraint_results.image_specification(image_modify.input),
1047 constraint_results.image_specification(image_modify.output)
1048 );
1049
1050 let virtual_image = *image_usage_to_virtual.get(&image_modify.input).unwrap();
1052 log::trace!(
1053 " Modify {:?} will pass through image {:?}",
1054 image_modify.output,
1055 virtual_image
1056 );
1057 image_usage_to_virtual.insert(image_modify.output, virtual_image);
1058
1059 propagate_virtual_image_id(
1061 graph,
1062 constraint_results,
1063 &mut image_usage_to_virtual,
1064 &mut virtual_image_id_allocator,
1065 image_modify.output,
1066 );
1067 }
1068
1069 for buffer_modify in &node.buffer_modifies {
1073 assert_eq!(
1076 constraint_results.buffer_specification(buffer_modify.input),
1077 constraint_results.buffer_specification(buffer_modify.output)
1078 );
1079
1080 let virtual_buffer = *buffer_usage_to_virtual.get(&buffer_modify.input).unwrap();
1082 log::trace!(
1083 " Modify {:?} will pass through buffer {:?}",
1084 buffer_modify.output,
1085 virtual_buffer
1086 );
1087 buffer_usage_to_virtual.insert(buffer_modify.output, virtual_buffer);
1088
1089 propagate_virtual_buffer_id(
1091 graph,
1092 constraint_results,
1093 &mut buffer_usage_to_virtual,
1094 &mut virtual_buffer_id_allocator,
1095 buffer_modify.output,
1096 );
1097 }
1098 }
1099
1100 AssignVirtualResourcesResult {
1102 image_usage_to_virtual,
1103 buffer_usage_to_virtual,
1104 }
1105}
1106
1107fn propagate_virtual_image_id(
1108 graph: &RenderGraphBuilder,
1109 constraint_results: &DetermineConstraintsResult,
1110 image_usage_to_virtual: &mut FnvHashMap<RenderGraphImageUsageId, VirtualImageId>,
1111 virtual_image_id_allocator: &mut VirtualImageIdAllocator,
1112 written_image: RenderGraphImageUsageId,
1113) {
1114 let written_image_version_info = graph.image_version_info(written_image);
1129 let mut read_count = 0;
1130 let mut write_count = 0;
1132 for usage in &written_image_version_info.read_usages {
1134 if graph.image_usages[usage.0].usage_type.is_read_only() {
1135 read_count += 1;
1136 } else {
1138 write_count += 1;
1139 }
1141 }
1142
1143 let write_virtual_image = *image_usage_to_virtual.get(&written_image).unwrap();
1151 let write_type = graph.image_usages[written_image.0].usage_type;
1152
1153 let written_spec = constraint_results
1154 .image_specification(written_image)
1155 .unwrap();
1156
1157 for usage_resource_id in &written_image_version_info.read_usages {
1158 let usage_spec = match constraint_results.image_specification(*usage_resource_id) {
1159 Some(usage_spec) => usage_spec,
1160 None => continue,
1163 };
1164
1165 let specifications_compatible =
1167 RenderGraphImageSpecification::specifications_are_compatible(written_spec, usage_spec);
1168
1169 let is_read_or_exclusive_write = (read_count > 0
1171 && graph.image_usages[usage_resource_id.0]
1172 .usage_type
1173 .is_read_only())
1174 || write_count <= 1;
1175
1176 let read_type = graph.image_usages[usage_resource_id.0].usage_type;
1177 if specifications_compatible && is_read_or_exclusive_write {
1178 log::trace!(
1180 " Usage {:?} will share an image with {:?} ({:?} -> {:?})",
1181 written_image,
1182 usage_resource_id,
1183 write_type,
1184 read_type
1185 );
1186 let overwritten_image =
1187 image_usage_to_virtual.insert(*usage_resource_id, write_virtual_image);
1188
1189 assert!(overwritten_image.is_none());
1190 } else {
1191 let virtual_image = virtual_image_id_allocator.allocate();
1193 log::info!(
1194 " Allocate image {:?} for {:?} ({:?} -> {:?}) (specifications_compatible match: {} is_read_or_exclusive_write: {})",
1195 virtual_image,
1196 usage_resource_id,
1197 write_type,
1198 read_type,
1199 specifications_compatible,
1200 is_read_or_exclusive_write
1201 );
1202 let overwritten_image =
1203 image_usage_to_virtual.insert(*usage_resource_id, virtual_image);
1204
1205 assert!(overwritten_image.is_none());
1206
1207 log::info!(
1211 " writer : {}",
1212 graph.debug_user_name_of_image_usage(written_image)
1213 );
1214 log::info!(
1215 " reader : {}",
1216 graph.debug_user_name_of_image_usage(*usage_resource_id)
1217 );
1218
1219 if !specifications_compatible {
1220 log::info!(" writer spec: {:?}", written_spec);
1221 log::info!(" reader spec: {:?}", usage_spec);
1222 }
1223 log::info!(" --- All Usages ---");
1224 log::info!(
1225 " Creator: {} spec: {:?}",
1226 graph.debug_user_name_of_image_usage(written_image),
1227 constraint_results.image_specification(written_image)
1228 );
1229 for &read_usage in &written_image_version_info.read_usages {
1230 log::info!(
1231 " Reader: {} spec: {:?}",
1232 graph.debug_user_name_of_image_usage(read_usage),
1233 constraint_results.image_specification(read_usage)
1234 );
1235 }
1236
1237 panic!("The render graph contains an image conflict that cannot be automatically resolved.");
1238 }
1239 }
1240}
1241
1242fn propagate_virtual_buffer_id(
1243 graph: &RenderGraphBuilder,
1244 constraint_results: &DetermineConstraintsResult,
1245 buffer_usage_to_virtual: &mut FnvHashMap<RenderGraphBufferUsageId, VirtualBufferId>,
1246 virtual_buffer_id_allocator: &mut VirtualBufferIdAllocator,
1247 written_buffer: RenderGraphBufferUsageId,
1248) {
1249 let written_buffer_version_info = graph.buffer_version_info(written_buffer);
1260 let mut read_count = 0;
1261 let mut write_count = 0;
1262 for usage in &written_buffer_version_info.read_usages {
1263 if graph.buffer_usages[usage.0].usage_type.is_read_only() {
1264 read_count += 1;
1265 } else {
1266 write_count += 1;
1267 }
1268 }
1269
1270 let write_virtual_buffer = *buffer_usage_to_virtual.get(&written_buffer).unwrap();
1271 let write_type = graph.buffer_usages[written_buffer.0].usage_type;
1272
1273 let written_spec = constraint_results
1274 .buffer_specification(written_buffer)
1275 .unwrap();
1276
1277 for usage_resource_id in &written_buffer_version_info.read_usages {
1278 let usage_spec = match constraint_results.buffer_specification(*usage_resource_id) {
1279 Some(usage_spec) => usage_spec,
1280 None => continue,
1283 };
1284
1285 let specifications_compatible =
1287 RenderGraphBufferSpecification::specifications_are_compatible(written_spec, usage_spec);
1288
1289 let is_read_or_exclusive_write = (read_count > 0
1291 && graph.buffer_usages[usage_resource_id.0]
1292 .usage_type
1293 .is_read_only())
1294 || write_count <= 1;
1295
1296 let read_type = graph.buffer_usages[usage_resource_id.0].usage_type;
1297 if specifications_compatible && is_read_or_exclusive_write {
1298 log::trace!(
1300 " Usage {:?} will share a buffer with {:?} ({:?} -> {:?})",
1301 written_buffer,
1302 usage_resource_id,
1303 write_type,
1304 read_type
1305 );
1306 let overwritten_buffer =
1307 buffer_usage_to_virtual.insert(*usage_resource_id, write_virtual_buffer);
1308
1309 assert!(overwritten_buffer.is_none());
1310 } else {
1311 let virtual_buffer = virtual_buffer_id_allocator.allocate();
1313 log::info!(
1314 " Allocate buffer {:?} for {:?} ({:?} -> {:?}) (specifications_compatible match: {} is_read_or_exclusive_write: {})",
1315 virtual_buffer,
1316 usage_resource_id,
1317 write_type,
1318 read_type,
1319 specifications_compatible,
1320 is_read_or_exclusive_write
1321 );
1322
1323 let overwritten_buffer =
1324 buffer_usage_to_virtual.insert(*usage_resource_id, virtual_buffer);
1325
1326 assert!(overwritten_buffer.is_none());
1327
1328 log::info!(
1332 " writer : {}",
1333 graph.debug_user_name_of_buffer_usage(written_buffer)
1334 );
1335 log::info!(
1336 " reader : {}",
1337 graph.debug_user_name_of_buffer_usage(*usage_resource_id)
1338 );
1339
1340 if !specifications_compatible {
1341 log::info!(" writer spec: {:?}", written_spec);
1342 log::info!(" reader spec: {:?}", usage_spec);
1343 }
1344 log::info!(" --- All Usages ---");
1345 log::info!(
1346 " Creator: {} spec {:?}",
1347 graph.debug_user_name_of_buffer_usage(written_buffer),
1348 constraint_results.buffer_specification(written_buffer)
1349 );
1350 for &read_usage in &written_buffer_version_info.read_usages {
1351 log::info!(
1352 " Reader: {} spec {:?}",
1353 graph.debug_user_name_of_buffer_usage(read_usage),
1354 constraint_results.buffer_specification(read_usage)
1355 );
1356 }
1357
1358 panic!("The render graph contains a buffer conflict that cannot be automatically resolved.");
1359 }
1360 }
1361}
1362
1363#[profiling::function]
1369fn build_physical_passes(
1370 graph: &RenderGraphBuilder,
1371 node_execution_order: &[RenderGraphNodeId],
1372 constraints: &DetermineConstraintsResult,
1373 virtual_resources: &AssignVirtualResourcesResult,
1374) -> Vec<RenderGraphPass> {
1375 #[derive(Debug)]
1376 enum PassNode {
1377 RenderpassNode(RenderGraphNodeId),
1378 CallbackNode(RenderGraphNodeId),
1379 }
1380
1381 let mut pass_nodes = Vec::default();
1383
1384 for node_id in node_execution_order {
1385 let pass_node = match graph.node(*node_id).kind {
1386 RenderGraphNodeKind::Renderpass => PassNode::RenderpassNode(*node_id),
1387 RenderGraphNodeKind::Callback => PassNode::CallbackNode(*node_id),
1388 };
1389 pass_nodes.push(pass_node);
1390 }
1391
1392 log::trace!("gather pass info");
1393 let mut passes = Vec::default();
1394 for pass_node in pass_nodes {
1395 log::trace!(" nodes in pass: {:?}", pass_node);
1396
1397 fn find_or_insert_attachment(
1398 attachments: &mut Vec<RenderGraphPassAttachment>,
1399 usage: RenderGraphImageUsageId,
1400 virtual_image: VirtualImageId,
1401 ) -> (usize, bool) {
1402 if let Some(position) = attachments
1403 .iter()
1404 .position(|x| x.virtual_image == virtual_image)
1405 {
1406 (position, false)
1407 } else {
1408 attachments.push(RenderGraphPassAttachment {
1409 usage,
1410 virtual_image,
1411
1412 image: None,
1414 image_view: None,
1415
1416 load_op: RafxLoadOp::DontCare,
1417 stencil_load_op: RafxLoadOp::DontCare,
1418 store_op: RafxStoreOp::DontCare,
1419 stencil_store_op: RafxStoreOp::DontCare,
1420 clear_color: None,
1421 format: RafxFormat::UNDEFINED,
1422 samples: RafxSampleCount::SampleCount1,
1423
1424 initial_state: RafxResourceState::UNDEFINED,
1426 final_state: RafxResourceState::UNDEFINED,
1427 });
1428 (attachments.len() - 1, true)
1429 }
1430 }
1431
1432 match pass_node {
1433 PassNode::CallbackNode(compute_node) => {
1434 passes.push(RenderGraphPass::Callback(RenderGraphCallbackPass {
1435 node: compute_node,
1436 pre_pass_barrier: Default::default(),
1437 }));
1438 }
1439 PassNode::RenderpassNode(renderpass_node) => {
1440 let mut renderpass_attachments = Vec::default();
1441
1442 log::trace!(" subpass node: {:?}", renderpass_node);
1443 let subpass_node = graph.node(renderpass_node);
1444
1445 if subpass_node.color_attachments.is_empty()
1447 && subpass_node.depth_attachment.is_none()
1448 {
1449 assert!(subpass_node.resolve_attachments.is_empty());
1450 log::trace!(" Not generating a subpass - no attachments");
1451 continue;
1452 }
1453
1454 let mut pass_color_attachments: [Option<usize>; MAX_COLOR_ATTACHMENTS] =
1455 Default::default();
1456 let mut pass_resolve_attachments: [Option<usize>; MAX_COLOR_ATTACHMENTS] =
1457 Default::default();
1458 let mut pass_depth_attachment = Default::default();
1459
1460 for (color_attachment_index, color_attachment) in
1461 subpass_node.color_attachments.iter().enumerate()
1462 {
1463 if let Some(color_attachment) = color_attachment {
1464 let read_or_write_usage = color_attachment
1465 .read_image
1466 .or(color_attachment.write_image)
1467 .unwrap();
1468 let virtual_image = virtual_resources
1469 .image_usage_to_virtual
1470 .get(&read_or_write_usage)
1471 .unwrap();
1472
1473 let specification = constraints.images.get(&read_or_write_usage).unwrap();
1474 log::trace!(" virtual attachment (color): {:?}", virtual_image);
1475
1476 let (pass_attachment_index, is_first_usage) = find_or_insert_attachment(
1477 &mut renderpass_attachments,
1478 read_or_write_usage,
1479 *virtual_image, );
1481 pass_color_attachments[color_attachment_index] =
1482 Some(pass_attachment_index);
1483
1484 let attachment = &mut renderpass_attachments[pass_attachment_index];
1485 if is_first_usage {
1486 if color_attachment.clear_color_value.is_some() {
1488 attachment.load_op = RafxLoadOp::Clear;
1489 attachment.clear_color = Some(AttachmentClearValue::Color(
1490 color_attachment.clear_color_value.unwrap(),
1491 ))
1492 } else if color_attachment.read_image.is_some() {
1493 attachment.load_op = RafxLoadOp::Load;
1494 }
1495
1496 attachment.format = specification.format.into();
1497 attachment.samples = specification.samples.into();
1498 };
1499
1500 let store_op = if let Some(write_image) = color_attachment.write_image {
1501 if !graph.image_version_info(write_image).read_usages.is_empty() {
1502 RafxStoreOp::Store
1503 } else {
1504 RafxStoreOp::DontCare
1505 }
1506 } else {
1507 RafxStoreOp::DontCare
1508 };
1509
1510 attachment.store_op = store_op;
1511 attachment.stencil_store_op = RafxStoreOp::DontCare;
1512 }
1513 }
1514
1515 for (resolve_attachment_index, resolve_attachment) in
1516 subpass_node.resolve_attachments.iter().enumerate()
1517 {
1518 if let Some(resolve_attachment) = resolve_attachment {
1519 let write_image = resolve_attachment.write_image;
1520 let virtual_image = virtual_resources
1521 .image_usage_to_virtual
1522 .get(&write_image)
1523 .unwrap();
1524 let specification = constraints.images.get(&write_image).unwrap();
1526 log::trace!(" virtual attachment (resolve): {:?}", virtual_image);
1527
1528 let (pass_attachment_index, is_first_usage) = find_or_insert_attachment(
1529 &mut renderpass_attachments,
1530 write_image,
1531 *virtual_image, );
1533 pass_resolve_attachments[resolve_attachment_index] =
1534 Some(pass_attachment_index);
1535
1536 assert!(is_first_usage); let attachment = &mut renderpass_attachments[pass_attachment_index];
1538 attachment.format = specification.format.into();
1539 attachment.samples = specification.samples.into();
1540
1541 let store_op =
1543 if !graph.image_version_info(write_image).read_usages.is_empty() {
1544 RafxStoreOp::Store
1545 } else {
1546 RafxStoreOp::DontCare
1547 };
1548
1549 attachment.store_op = store_op;
1550 attachment.stencil_store_op = RafxStoreOp::DontCare;
1551 }
1552 }
1553
1554 if let Some(depth_attachment) = &subpass_node.depth_attachment {
1555 let read_or_write_usage = depth_attachment
1556 .read_image
1557 .or(depth_attachment.write_image)
1558 .unwrap();
1559 let virtual_image = virtual_resources
1560 .image_usage_to_virtual
1561 .get(&read_or_write_usage)
1562 .unwrap();
1563 let specification = constraints.images.get(&read_or_write_usage).unwrap();
1564 log::trace!(" virtual attachment (depth): {:?}", virtual_image);
1565
1566 let (pass_attachment_index, is_first_usage) = find_or_insert_attachment(
1567 &mut renderpass_attachments,
1568 read_or_write_usage,
1569 *virtual_image, );
1571 pass_depth_attachment = Some(pass_attachment_index);
1572
1573 let attachment = &mut renderpass_attachments[pass_attachment_index];
1574 if is_first_usage {
1575 if depth_attachment.clear_depth_stencil_value.is_some() {
1579 if depth_attachment.has_depth {
1580 attachment.load_op = RafxLoadOp::Clear;
1581 }
1582 if depth_attachment.has_stencil {
1583 attachment.stencil_load_op = RafxLoadOp::Clear;
1584 }
1585 attachment.clear_color = Some(AttachmentClearValue::DepthStencil(
1586 depth_attachment.clear_depth_stencil_value.unwrap(),
1587 ));
1588 } else if depth_attachment.read_image.is_some() {
1589 if depth_attachment.has_depth {
1590 attachment.load_op = RafxLoadOp::Load;
1591 }
1592
1593 if depth_attachment.has_stencil {
1594 attachment.stencil_load_op = RafxLoadOp::Load;
1595 }
1596 }
1597
1598 attachment.format = specification.format.into();
1599 attachment.samples = specification.samples.into();
1600 };
1601
1602 let store_op = if let Some(write_image) = depth_attachment.write_image {
1603 if !graph.image_version_info(write_image).read_usages.is_empty() {
1604 RafxStoreOp::Store
1605 } else {
1606 RafxStoreOp::DontCare
1607 }
1608 } else {
1609 RafxStoreOp::DontCare
1610 };
1611
1612 if depth_attachment.has_depth {
1613 attachment.store_op = store_op;
1614 }
1615
1616 if depth_attachment.has_stencil {
1617 attachment.stencil_store_op = store_op;
1618 }
1619 }
1620
1621 passes.push(RenderGraphPass::Render(RenderGraphRenderPass {
1622 node_id: renderpass_node,
1623 attachments: renderpass_attachments,
1624 color_attachments: pass_color_attachments,
1625 depth_attachment: pass_depth_attachment,
1626 resolve_attachments: pass_resolve_attachments,
1627 pre_pass_barrier: None,
1628 }));
1629 }
1630 }
1631 }
1632
1633 passes
1634}
1635
1636#[derive(Debug)]
1637struct AssignPhysicalResourcesResult {
1638 image_usage_to_physical: FnvHashMap<RenderGraphImageUsageId, PhysicalImageId>,
1639 image_usage_to_image_view: FnvHashMap<RenderGraphImageUsageId, PhysicalImageViewId>,
1640 image_views: Vec<RenderGraphImageView>, #[allow(unused)]
1642 image_virtual_to_physical: FnvHashMap<VirtualImageId, PhysicalImageId>,
1643 image_specifications: Vec<RenderGraphImageSpecification>, #[allow(unused)]
1646 buffer_usage_to_physical: FnvHashMap<RenderGraphBufferUsageId, PhysicalBufferId>,
1647 #[allow(unused)]
1648 buffer_virtual_to_physical: FnvHashMap<VirtualBufferId, PhysicalBufferId>,
1649 buffer_specifications: Vec<RenderGraphBufferSpecification>, }
1651
1652#[profiling::function]
1659fn assign_physical_resources(
1660 graph: &RenderGraphBuilder,
1661 constraints: &DetermineConstraintsResult,
1662 virtual_resources: &AssignVirtualResourcesResult,
1663 passes: &mut [RenderGraphPass],
1664) -> AssignPhysicalResourcesResult {
1665 log::trace!("-- Assign physical resources --");
1666 struct PhysicalImageReuseRequirements {
1667 virtual_id: VirtualImageId,
1668 specification: RenderGraphImageSpecification,
1669 first_node_pass_index: usize,
1670 last_node_pass_index: usize,
1671 }
1672
1673 struct PhysicalBufferReuseRequirements {
1674 virtual_id: VirtualBufferId,
1675 specification: RenderGraphBufferSpecification,
1676 first_node_pass_index: usize,
1677 last_node_pass_index: usize,
1678 }
1679
1680 fn add_or_modify_reuse_image_requirements(
1685 virtual_resources: &AssignVirtualResourcesResult,
1686 constraints: &DetermineConstraintsResult,
1687 pass_index: usize,
1688 usage: RenderGraphImageUsageId,
1689 reuse_requirements: &mut Vec<PhysicalImageReuseRequirements>,
1690 reuse_requirements_lookup: &mut FnvHashMap<VirtualImageId, usize>,
1691 ) {
1692 let virtual_id = virtual_resources.image_usage_to_virtual[&usage];
1694
1695 let reused_image_requirements_index = *reuse_requirements_lookup
1699 .entry(virtual_id)
1700 .or_insert_with(|| {
1701 let reused_image_requirements_index = reuse_requirements.len();
1702 let specification = &constraints.images[&usage];
1703 reuse_requirements.push(PhysicalImageReuseRequirements {
1704 virtual_id,
1705 first_node_pass_index: pass_index,
1706 last_node_pass_index: pass_index,
1707 specification: specification.clone(),
1708 });
1709
1710 log::trace!(" Add requirement {:?} {:?}", virtual_id, specification);
1711 reused_image_requirements_index
1712 });
1713
1714 reuse_requirements[reused_image_requirements_index].last_node_pass_index = pass_index;
1716 }
1717
1718 fn add_or_modify_reuse_buffer_requirements(
1719 virtual_resources: &AssignVirtualResourcesResult,
1720 constraints: &DetermineConstraintsResult,
1721 pass_index: usize,
1722 usage: RenderGraphBufferUsageId,
1723 reuse_requirements: &mut Vec<PhysicalBufferReuseRequirements>,
1724 reuse_requirements_lookup: &mut FnvHashMap<VirtualBufferId, usize>,
1725 ) {
1726 let virtual_id = virtual_resources.buffer_usage_to_virtual[&usage];
1728
1729 let reused_buffer_requirements_index = *reuse_requirements_lookup
1733 .entry(virtual_id)
1734 .or_insert_with(|| {
1735 let reused_buffer_requirements_index = reuse_requirements.len();
1736 let specification = &constraints.buffers[&usage];
1737 reuse_requirements.push(PhysicalBufferReuseRequirements {
1738 virtual_id,
1739 first_node_pass_index: pass_index,
1740 last_node_pass_index: pass_index,
1741 specification: specification.clone(),
1742 });
1743
1744 log::trace!(" Add requirement {:?} {:?}", virtual_id, specification);
1745 reused_buffer_requirements_index
1746 });
1747
1748 reuse_requirements[reused_buffer_requirements_index].last_node_pass_index = pass_index;
1750 }
1751
1752 let mut image_reuse_requirements = Vec::<PhysicalImageReuseRequirements>::default();
1753 let mut image_reuse_requirements_lookup = FnvHashMap::<VirtualImageId, usize>::default();
1754 let mut buffer_reuse_requirements = Vec::<PhysicalBufferReuseRequirements>::default();
1755 let mut buffer_reuse_requirements_lookup = FnvHashMap::<VirtualBufferId, usize>::default();
1756
1757 for (pass_index, pass) in passes.iter().enumerate() {
1761 let subpass_node_id = pass.node();
1762 let node = graph.node(subpass_node_id);
1763
1764 for image_modify in &node.image_modifies {
1765 add_or_modify_reuse_image_requirements(
1766 virtual_resources,
1767 constraints,
1768 pass_index,
1769 image_modify.input,
1770 &mut image_reuse_requirements,
1771 &mut image_reuse_requirements_lookup,
1772 );
1773 add_or_modify_reuse_image_requirements(
1774 virtual_resources,
1775 constraints,
1776 pass_index,
1777 image_modify.output,
1778 &mut image_reuse_requirements,
1779 &mut image_reuse_requirements_lookup,
1780 );
1781 }
1782
1783 for image_read in &node.image_reads {
1784 add_or_modify_reuse_image_requirements(
1785 virtual_resources,
1786 constraints,
1787 pass_index,
1788 image_read.image,
1789 &mut image_reuse_requirements,
1790 &mut image_reuse_requirements_lookup,
1791 );
1792 }
1793
1794 for image_create in &node.image_creates {
1795 add_or_modify_reuse_image_requirements(
1796 virtual_resources,
1797 constraints,
1798 pass_index,
1799 image_create.image,
1800 &mut image_reuse_requirements,
1801 &mut image_reuse_requirements_lookup,
1802 );
1803 }
1804
1805 for image_sample in &node.sampled_images {
1806 add_or_modify_reuse_image_requirements(
1807 virtual_resources,
1808 constraints,
1809 pass_index,
1810 *image_sample,
1811 &mut image_reuse_requirements,
1812 &mut image_reuse_requirements_lookup,
1813 );
1814 }
1815
1816 for buffer_modify in &node.buffer_modifies {
1817 add_or_modify_reuse_buffer_requirements(
1818 virtual_resources,
1819 constraints,
1820 pass_index,
1821 buffer_modify.input,
1822 &mut buffer_reuse_requirements,
1823 &mut buffer_reuse_requirements_lookup,
1824 );
1825 add_or_modify_reuse_buffer_requirements(
1826 virtual_resources,
1827 constraints,
1828 pass_index,
1829 buffer_modify.output,
1830 &mut buffer_reuse_requirements,
1831 &mut buffer_reuse_requirements_lookup,
1832 );
1833 }
1834
1835 for buffer_read in &node.buffer_reads {
1836 add_or_modify_reuse_buffer_requirements(
1837 virtual_resources,
1838 constraints,
1839 pass_index,
1840 buffer_read.buffer,
1841 &mut buffer_reuse_requirements,
1842 &mut buffer_reuse_requirements_lookup,
1843 );
1844 }
1845
1846 for buffer_create in &node.buffer_creates {
1847 add_or_modify_reuse_buffer_requirements(
1848 virtual_resources,
1849 constraints,
1850 pass_index,
1851 buffer_create.buffer,
1852 &mut buffer_reuse_requirements,
1853 &mut buffer_reuse_requirements_lookup,
1854 );
1855 }
1856 }
1857
1858 #[derive(Debug, PartialEq)]
1863 struct PhysicalImage {
1864 specification: RenderGraphImageSpecification,
1865 last_node_pass_index: usize,
1866 can_be_reused: bool,
1867 }
1868
1869 #[derive(Debug, PartialEq)]
1870 struct PhysicalBuffer {
1871 specification: RenderGraphBufferSpecification,
1872 last_node_pass_index: usize,
1873 can_be_reused: bool,
1874 }
1875
1876 let mut physical_images = Vec::<PhysicalImage>::default();
1877 let mut image_virtual_to_physical = FnvHashMap::<VirtualImageId, PhysicalImageId>::default();
1878 let mut physical_buffers = Vec::<PhysicalBuffer>::default();
1879 let mut buffer_virtual_to_physical = FnvHashMap::<VirtualBufferId, PhysicalBufferId>::default();
1880
1881 for external_image in &graph.external_images {
1885 if let Some(input_usage) = external_image.input_usage {
1886 let virtual_id = virtual_resources.image_usage_to_virtual[&input_usage];
1887 let physical_image = PhysicalImage {
1888 specification: external_image.specification.clone(),
1889 last_node_pass_index: passes.len() - 1,
1890 can_be_reused: false, };
1892
1893 let physical_image_id = PhysicalImageId(physical_images.len());
1894 physical_images.push(physical_image);
1895 let old = image_virtual_to_physical.insert(virtual_id, physical_image_id);
1896 assert!(old.is_none());
1897
1898 log::trace!(
1899 " Input Image {:?} -> {:?} Used in passes [{}:{}]",
1900 virtual_id,
1901 physical_image_id,
1902 0,
1903 passes.len() - 1
1904 );
1905 }
1906 }
1907
1908 for external_buffer in &graph.external_buffers {
1909 if let Some(input_usage) = external_buffer.input_usage {
1910 let virtual_id = virtual_resources.buffer_usage_to_virtual[&input_usage];
1911 let physical_buffer = PhysicalBuffer {
1912 specification: external_buffer.specification.clone(),
1913 last_node_pass_index: passes.len() - 1,
1914 can_be_reused: false, };
1916
1917 let physical_buffer_id = PhysicalBufferId(physical_buffers.len());
1918 physical_buffers.push(physical_buffer);
1919 let old = buffer_virtual_to_physical.insert(virtual_id, physical_buffer_id);
1920 assert!(old.is_none());
1921
1922 log::trace!(
1923 " Input Buffer {:?} -> {:?} Used in passes [{}:{}]",
1924 virtual_id,
1925 physical_buffer_id,
1926 0,
1927 passes.len() - 1
1928 );
1929 }
1930 }
1931
1932 for external_image in &graph.external_images {
1936 if let Some(output_usage) = external_image.output_usage {
1937 let virtual_id = virtual_resources.image_usage_to_virtual[&output_usage];
1938 let physical_image = PhysicalImage {
1939 specification: external_image.specification.clone(),
1940 last_node_pass_index: passes.len() - 1,
1941 can_be_reused: false, };
1943
1944 let physical_image_id = if let Some(existing_physical_image_id) =
1945 image_virtual_to_physical.get(&virtual_id)
1946 {
1947 let existing_physical_image = &physical_images[existing_physical_image_id.0];
1949 assert_eq!(physical_image, *existing_physical_image);
1950 *existing_physical_image_id
1951 } else {
1952 let physical_image_id = PhysicalImageId(physical_images.len());
1953 physical_images.push(physical_image);
1954 let old = image_virtual_to_physical.insert(virtual_id, physical_image_id);
1955 assert!(old.is_none());
1956 physical_image_id
1957 };
1958
1959 log::trace!(
1960 " Output Image {:?} -> {:?} Used in passes [{}:{}]",
1961 virtual_id,
1962 physical_image_id,
1963 0,
1964 passes.len() - 1
1965 );
1966 }
1967 }
1968
1969 for external_buffer in &graph.external_buffers {
1970 if let Some(output_usage) = external_buffer.output_usage {
1971 let virtual_id = virtual_resources.buffer_usage_to_virtual[&output_usage];
1972 let physical_buffer = PhysicalBuffer {
1973 specification: external_buffer.specification.clone(),
1974 last_node_pass_index: passes.len() - 1,
1975 can_be_reused: false, };
1977
1978 let physical_buffer_id = if let Some(existing_physical_buffer_id) =
1979 buffer_virtual_to_physical.get(&virtual_id)
1980 {
1981 let existing_physical_buffer = &physical_buffers[existing_physical_buffer_id.0];
1983 assert_eq!(physical_buffer, *existing_physical_buffer);
1984 *existing_physical_buffer_id
1985 } else {
1986 let physical_buffer_id = PhysicalBufferId(physical_buffers.len());
1987 physical_buffers.push(physical_buffer);
1988 let old = buffer_virtual_to_physical.insert(virtual_id, physical_buffer_id);
1989 assert!(old.is_none());
1990 physical_buffer_id
1991 };
1992
1993 log::trace!(
1994 " Output Buffer {:?} -> {:?} Used in passes [{}:{}]",
1995 virtual_id,
1996 physical_buffer_id,
1997 0,
1998 passes.len() - 1
1999 );
2000 }
2001 }
2002
2003 for reuse_requirements in &image_reuse_requirements {
2011 if image_virtual_to_physical.contains_key(&reuse_requirements.virtual_id) {
2012 continue;
2014 }
2015
2016 let mut physical_image_id = None;
2018 for (physical_image_index, physical_image) in physical_images.iter_mut().enumerate() {
2019 if physical_image.last_node_pass_index < reuse_requirements.first_node_pass_index
2020 && physical_image.can_be_reused
2021 {
2022 if physical_image
2023 .specification
2024 .try_merge(&reuse_requirements.specification)
2025 {
2026 physical_image.last_node_pass_index = reuse_requirements.last_node_pass_index;
2027 physical_image_id = Some(PhysicalImageId(physical_image_index));
2028 log::trace!(
2029 " Intermediate Image (Reuse) {:?} -> {:?} Used in passes [{}:{}]",
2030 reuse_requirements.virtual_id,
2031 physical_image_id,
2032 reuse_requirements.first_node_pass_index,
2033 reuse_requirements.last_node_pass_index
2034 );
2035 break;
2036 }
2037 }
2038 }
2039
2040 let physical_image_id = physical_image_id.unwrap_or_else(|| {
2042 let physical_image_id = PhysicalImageId(physical_images.len());
2043 physical_images.push(PhysicalImage {
2044 specification: reuse_requirements.specification.clone(),
2045 last_node_pass_index: reuse_requirements.last_node_pass_index,
2046 can_be_reused: true,
2047 });
2048
2049 log::trace!(
2050 " Intermediate Image (Create new) {:?} -> {:?} Used in passes [{}:{}]",
2051 reuse_requirements.virtual_id,
2052 physical_image_id,
2053 reuse_requirements.first_node_pass_index,
2054 reuse_requirements.last_node_pass_index
2055 );
2056 physical_image_id
2057 });
2058
2059 image_virtual_to_physical.insert(reuse_requirements.virtual_id, physical_image_id);
2060 }
2061
2062 for reuse_requirements in &buffer_reuse_requirements {
2063 if buffer_virtual_to_physical.contains_key(&reuse_requirements.virtual_id) {
2064 continue;
2066 }
2067
2068 let mut physical_buffer_id = None;
2070 for (physical_buffer_index, physical_buffer) in physical_buffers.iter_mut().enumerate() {
2071 if physical_buffer.last_node_pass_index < reuse_requirements.first_node_pass_index
2072 && physical_buffer.can_be_reused
2073 {
2074 if physical_buffer
2075 .specification
2076 .try_merge(&reuse_requirements.specification)
2077 {
2078 physical_buffer.last_node_pass_index = reuse_requirements.last_node_pass_index;
2079 physical_buffer_id = Some(PhysicalBufferId(physical_buffer_index));
2080 log::trace!(
2081 " Intermediate Buffer (Reuse) {:?} -> {:?} Used in passes [{}:{}]",
2082 reuse_requirements.virtual_id,
2083 physical_buffer_id,
2084 reuse_requirements.first_node_pass_index,
2085 reuse_requirements.last_node_pass_index
2086 );
2087 break;
2088 }
2089 }
2090 }
2091
2092 let physical_buffer_id = physical_buffer_id.unwrap_or_else(|| {
2094 let physical_buffer_id = PhysicalBufferId(physical_buffers.len());
2095 physical_buffers.push(PhysicalBuffer {
2096 specification: reuse_requirements.specification.clone(),
2097 last_node_pass_index: reuse_requirements.last_node_pass_index,
2098 can_be_reused: true,
2099 });
2100
2101 log::trace!(
2102 " Intermediate Buffer (Create new) {:?} -> {:?} Used in passes [{}:{}]",
2103 reuse_requirements.virtual_id,
2104 physical_buffer_id,
2105 reuse_requirements.first_node_pass_index,
2106 reuse_requirements.last_node_pass_index
2107 );
2108 physical_buffer_id
2109 });
2110
2111 buffer_virtual_to_physical.insert(reuse_requirements.virtual_id, physical_buffer_id);
2112 }
2113
2114 let mut image_usage_to_physical = FnvHashMap::default();
2118 for (&usage, virtual_image) in &virtual_resources.image_usage_to_virtual {
2119 image_usage_to_physical.insert(usage, image_virtual_to_physical[virtual_image]);
2122 }
2123
2124 let mut buffer_usage_to_physical = FnvHashMap::default();
2128 for (&usage, virtual_buffer) in &virtual_resources.buffer_usage_to_virtual {
2129 buffer_usage_to_physical.insert(usage, buffer_virtual_to_physical[virtual_buffer]);
2132 }
2133
2134 let mut image_subresource_to_view = FnvHashMap::default();
2140
2141 let mut image_views = Vec::default();
2143 let mut image_usage_to_image_view = FnvHashMap::default();
2144
2145 for (&usage, &physical_image) in &image_usage_to_physical {
2149 let image_specification = constraints.image_specification(usage).unwrap();
2150 let image_view = RenderGraphImageView {
2151 physical_image,
2152 format: image_specification.format,
2153 view_options: graph.image_usage(usage).view_options.clone(),
2154 };
2155
2156 let image_view_id = *image_subresource_to_view
2159 .entry(image_view.clone())
2160 .or_insert_with(|| {
2161 let image_view_id = PhysicalImageViewId(image_views.len());
2162 image_views.push(image_view);
2163 image_view_id
2164 });
2165
2166 let old = image_usage_to_image_view.insert(usage, image_view_id);
2167 assert!(old.is_none());
2168 }
2169
2170 for pass in passes {
2171 if let RenderGraphPass::Render(renderpass) = pass {
2172 for attachment in &mut renderpass.attachments {
2173 let physical_image = image_virtual_to_physical[&attachment.virtual_image];
2174 let image_view_id = image_usage_to_image_view[&attachment.usage];
2175 attachment.image = Some(physical_image);
2176 attachment.image_view = Some(image_view_id);
2177 }
2178 }
2179 }
2180
2181 let image_specifications: Vec<_> = physical_images
2185 .into_iter()
2186 .map(|x| x.specification)
2187 .collect();
2188
2189 let buffer_specifications: Vec<_> = physical_buffers
2193 .into_iter()
2194 .map(|x| x.specification)
2195 .collect();
2196
2197 AssignPhysicalResourcesResult {
2198 image_usage_to_physical,
2199 image_virtual_to_physical,
2200 image_usage_to_image_view,
2201 image_views,
2202 image_specifications,
2203 buffer_usage_to_physical,
2204 buffer_virtual_to_physical,
2205 buffer_specifications,
2206 }
2207}
2208
2209fn add_image_barrier_for_node(
2210 physical_resources: &AssignPhysicalResourcesResult,
2211 image_node_barriers: &mut FnvHashMap<PhysicalImageId, RenderGraphPassImageBarriers>,
2212 image: RenderGraphImageUsageId,
2213 resource_state: RafxResourceState,
2214) {
2215 let physical_image = physical_resources
2216 .image_usage_to_physical
2217 .get(&image)
2218 .unwrap();
2219
2220 let old = image_node_barriers.insert(
2222 *physical_image,
2223 RenderGraphPassImageBarriers::new(resource_state),
2224 );
2225 assert!(old.is_none());
2226}
2227
2228fn add_buffer_barrier_for_node(
2229 physical_resources: &AssignPhysicalResourcesResult,
2230 buffer_node_barriers: &mut FnvHashMap<PhysicalBufferId, RenderGraphPassBufferBarriers>,
2231 buffer: RenderGraphBufferUsageId,
2232 resource_state: RafxResourceState,
2233) {
2234 let physical_buffer = physical_resources
2235 .buffer_usage_to_physical
2236 .get(&buffer)
2237 .unwrap();
2238
2239 let old = buffer_node_barriers.insert(
2241 *physical_buffer,
2242 RenderGraphPassBufferBarriers::new(resource_state),
2243 );
2244 assert!(old.is_none());
2245}
2246
2247#[profiling::function]
2248fn build_node_barriers(
2249 graph: &RenderGraphBuilder,
2250 node_execution_order: &[RenderGraphNodeId],
2251 _constraints: &DetermineConstraintsResult,
2252 physical_resources: &AssignPhysicalResourcesResult,
2253 builtin_final_node: RenderGraphNodeId,
2254) -> FnvHashMap<RenderGraphNodeId, RenderGraphNodeResourceBarriers> {
2255 let mut resource_barriers =
2256 FnvHashMap::<RenderGraphNodeId, RenderGraphNodeResourceBarriers>::default();
2257
2258 for node_id in node_execution_order {
2259 if *node_id == builtin_final_node {
2262 break;
2263 }
2264
2265 let node = graph.node(*node_id);
2266 let mut image_node_barriers: FnvHashMap<PhysicalImageId, RenderGraphPassImageBarriers> =
2267 Default::default();
2268 let mut buffer_node_barriers: FnvHashMap<PhysicalBufferId, RenderGraphPassBufferBarriers> =
2269 Default::default();
2270
2271 for color_attachment in &node.color_attachments {
2275 if let Some(color_attachment) = color_attachment {
2276 let read_or_write_usage = color_attachment
2277 .read_image
2278 .or(color_attachment.write_image)
2279 .unwrap();
2280
2281 add_image_barrier_for_node(
2282 physical_resources,
2283 &mut image_node_barriers,
2284 read_or_write_usage,
2285 RafxResourceState::RENDER_TARGET,
2286 );
2287 }
2288 }
2289
2290 for resolve_attachment in &node.resolve_attachments {
2291 if let Some(resolve_attachment) = resolve_attachment {
2292 add_image_barrier_for_node(
2293 physical_resources,
2294 &mut image_node_barriers,
2295 resolve_attachment.write_image,
2296 RafxResourceState::RENDER_TARGET,
2297 );
2298 }
2299 }
2300
2301 if let Some(depth_attachment) = &node.depth_attachment {
2302 let read_or_write_usage = depth_attachment
2303 .read_image
2304 .or(depth_attachment.write_image)
2305 .unwrap();
2306
2307 add_image_barrier_for_node(
2308 physical_resources,
2309 &mut image_node_barriers,
2310 read_or_write_usage,
2311 RafxResourceState::DEPTH_WRITE,
2312 );
2313 }
2314
2315 for &image in &node.sampled_images {
2319 add_image_barrier_for_node(
2320 physical_resources,
2321 &mut image_node_barriers,
2322 image,
2323 RafxResourceState::SHADER_RESOURCE,
2324 );
2325 }
2326
2327 for &image in &node.storage_image_creates {
2328 add_image_barrier_for_node(
2329 physical_resources,
2330 &mut image_node_barriers,
2331 image,
2332 RafxResourceState::UNORDERED_ACCESS,
2333 );
2334 }
2335
2336 for &image in &node.storage_image_reads {
2337 add_image_barrier_for_node(
2338 physical_resources,
2339 &mut image_node_barriers,
2340 image,
2341 RafxResourceState::UNORDERED_ACCESS,
2342 );
2343 }
2344
2345 for &image in &node.storage_image_modifies {
2346 add_image_barrier_for_node(
2347 physical_resources,
2348 &mut image_node_barriers,
2349 image,
2350 RafxResourceState::UNORDERED_ACCESS,
2351 );
2352 }
2353
2354 for &image in &node.copy_src_image_reads {
2355 add_image_barrier_for_node(
2356 physical_resources,
2357 &mut image_node_barriers,
2358 image,
2359 RafxResourceState::COPY_SRC,
2360 );
2361 }
2362
2363 for &image in &node.copy_dst_image_writes {
2364 add_image_barrier_for_node(
2365 physical_resources,
2366 &mut image_node_barriers,
2367 image,
2368 RafxResourceState::COPY_DST,
2369 );
2370 }
2371
2372 for &buffer in &node.vertex_buffer_reads {
2376 add_buffer_barrier_for_node(
2377 physical_resources,
2378 &mut buffer_node_barriers,
2379 buffer,
2380 RafxResourceState::VERTEX_AND_CONSTANT_BUFFER,
2381 );
2382 }
2383
2384 for &buffer in &node.index_buffer_reads {
2385 add_buffer_barrier_for_node(
2386 physical_resources,
2387 &mut buffer_node_barriers,
2388 buffer,
2389 RafxResourceState::INDEX_BUFFER,
2390 );
2391 }
2392
2393 for &buffer in &node.indirect_buffer_reads {
2394 add_buffer_barrier_for_node(
2395 physical_resources,
2396 &mut buffer_node_barriers,
2397 buffer,
2398 RafxResourceState::INDIRECT_ARGUMENT,
2399 );
2400 }
2401
2402 for &buffer in &node.uniform_buffer_reads {
2403 add_buffer_barrier_for_node(
2404 physical_resources,
2405 &mut buffer_node_barriers,
2406 buffer,
2407 RafxResourceState::VERTEX_AND_CONSTANT_BUFFER,
2408 );
2409 }
2410
2411 for &buffer in &node.storage_buffer_creates {
2412 add_buffer_barrier_for_node(
2413 physical_resources,
2414 &mut buffer_node_barriers,
2415 buffer,
2416 RafxResourceState::UNORDERED_ACCESS,
2417 );
2418 }
2419
2420 for &buffer in &node.storage_buffer_reads {
2421 add_buffer_barrier_for_node(
2422 physical_resources,
2423 &mut buffer_node_barriers,
2424 buffer,
2425 RafxResourceState::UNORDERED_ACCESS,
2426 );
2427 }
2428
2429 for &buffer in &node.storage_buffer_modifies {
2430 add_buffer_barrier_for_node(
2431 physical_resources,
2432 &mut buffer_node_barriers,
2433 buffer,
2434 RafxResourceState::UNORDERED_ACCESS,
2435 );
2436 }
2437
2438 for &buffer in &node.copy_src_buffer_reads {
2439 add_buffer_barrier_for_node(
2440 physical_resources,
2441 &mut buffer_node_barriers,
2442 buffer,
2443 RafxResourceState::COPY_SRC,
2444 );
2445 }
2446
2447 for &buffer in &node.copy_dst_buffer_writes {
2448 add_buffer_barrier_for_node(
2449 physical_resources,
2450 &mut buffer_node_barriers,
2451 buffer,
2452 RafxResourceState::COPY_DST,
2453 );
2454 }
2455
2456 resource_barriers.insert(
2457 *node_id,
2458 RenderGraphNodeResourceBarriers {
2459 image_barriers: image_node_barriers,
2460 buffer_barriers: buffer_node_barriers,
2461 },
2462 );
2463 }
2464
2465 let _builtin_final_node = graph.node(builtin_final_node);
2469 let mut final_image_node_barriers: FnvHashMap<PhysicalImageId, RenderGraphPassImageBarriers> =
2470 Default::default();
2471 let mut final_buffer_node_barriers: FnvHashMap<
2472 PhysicalBufferId,
2473 RenderGraphPassBufferBarriers,
2474 > = Default::default();
2475
2476 for external_image in &graph.external_images {
2477 if let Some(output_usage) = external_image.output_usage {
2478 add_image_barrier_for_node(
2479 physical_resources,
2480 &mut final_image_node_barriers,
2481 output_usage,
2482 external_image.final_state,
2483 );
2484 }
2485 }
2486
2487 for external_buffer in &graph.external_buffers {
2488 if let Some(output_usage) = external_buffer.output_usage {
2489 add_buffer_barrier_for_node(
2490 physical_resources,
2491 &mut final_buffer_node_barriers,
2492 output_usage,
2493 external_buffer.final_state,
2494 );
2495 }
2496 }
2497
2498 resource_barriers.insert(
2499 builtin_final_node,
2500 RenderGraphNodeResourceBarriers {
2501 image_barriers: final_image_node_barriers,
2502 buffer_barriers: final_buffer_node_barriers,
2503 },
2504 );
2505
2506 resource_barriers
2507}
2508
2509#[profiling::function]
2515fn build_pass_barriers(
2516 graph: &RenderGraphBuilder,
2517 _node_execution_order: &[RenderGraphNodeId],
2518 _constraints: &DetermineConstraintsResult,
2519 physical_resources: &AssignPhysicalResourcesResult,
2520 node_barriers: &FnvHashMap<RenderGraphNodeId, RenderGraphNodeResourceBarriers>,
2521 passes: &mut [RenderGraphPass],
2522) {
2523 log::trace!("-- build_pass_barriers --");
2524
2525 struct ImageState {
2529 resource_state: RafxResourceState,
2530 }
2531
2532 impl Default for ImageState {
2533 fn default() -> Self {
2534 ImageState {
2535 resource_state: RafxResourceState::UNDEFINED,
2536 }
2537 }
2538 }
2539
2540 struct BufferState {
2541 resource_state: RafxResourceState,
2542 }
2543
2544 impl Default for BufferState {
2545 fn default() -> Self {
2546 BufferState {
2547 resource_state: RafxResourceState::COPY_DST,
2549 }
2550 }
2551 }
2552
2553 let mut image_states: Vec<ImageState> =
2559 Vec::with_capacity(physical_resources.image_specifications.len());
2560 image_states.resize_with(physical_resources.image_specifications.len(), || {
2561 Default::default()
2562 });
2563
2564 let mut buffer_states: Vec<BufferState> =
2565 Vec::with_capacity(physical_resources.buffer_specifications.len());
2566 buffer_states.resize_with(physical_resources.buffer_specifications.len(), || {
2567 Default::default()
2568 });
2569
2570 for external_image in &graph.external_images {
2572 if let Some(input_usage) = external_image.input_usage {
2573 let physical_id = physical_resources.image_usage_to_physical[&input_usage];
2574 image_states[physical_id.0].resource_state = external_image.initial_state;
2575 }
2576 }
2577
2578 for external_buffer in &graph.external_buffers {
2579 if let Some(input_usage) = external_buffer.input_usage {
2580 let physical_id = physical_resources.buffer_usage_to_physical[&input_usage];
2581 buffer_states[physical_id.0].resource_state = external_buffer.initial_state;
2582 }
2583 }
2584
2585 for (pass_index, pass) in passes.iter_mut().enumerate() {
2586 log::trace!("pass {}", pass_index);
2587
2588 let mut attachment_initial_state: Vec<Option<RafxResourceState>> = Default::default();
2590 if let RenderGraphPass::Render(pass) = pass {
2591 attachment_initial_state.resize_with(pass.attachments.len(), || None);
2592 }
2593
2594 let subpass_node_id = pass.node();
2597 let node_barriers = &node_barriers[&subpass_node_id];
2598
2599 struct ImageTransition {
2600 physical_image_id: PhysicalImageId,
2601 old_state: RafxResourceState,
2602 new_state: RafxResourceState,
2603 }
2604
2605 struct BufferTransition {
2606 physical_buffer_id: PhysicalBufferId,
2607 old_state: RafxResourceState,
2608 new_state: RafxResourceState,
2609 }
2610
2611 let mut image_transitions = Vec::default();
2612 for (physical_image_id, image_barrier) in &node_barriers.image_barriers {
2614 log::trace!(" image {:?}", physical_image_id);
2615 let image_state = &mut image_states[physical_image_id.0];
2616
2617 let resource_state_change = image_state.resource_state != image_barrier.resource_state;
2618 if resource_state_change {
2619 log::trace!(
2620 " state change! {:?} -> {:?}",
2621 image_state.resource_state,
2622 image_barrier.resource_state
2623 );
2624
2625 if resource_state_change {
2626 image_transitions.push(ImageTransition {
2627 physical_image_id: *physical_image_id,
2628 old_state: image_state.resource_state,
2629 new_state: image_barrier.resource_state,
2630 });
2631 }
2632
2633 image_state.resource_state = image_barrier.resource_state;
2634 }
2635
2636 if let RenderGraphPass::Render(pass) = pass {
2640 for (attachment_index, attachment) in &mut pass.attachments.iter_mut().enumerate() {
2641 if attachment.image.unwrap() == *physical_image_id {
2643 if attachment_initial_state[attachment_index].is_none() {
2644 attachment_initial_state[attachment_index] =
2646 Some(image_state.resource_state.into());
2647
2648 attachment.initial_state = image_barrier.resource_state.into();
2652 }
2653
2654 attachment.final_state = image_barrier.resource_state.into();
2655 break;
2656 }
2657 }
2658 }
2659 }
2660
2661 let mut buffer_transitions = Vec::default();
2663 for (physical_buffer_id, buffer_barrier) in &node_barriers.buffer_barriers {
2664 log::trace!(" buffer {:?}", physical_buffer_id);
2665 let buffer_state = &mut buffer_states[physical_buffer_id.0];
2666
2667 let resource_state_change =
2668 buffer_state.resource_state != buffer_barrier.resource_state;
2669 if resource_state_change {
2670 log::trace!(
2671 " state change! {:?} -> {:?}",
2672 buffer_state.resource_state,
2673 buffer_barrier.resource_state
2674 );
2675
2676 buffer_transitions.push(BufferTransition {
2677 physical_buffer_id: *physical_buffer_id,
2678 old_state: buffer_state.resource_state,
2679 new_state: buffer_barrier.resource_state,
2680 });
2681
2682 buffer_state.resource_state = buffer_barrier.resource_state;
2683 }
2684 }
2685
2686 let image_barriers: Vec<_> = image_transitions
2687 .into_iter()
2688 .map(|image_transition| {
2689 assert_ne!(image_transition.new_state, RafxResourceState::UNDEFINED);
2690 PrepassImageBarrier {
2691 image: image_transition.physical_image_id,
2692 old_state: image_transition.old_state,
2693 new_state: image_transition.new_state,
2694 }
2695 })
2696 .collect();
2697
2698 let buffer_barriers: Vec<_> = buffer_transitions
2699 .into_iter()
2700 .map(|buffer_transition| {
2701 assert_ne!(buffer_transition.new_state, RafxResourceState::UNDEFINED);
2702 PrepassBufferBarrier {
2703 buffer: buffer_transition.physical_buffer_id,
2704 old_state: buffer_transition.old_state,
2705 new_state: buffer_transition.new_state,
2706 }
2707 })
2708 .collect();
2709
2710 if !image_barriers.is_empty() || !buffer_barriers.is_empty() {
2711 let barrier = PrepassBarrier {
2712 image_barriers,
2713 buffer_barriers,
2714 };
2715
2716 pass.set_pre_pass_barrier(barrier);
2717 }
2718 }
2719}
2720
2721#[profiling::function]
2722fn create_output_passes(
2723 graph: &RenderGraphBuilder,
2724 passes: Vec<RenderGraphPass>,
2725) -> Vec<RenderGraphOutputPass> {
2726 let mut renderpasses = Vec::with_capacity(passes.len());
2727
2728 for pass in passes {
2729 let render_node = graph.node(pass.node());
2730 let debug_name = render_node.name;
2731
2732 match pass {
2733 RenderGraphPass::Render(pass) => {
2734 let attachment_images = pass
2735 .attachments
2736 .iter()
2737 .map(|attachment| attachment.image_view.unwrap())
2738 .collect();
2739
2740 let mut color_formats = vec![];
2741 let mut sample_count = None;
2742 for color_attachment in &pass.color_attachments {
2743 if let Some(color_attachment) = color_attachment {
2744 color_formats.push(pass.attachments[*color_attachment].format);
2745
2746 let expected_sample_count = pass.attachments[*color_attachment].samples;
2747 if let Some(sample_count) = sample_count {
2748 assert_eq!(sample_count, expected_sample_count, "Render node has color attachments with different sample counts, this is unsupported.");
2749 } else {
2750 sample_count = Some(expected_sample_count);
2751 }
2752 }
2753 }
2754
2755 let mut depth_format = None;
2756 if let Some(depth_attachment) = pass.depth_attachment {
2757 depth_format = Some(pass.attachments[depth_attachment].format);
2758
2759 let expected_sample_count = pass.attachments[depth_attachment].samples;
2760 if let Some(sample_count) = sample_count {
2761 assert_eq!(sample_count, expected_sample_count, "Render node has color attachment and depth attachment with different sample counts, this is unsupported.");
2762 } else {
2763 sample_count = Some(expected_sample_count);
2764 }
2765 }
2766
2767 let render_target_meta = GraphicsPipelineRenderTargetMeta::new(
2768 color_formats,
2769 depth_format,
2770 sample_count.unwrap(),
2771 );
2772
2773 let mut color_render_targets = Vec::with_capacity(MAX_COLOR_ATTACHMENTS);
2774
2775 for (color_index, attachment_index) in pass.color_attachments.iter().enumerate() {
2776 if let Some(attachment_index) = attachment_index {
2777 let attachment = &pass.attachments[*attachment_index]; let attachment_usage = &graph.image_usages[attachment.usage.0];
2779 let array_slice = attachment_usage.view_options.array_slice;
2780 let mip_slice = attachment_usage.view_options.mip_slice;
2781
2782 let mut resolve_image = None;
2783 let mut resolve_array_slice = None;
2784 let mut resolve_mip_slice = None;
2785 let mut resolve_store_op = RafxStoreOp::DontCare;
2786 if let Some(resolve_attachment_index) =
2787 pass.resolve_attachments[color_index]
2788 {
2789 let resolve_attachment = &pass.attachments[resolve_attachment_index]; let resolve_attachment_usage =
2791 &graph.image_usages[resolve_attachment.usage.0];
2792 resolve_image = Some(resolve_attachment.image.unwrap());
2793 resolve_array_slice = resolve_attachment_usage.view_options.array_slice;
2794 resolve_mip_slice = resolve_attachment_usage.view_options.mip_slice;
2795 resolve_store_op = resolve_attachment.store_op;
2796 }
2797
2798 color_render_targets.push(RenderGraphColorRenderTarget {
2799 image: attachment.image.unwrap(),
2800 load_op: attachment.load_op,
2801 store_op: attachment.store_op,
2802 clear_value: attachment
2803 .clear_color
2804 .clone()
2805 .map(|x| x.to_color_clear_value())
2806 .unwrap_or_default(),
2807 array_slice,
2808 mip_slice,
2809 resolve_image,
2810 resolve_store_op,
2811 resolve_array_slice,
2812 resolve_mip_slice,
2813 });
2814 }
2815 }
2816
2817 let mut depth_stencil_render_target = None;
2818 if let Some(attachment_index) = pass.depth_attachment {
2819 let attachment = &pass.attachments[attachment_index];
2820 let array_slice = graph.image_usages[attachment.usage.0]
2821 .view_options
2822 .array_slice;
2823 let mip_slice = graph.image_usages[attachment.usage.0]
2824 .view_options
2825 .mip_slice;
2826 depth_stencil_render_target = Some(RenderGraphDepthStencilRenderTarget {
2827 image: attachment.image.unwrap(),
2828 depth_load_op: attachment.load_op,
2829 stencil_load_op: attachment.stencil_load_op,
2830 depth_store_op: attachment.store_op,
2831 stencil_store_op: attachment.stencil_store_op,
2832 clear_value: attachment
2833 .clear_color
2834 .clone()
2835 .map(|x| x.to_depth_stencil_clear_value())
2836 .unwrap_or_default(),
2837 array_slice,
2838 mip_slice,
2839 });
2840 }
2841
2842 let output_pass = RenderGraphOutputRenderPass {
2843 node_id: pass.node_id,
2844 attachment_images,
2845 pre_pass_barrier: pass.pre_pass_barrier,
2846 debug_name,
2847 color_render_targets,
2848 depth_stencil_render_target,
2849 render_target_meta,
2850 };
2851
2852 renderpasses.push(RenderGraphOutputPass::Render(output_pass));
2853 }
2854 RenderGraphPass::Callback(pass) => {
2855 let output_pass = RenderGraphOutputCallbackPass {
2856 node: pass.node,
2857 pre_pass_barrier: pass.pre_pass_barrier,
2858 debug_name,
2859 };
2860
2861 renderpasses.push(RenderGraphOutputPass::Callback(output_pass));
2862 }
2863 }
2864 }
2865
2866 renderpasses
2867}
2868
2869#[allow(dead_code)]
2870fn print_constraints(
2871 graph: &RenderGraphBuilder,
2872 constraint_results: &mut DetermineConstraintsResult,
2873) {
2874 log::trace!("Image constraints:");
2875 for (image_index, image_resource) in graph.image_resources.iter().enumerate() {
2876 log::trace!(" Image {:?} {:?}", image_index, image_resource.name);
2877 for (version_index, version) in image_resource.versions.iter().enumerate() {
2878 log::trace!(" Version {}", version_index);
2879
2880 log::trace!(
2881 " Writen as: {:?}",
2882 constraint_results.image_specification(version.create_usage)
2883 );
2884
2885 for (usage_index, usage) in version.read_usages.iter().enumerate() {
2886 log::trace!(
2887 " Read Usage {}: {:?}",
2888 usage_index,
2889 constraint_results.image_specification(*usage)
2890 );
2891 }
2892 }
2893 }
2894
2895 log::trace!("Buffer constraints:");
2896 for (buffer_index, buffer_resource) in graph.buffer_resources.iter().enumerate() {
2897 log::trace!(" Buffer {:?} {:?}", buffer_index, buffer_resource.name);
2898 for (version_index, version) in buffer_resource.versions.iter().enumerate() {
2899 log::trace!(" Version {}", version_index);
2900
2901 log::trace!(
2902 " Writen as: {:?}",
2903 constraint_results.buffer_specification(version.create_usage)
2904 );
2905
2906 for (usage_index, usage) in version.read_usages.iter().enumerate() {
2907 log::trace!(
2908 " Read Usage {}: {:?}",
2909 usage_index,
2910 constraint_results.buffer_specification(*usage)
2911 );
2912 }
2913 }
2914 }
2915}
2916
2917#[allow(dead_code)]
2918fn print_image_compatibility(
2919 graph: &RenderGraphBuilder,
2920 constraint_results: &DetermineConstraintsResult,
2921) {
2922 log::trace!("Image Compatibility Report:");
2923 for (image_index, image_resource) in graph.image_resources.iter().enumerate() {
2924 log::trace!(" Image {:?} {:?}", image_index, image_resource.name);
2925 for (version_index, version) in image_resource.versions.iter().enumerate() {
2926 let write_specification = constraint_results.image_specification(version.create_usage);
2927
2928 log::trace!(" Version {}: {:?}", version_index, version);
2929 for (usage_index, usage) in version.read_usages.iter().enumerate() {
2930 let read_specification = constraint_results.image_specification(*usage);
2931
2932 if write_specification == read_specification {
2935 log::trace!(" read usage {} matches", usage_index);
2936 } else {
2937 log::trace!(" read usage {} does not match", usage_index);
2938 log::trace!(" produced: {:?}", write_specification);
2939 log::trace!(" required: {:?}", read_specification);
2940 }
2941 }
2942 }
2943 }
2944}
2945
2946#[allow(dead_code)]
2947fn print_node_barriers(
2948 node_barriers: &FnvHashMap<RenderGraphNodeId, RenderGraphNodeResourceBarriers>
2949) {
2950 log::trace!("Barriers:");
2951 for (node_id, barriers) in node_barriers.iter() {
2952 log::trace!(" pass {:?}", node_id);
2953 log::trace!(" resource states");
2954 for (physical_id, barriers) in &barriers.image_barriers {
2955 log::trace!(" {:?}: {:?}", physical_id, barriers.resource_state);
2956 }
2957
2958 for (physical_id, barriers) in &barriers.buffer_barriers {
2959 log::trace!(" {:?}: {:?}", physical_id, barriers.resource_state);
2960 }
2961 }
2962}
2963
2964#[allow(dead_code)]
2965fn verify_unculled_image_usages_specifications_exist(
2966 graph: &RenderGraphBuilder,
2967 node_execution_order: &Vec<RenderGraphNodeId>,
2968 constraint_results: &DetermineConstraintsResult,
2969) {
2970 for (_image_index, image_resource) in graph.image_resources.iter().enumerate() {
2971 for (_version_index, version) in image_resource.versions.iter().enumerate() {
2973 if node_execution_order.contains(&version.creator_node)
2975 && constraint_results
2976 .images
2977 .get(&version.create_usage)
2978 .is_none()
2979 {
2980 let usage_info = &graph.image_usages[version.create_usage.0];
2981 panic!(
2982 "Could not determine specification for image {:?} use by {:?} for {:?}",
2983 version.create_usage, usage_info.user, usage_info.usage_type
2984 );
2985 }
2986
2987 for (_, usage) in version.read_usages.iter().enumerate() {
2989 let usage_info = &graph.image_usages[usage.0];
2990 let is_scheduled = match &usage_info.user {
2991 RenderGraphImageUser::Node(node_id) => node_execution_order.contains(node_id),
2992 RenderGraphImageUser::Input(_) => true,
2993 RenderGraphImageUser::Output(_) => true,
2994 };
2995
2996 if is_scheduled && constraint_results.images.get(usage).is_none() {
2997 panic!(
2998 "Could not determine specification for image {:?} used by {:?} for {:?}",
2999 usage, usage_info.user, usage_info.usage_type
3000 );
3001 }
3002 }
3003 }
3004 }
3005}
3006
3007#[allow(dead_code)]
3008fn print_final_images(
3009 assign_physical_resources_result: &AssignPhysicalResourcesResult,
3010 external_images: &FnvHashMap<PhysicalImageViewId, RenderGraphPlanExternalImage>,
3011 intermediate_images: &FnvHashMap<PhysicalImageId, RenderGraphImageSpecification>,
3012) {
3013 log::trace!("-- IMAGES --");
3014 for (physical_id, intermediate_image_spec) in intermediate_images {
3015 log::trace!(
3016 "Intermediate Image: {:?} {:?}",
3017 physical_id,
3018 intermediate_image_spec
3019 );
3020 }
3021
3022 for (physical_id, external_image) in external_images {
3023 log::trace!(
3024 "External Image: {:?} {:?}",
3025 assign_physical_resources_result.image_views[physical_id.0].physical_image,
3026 external_image
3027 );
3028 }
3029}
3030
3031#[allow(dead_code)]
3032fn print_final_buffers(
3033 external_buffers: &FnvHashMap<PhysicalBufferId, RenderGraphPlanExternalBuffer>,
3034 intermediate_buffers: &FnvHashMap<PhysicalBufferId, RenderGraphBufferSpecification>,
3035) {
3036 log::trace!("-- BUFFERS --");
3037 for (physical_id, intermediate_image_spec) in intermediate_buffers {
3038 log::trace!(
3039 "Intermediate Buffer: {:?} {:?}",
3040 physical_id,
3041 intermediate_image_spec
3042 );
3043 }
3044 for (physical_id, external_image) in external_buffers {
3045 log::trace!("External Buffer: {:?} {:?}", physical_id, external_image);
3046 }
3047}
3048
3049#[allow(dead_code)]
3050fn print_final_resource_usages(
3051 graph: &RenderGraphBuilder,
3052 assign_physical_resources_result: &AssignPhysicalResourcesResult,
3053 constraint_results: &DetermineConstraintsResult,
3054 renderpasses: &Vec<RenderGraphOutputPass>,
3055) {
3056 fn print_image_resource_usage(
3057 graph: &RenderGraphBuilder,
3058 assign_physical_resources_result: &AssignPhysicalResourcesResult,
3059 constraint_results: &DetermineConstraintsResult,
3060 image: RenderGraphImageUsageId,
3061 prefix: &str,
3062 ) {
3063 let physical_image = assign_physical_resources_result.image_usage_to_physical[&image];
3064 let write_name = graph.image_resource(image).name;
3065 log::debug!(
3066 " {}: {:?} Name: {:?} Constraints: {:?}",
3067 prefix,
3068 physical_image,
3069 write_name,
3070 constraint_results.images[&image]
3071 );
3072 }
3073
3074 fn print_buffer_resource_usage(
3075 graph: &RenderGraphBuilder,
3076 assign_physical_resources_result: &AssignPhysicalResourcesResult,
3077 constraint_results: &DetermineConstraintsResult,
3078 buffer: RenderGraphBufferUsageId,
3079 prefix: &str,
3080 ) {
3081 let physical_buffer = assign_physical_resources_result.buffer_usage_to_physical[&buffer];
3082 let write_name = graph.buffer_resource(buffer).name;
3083 log::debug!(
3084 " {}: {:?} Name: {:?} Constraints: {:?}",
3085 prefix,
3086 physical_buffer,
3087 write_name,
3088 constraint_results.buffers[&buffer]
3089 );
3090 }
3091
3092 log::debug!("-- RESOURCE USAGE --");
3093 for (pass_index, pass) in renderpasses.iter().enumerate() {
3094 log::debug!("pass {}", pass_index);
3095
3096 let node = graph.node(pass.node());
3097 log::debug!(" subpass {:?} {:?}", pass.node(), node.name);
3098
3099 for (color_attachment_index, color_attachment) in node.color_attachments.iter().enumerate()
3100 {
3101 if let Some(color_attachment) = color_attachment {
3102 let read_or_write = color_attachment
3103 .read_image
3104 .or_else(|| color_attachment.write_image)
3105 .unwrap();
3106 print_image_resource_usage(
3107 graph,
3108 assign_physical_resources_result,
3109 constraint_results,
3110 read_or_write,
3111 &format!("Color Attachment {}", color_attachment_index),
3112 );
3113 }
3114 }
3115
3116 for (resolve_attachment_index, resolve_attachment) in
3117 node.resolve_attachments.iter().enumerate()
3118 {
3119 if let Some(resolve_attachment) = resolve_attachment {
3120 print_image_resource_usage(
3121 graph,
3122 assign_physical_resources_result,
3123 constraint_results,
3124 resolve_attachment.write_image,
3125 &format!("Resolve Attachment {}", resolve_attachment_index),
3126 );
3127 }
3128 }
3129
3130 if let Some(depth_attachment) = &node.depth_attachment {
3131 let read_or_write = depth_attachment
3132 .read_image
3133 .or_else(|| depth_attachment.write_image)
3134 .unwrap();
3135 print_image_resource_usage(
3136 graph,
3137 assign_physical_resources_result,
3138 constraint_results,
3139 read_or_write,
3140 "Depth Attachment",
3141 );
3142 }
3143
3144 for &image in &node.sampled_images {
3145 print_image_resource_usage(
3146 graph,
3147 assign_physical_resources_result,
3148 constraint_results,
3149 image,
3150 "Sampled",
3151 );
3152 }
3153
3154 for &image in &node.storage_image_creates {
3155 print_image_resource_usage(
3156 graph,
3157 assign_physical_resources_result,
3158 constraint_results,
3159 image,
3160 "Storage Image (Create)",
3161 );
3162 }
3163
3164 for &image in &node.storage_image_reads {
3165 print_image_resource_usage(
3166 graph,
3167 assign_physical_resources_result,
3168 constraint_results,
3169 image,
3170 "Storage Image (Read)",
3171 );
3172 }
3173
3174 for &image in &node.storage_image_modifies {
3175 print_image_resource_usage(
3176 graph,
3177 assign_physical_resources_result,
3178 constraint_results,
3179 image,
3180 "Storage Image (Modify)",
3181 );
3182 }
3183
3184 for &image in &node.copy_src_image_reads {
3185 print_image_resource_usage(
3186 graph,
3187 assign_physical_resources_result,
3188 constraint_results,
3189 image,
3190 "Copy Src Image",
3191 );
3192 }
3193
3194 for &image in &node.copy_dst_image_writes {
3195 print_image_resource_usage(
3196 graph,
3197 assign_physical_resources_result,
3198 constraint_results,
3199 image,
3200 "Copy Dst Image",
3201 );
3202 }
3203
3204 for &buffer in &node.vertex_buffer_reads {
3205 print_buffer_resource_usage(
3206 graph,
3207 assign_physical_resources_result,
3208 constraint_results,
3209 buffer,
3210 "Vertex Buffer",
3211 );
3212 }
3213
3214 for &buffer in &node.index_buffer_reads {
3215 print_buffer_resource_usage(
3216 graph,
3217 assign_physical_resources_result,
3218 constraint_results,
3219 buffer,
3220 "Index Buffer",
3221 );
3222 }
3223
3224 for &buffer in &node.indirect_buffer_reads {
3225 print_buffer_resource_usage(
3226 graph,
3227 assign_physical_resources_result,
3228 constraint_results,
3229 buffer,
3230 "Indirect Buffer",
3231 );
3232 }
3233
3234 for &buffer in &node.uniform_buffer_reads {
3235 print_buffer_resource_usage(
3236 graph,
3237 assign_physical_resources_result,
3238 constraint_results,
3239 buffer,
3240 "Uniform Buffer",
3241 );
3242 }
3243
3244 for &buffer in &node.storage_buffer_creates {
3245 print_buffer_resource_usage(
3246 graph,
3247 assign_physical_resources_result,
3248 constraint_results,
3249 buffer,
3250 "Storage Buffer (Create)",
3251 );
3252 }
3253
3254 for &buffer in &node.storage_buffer_reads {
3255 print_buffer_resource_usage(
3256 graph,
3257 assign_physical_resources_result,
3258 constraint_results,
3259 buffer,
3260 "Storage Buffer (Read)",
3261 );
3262 }
3263
3264 for &buffer in &node.storage_buffer_modifies {
3265 print_buffer_resource_usage(
3266 graph,
3267 assign_physical_resources_result,
3268 constraint_results,
3269 buffer,
3270 "Storage Buffer (Modify)",
3271 );
3272 }
3273
3274 for &buffer in &node.copy_src_buffer_reads {
3275 print_buffer_resource_usage(
3276 graph,
3277 assign_physical_resources_result,
3278 constraint_results,
3279 buffer,
3280 "Copy Src Buffer",
3281 );
3282 }
3283
3284 for &buffer in &node.copy_dst_buffer_writes {
3285 print_buffer_resource_usage(
3286 graph,
3287 assign_physical_resources_result,
3288 constraint_results,
3289 buffer,
3290 "Copy Dst Buffer",
3291 );
3292 }
3293 }
3294
3295 log::debug!("External Resources");
3296
3297 for external_image in &graph.external_images {
3298 if let Some(input_usage) = external_image.input_usage {
3299 print_image_resource_usage(
3300 graph,
3301 assign_physical_resources_result,
3302 constraint_results,
3303 input_usage,
3304 "Read External Image",
3305 );
3306 }
3307
3308 if let Some(output_usage) = external_image.output_usage {
3309 print_image_resource_usage(
3310 graph,
3311 assign_physical_resources_result,
3312 constraint_results,
3313 output_usage,
3314 "Write External Image",
3315 );
3316 }
3317 }
3318
3319 for external_buffer in &graph.external_buffers {
3320 if let Some(input_usage) = external_buffer.input_usage {
3321 print_buffer_resource_usage(
3322 graph,
3323 assign_physical_resources_result,
3324 constraint_results,
3325 input_usage,
3326 "Read External Buffer",
3327 );
3328 }
3329
3330 if let Some(output_usage) = external_buffer.output_usage {
3331 print_buffer_resource_usage(
3332 graph,
3333 assign_physical_resources_result,
3334 constraint_results,
3335 output_usage,
3336 "Write External Buffer",
3337 );
3338 }
3339 }
3340}
3341
3342#[derive(Debug)]
3343pub struct RenderGraphPlanExternalImage {
3344 pub id: RenderGraphExternalImageId,
3345 pub resource: ResourceArc<ImageViewResource>,
3346}
3347
3348#[derive(Debug)]
3349pub struct RenderGraphPlanExternalBuffer {
3350 pub id: RenderGraphExternalBufferId,
3351 pub resource: ResourceArc<BufferResource>,
3352}
3353
3354pub struct RenderGraphPlan {
3357 pub(super) passes: Vec<RenderGraphOutputPass>,
3358 pub(super) external_images: FnvHashMap<PhysicalImageViewId, RenderGraphPlanExternalImage>,
3359 pub(super) external_buffers: FnvHashMap<PhysicalBufferId, RenderGraphPlanExternalBuffer>,
3360 pub(super) intermediate_images: FnvHashMap<PhysicalImageId, RenderGraphImageSpecification>,
3361 pub(super) intermediate_buffers: FnvHashMap<PhysicalBufferId, RenderGraphBufferSpecification>,
3362 pub(super) image_views: Vec<RenderGraphImageView>, pub(super) node_to_pass_index: FnvHashMap<RenderGraphNodeId, usize>,
3364 pub(super) _image_usage_to_physical: FnvHashMap<RenderGraphImageUsageId, PhysicalImageId>,
3365 pub(super) image_usage_to_view: FnvHashMap<RenderGraphImageUsageId, PhysicalImageViewId>,
3366 pub(super) buffer_usage_to_physical: FnvHashMap<RenderGraphBufferUsageId, PhysicalBufferId>,
3367
3368 pub(super) visit_node_callbacks:
3370 FnvHashMap<RenderGraphNodeId, RenderGraphNodeVisitNodeCallback>,
3371 pub(super) _render_phase_dependencies:
3372 FnvHashMap<RenderGraphNodeId, FnvHashSet<RenderPhaseIndex>>,
3373}
3374
3375impl RenderGraphPlan {
3376 #[profiling::function]
3377 pub(super) fn new(
3378 mut graph: RenderGraphBuilder,
3379 swapchain_surface_info: &SwapchainSurfaceInfo,
3380 ) -> RenderGraphPlan {
3381 log::trace!("-- Create render graph plan --");
3382
3383 let builtin_final_node =
3389 graph.add_callback_node("BuiltinFinalNode", RenderGraphQueue::DefaultGraphics);
3390
3391 let mut node_execution_order = determine_node_order(&graph);
3401 node_execution_order.push(builtin_final_node);
3402
3403 log::trace!("Execution order of unculled nodes:");
3405 for node in &node_execution_order {
3406 log::trace!(" Node {:?} {:?}", node, graph.node(*node).name());
3407 }
3408
3409 let mut constraint_results =
3417 determine_constraints(&graph, &node_execution_order, swapchain_surface_info);
3418
3419 insert_resolves(&mut graph, &node_execution_order, &mut constraint_results);
3431
3432 let assign_virtual_images_result =
3440 assign_virtual_resources(&graph, &node_execution_order, &mut constraint_results);
3441
3442 let mut passes = build_physical_passes(
3446 &graph,
3447 &node_execution_order,
3448 &constraint_results,
3449 &assign_virtual_images_result,
3450 );
3451
3452 let assign_physical_resources_result = assign_physical_resources(
3457 &graph,
3458 &constraint_results,
3459 &assign_virtual_images_result,
3460 &mut passes,
3461 );
3462
3463 let node_barriers = build_node_barriers(
3467 &graph,
3468 &node_execution_order,
3469 &constraint_results,
3470 &assign_physical_resources_result, builtin_final_node,
3472 );
3473
3474 print_node_barriers(&node_barriers);
3475
3476 build_pass_barriers(
3484 &graph,
3485 &node_execution_order,
3486 &constraint_results,
3487 &assign_physical_resources_result,
3488 &node_barriers,
3489 &mut passes,
3490 );
3491
3492 let output_passes = create_output_passes(&graph, passes);
3511
3512 let mut external_images: FnvHashMap<PhysicalImageViewId, RenderGraphPlanExternalImage> =
3517 Default::default();
3518 let mut external_image_physical_ids = FnvHashSet::default();
3519 for external_image in &graph.external_images {
3520 let input_physical_view_id = external_image
3521 .input_usage
3522 .map(|usage| assign_physical_resources_result.image_usage_to_image_view[&usage]);
3523
3524 let output_physical_view_id = external_image
3525 .output_usage
3526 .map(|usage| assign_physical_resources_result.image_usage_to_image_view[&usage]);
3527
3528 if let Some(physical_view_id) = input_physical_view_id.or(output_physical_view_id) {
3529 assert!(
3531 input_physical_view_id.is_none()
3532 || output_physical_view_id.is_none()
3533 || input_physical_view_id == output_physical_view_id
3534 );
3535
3536 external_images.insert(
3537 physical_view_id,
3538 RenderGraphPlanExternalImage {
3539 id: external_image.external_image_id,
3540 resource: external_image.image_resource.clone(),
3541 },
3542 );
3543
3544 external_image_physical_ids.insert(
3545 assign_physical_resources_result.image_views[physical_view_id.0].physical_image,
3546 );
3547 }
3548 }
3549
3550 let mut external_buffers: FnvHashMap<PhysicalBufferId, RenderGraphPlanExternalBuffer> =
3551 Default::default();
3552 for external_buffer in &graph.external_buffers {
3554 let input_physical_id = external_buffer
3555 .input_usage
3556 .map(|usage| assign_physical_resources_result.buffer_usage_to_physical[&usage]);
3557
3558 let output_physical_id = external_buffer
3559 .output_usage
3560 .map(|usage| assign_physical_resources_result.buffer_usage_to_physical[&usage]);
3561
3562 if let Some(physical_id) = input_physical_id.or(output_physical_id) {
3563 assert!(
3565 input_physical_id.is_none()
3566 || output_physical_id.is_none()
3567 || input_physical_id == output_physical_id
3568 );
3569
3570 external_buffers.insert(
3571 physical_id,
3572 RenderGraphPlanExternalBuffer {
3573 id: external_buffer.external_buffer_id,
3574 resource: external_buffer.buffer_resource.clone(),
3575 },
3576 );
3577 }
3578 }
3579
3580 let mut intermediate_images: FnvHashMap<PhysicalImageId, RenderGraphImageSpecification> =
3581 Default::default();
3582 for (index, specification) in assign_physical_resources_result
3583 .image_specifications
3584 .iter()
3585 .enumerate()
3586 {
3587 let physical_image = PhysicalImageId(index);
3588
3589 if external_image_physical_ids.contains(&physical_image) {
3590 continue;
3591 }
3592
3593 intermediate_images.insert(physical_image, specification.clone());
3594 }
3595
3596 let mut intermediate_buffers: FnvHashMap<PhysicalBufferId, RenderGraphBufferSpecification> =
3597 Default::default();
3598 for (index, specification) in assign_physical_resources_result
3599 .buffer_specifications
3600 .iter()
3601 .enumerate()
3602 {
3603 let physical_buffer = PhysicalBufferId(index);
3604
3605 if external_buffers.contains_key(&physical_buffer) {
3606 continue;
3607 }
3608
3609 intermediate_buffers.insert(physical_buffer, specification.clone());
3610 }
3611
3612 print_final_images(
3613 &assign_physical_resources_result,
3614 &external_images,
3615 &intermediate_images,
3616 );
3617 print_final_buffers(&external_buffers, &intermediate_buffers);
3618
3619 print_final_resource_usages(
3620 &graph,
3621 &assign_physical_resources_result,
3622 &constraint_results,
3623 &output_passes,
3624 );
3625
3626 let mut node_to_pass_index = FnvHashMap::default();
3631 for (pass_index, pass) in output_passes.iter().enumerate() {
3632 node_to_pass_index.insert(pass.node(), pass_index);
3633 }
3634
3635 RenderGraphPlan {
3636 passes: output_passes,
3637 external_images,
3638 external_buffers,
3639 intermediate_images,
3640 intermediate_buffers,
3641 image_views: assign_physical_resources_result.image_views,
3642 node_to_pass_index,
3643 _image_usage_to_physical: assign_physical_resources_result.image_usage_to_physical,
3644 image_usage_to_view: assign_physical_resources_result.image_usage_to_image_view,
3645 buffer_usage_to_physical: assign_physical_resources_result.buffer_usage_to_physical,
3646
3647 visit_node_callbacks: graph.visit_node_callbacks,
3648 _render_phase_dependencies: graph.render_phase_dependencies,
3649 }
3650 }
3651}