@@ -3,7 +3,7 @@ use crate::{
3
3
render_graph:: { CommandQueue , Node , ResourceSlots , SystemNode } ,
4
4
renderer:: {
5
5
BufferId , BufferInfo , BufferMapMode , BufferUsage , RenderContext , RenderResourceBinding ,
6
- RenderResourceBindings , RenderResourceContext ,
6
+ RenderResourceContext ,
7
7
} ,
8
8
} ;
9
9
use bevy_core:: AsBytes ;
@@ -50,88 +50,126 @@ impl SystemNode for CameraNode {
50
50
config. 0 = Some ( CameraNodeState {
51
51
camera_name : self . camera_name . clone ( ) ,
52
52
command_queue : self . command_queue . clone ( ) ,
53
- camera_buffer : None ,
54
53
staging_buffer : None ,
55
54
} )
56
55
} ) ;
57
56
Box :: new ( system)
58
57
}
59
58
}
60
59
60
+ const CAMERA_VIEW_PROJ : & str = "CameraViewProj" ;
61
+ const CAMERA_VIEW : & str = "CameraView" ;
62
+
61
63
#[ derive( Debug , Default ) ]
62
64
pub struct CameraNodeState {
63
65
command_queue : CommandQueue ,
64
66
camera_name : Cow < ' static , str > ,
65
- camera_buffer : Option < BufferId > ,
66
67
staging_buffer : Option < BufferId > ,
67
68
}
68
69
70
+ const MATRIX_SIZE : usize = std:: mem:: size_of :: < [ [ f32 ; 4 ] ; 4 ] > ( ) ;
71
+
69
72
pub fn camera_node_system (
70
73
mut state : Local < CameraNodeState > ,
71
- active_cameras : Res < ActiveCameras > ,
74
+ mut active_cameras : ResMut < ActiveCameras > ,
72
75
render_resource_context : Res < Box < dyn RenderResourceContext > > ,
73
- // PERF: this write on RenderResourceAssignments will prevent this system from running in
74
- // parallel with other systems that do the same
75
- mut render_resource_bindings : ResMut < RenderResourceBindings > ,
76
- query : Query < ( & Camera , & GlobalTransform ) > ,
76
+ mut query : Query < ( & Camera , & GlobalTransform ) > ,
77
77
) {
78
78
let render_resource_context = & * * render_resource_context;
79
79
80
- let ( camera, global_transform) = if let Some ( entity) = active_cameras. get ( & state. camera_name ) {
81
- query. get ( entity) . unwrap ( )
82
- } else {
83
- return ;
84
- } ;
80
+ let ( ( camera, global_transform) , bindings) =
81
+ if let Some ( active_camera) = active_cameras. get_mut ( & state. camera_name ) {
82
+ if let Some ( entity) = active_camera. entity {
83
+ ( query. get_mut ( entity) . unwrap ( ) , & mut active_camera. bindings )
84
+ } else {
85
+ return ;
86
+ }
87
+ } else {
88
+ return ;
89
+ } ;
85
90
86
91
let staging_buffer = if let Some ( staging_buffer) = state. staging_buffer {
87
92
render_resource_context. map_buffer ( staging_buffer, BufferMapMode :: Write ) ;
88
93
staging_buffer
89
94
} else {
90
- let size = std:: mem:: size_of :: < [ [ f32 ; 4 ] ; 4 ] > ( ) ;
95
+ let staging_buffer = render_resource_context. create_buffer ( BufferInfo {
96
+ size : MATRIX_SIZE * 2 ,
97
+ buffer_usage : BufferUsage :: COPY_SRC | BufferUsage :: MAP_WRITE ,
98
+ mapped_at_creation : true ,
99
+ } ) ;
100
+
101
+ state. staging_buffer = Some ( staging_buffer) ;
102
+ staging_buffer
103
+ } ;
104
+
105
+ if bindings. get ( CAMERA_VIEW_PROJ ) . is_none ( ) {
91
106
let buffer = render_resource_context. create_buffer ( BufferInfo {
92
- size,
107
+ size : MATRIX_SIZE ,
93
108
buffer_usage : BufferUsage :: COPY_DST | BufferUsage :: UNIFORM ,
94
109
..Default :: default ( )
95
110
} ) ;
96
- render_resource_bindings . set (
97
- & state . camera_name ,
111
+ bindings . set (
112
+ CAMERA_VIEW_PROJ ,
98
113
RenderResourceBinding :: Buffer {
99
114
buffer,
100
- range : 0 ..size as u64 ,
115
+ range : 0 ..MATRIX_SIZE as u64 ,
101
116
dynamic_index : None ,
102
117
} ,
103
118
) ;
104
- state . camera_buffer = Some ( buffer ) ;
119
+ }
105
120
106
- let staging_buffer = render_resource_context. create_buffer ( BufferInfo {
107
- size,
108
- buffer_usage : BufferUsage :: COPY_SRC | BufferUsage :: MAP_WRITE ,
109
- mapped_at_creation : true ,
121
+ if bindings. get ( CAMERA_VIEW ) . is_none ( ) {
122
+ let buffer = render_resource_context. create_buffer ( BufferInfo {
123
+ size : MATRIX_SIZE ,
124
+ buffer_usage : BufferUsage :: COPY_DST | BufferUsage :: UNIFORM ,
125
+ ..Default :: default ( )
110
126
} ) ;
127
+ bindings. set (
128
+ CAMERA_VIEW ,
129
+ RenderResourceBinding :: Buffer {
130
+ buffer,
131
+ range : 0 ..MATRIX_SIZE as u64 ,
132
+ dynamic_index : None ,
133
+ } ,
134
+ ) ;
135
+ }
111
136
112
- state. staging_buffer = Some ( staging_buffer) ;
113
- staging_buffer
114
- } ;
137
+ let view = global_transform. compute_matrix ( ) ;
115
138
116
- let matrix_size = std:: mem:: size_of :: < [ [ f32 ; 4 ] ; 4 ] > ( ) ;
117
- let camera_matrix: [ f32 ; 16 ] =
118
- ( camera. projection_matrix * global_transform. compute_matrix ( ) . inverse ( ) ) . to_cols_array ( ) ;
119
-
120
- render_resource_context. write_mapped_buffer (
121
- staging_buffer,
122
- 0 ..matrix_size as u64 ,
123
- & mut |data, _renderer| {
124
- data[ 0 ..matrix_size] . copy_from_slice ( camera_matrix. as_bytes ( ) ) ;
125
- } ,
126
- ) ;
127
- render_resource_context. unmap_buffer ( staging_buffer) ;
139
+ if let Some ( RenderResourceBinding :: Buffer { buffer, .. } ) = bindings. get ( CAMERA_VIEW ) {
140
+ render_resource_context. write_mapped_buffer (
141
+ staging_buffer,
142
+ 0 ..MATRIX_SIZE as u64 ,
143
+ & mut |data, _renderer| {
144
+ data[ 0 ..MATRIX_SIZE ] . copy_from_slice ( view. to_cols_array_2d ( ) . as_bytes ( ) ) ;
145
+ } ,
146
+ ) ;
147
+ state. command_queue . copy_buffer_to_buffer (
148
+ staging_buffer,
149
+ 0 ,
150
+ * buffer,
151
+ 0 ,
152
+ MATRIX_SIZE as u64 ,
153
+ ) ;
154
+ }
155
+
156
+ if let Some ( RenderResourceBinding :: Buffer { buffer, .. } ) = bindings. get ( CAMERA_VIEW_PROJ ) {
157
+ let view_proj = camera. projection_matrix * view. inverse ( ) ;
158
+ render_resource_context. write_mapped_buffer (
159
+ staging_buffer,
160
+ MATRIX_SIZE as u64 ..( 2 * MATRIX_SIZE ) as u64 ,
161
+ & mut |data, _renderer| {
162
+ data[ 0 ..MATRIX_SIZE ] . copy_from_slice ( view_proj. to_cols_array_2d ( ) . as_bytes ( ) ) ;
163
+ } ,
164
+ ) ;
165
+ state. command_queue . copy_buffer_to_buffer (
166
+ staging_buffer,
167
+ MATRIX_SIZE as u64 ,
168
+ * buffer,
169
+ 0 ,
170
+ MATRIX_SIZE as u64 ,
171
+ ) ;
172
+ }
128
173
129
- let camera_buffer = state. camera_buffer . unwrap ( ) ;
130
- state. command_queue . copy_buffer_to_buffer (
131
- staging_buffer,
132
- 0 ,
133
- camera_buffer,
134
- 0 ,
135
- matrix_size as u64 ,
136
- ) ;
174
+ render_resource_context. unmap_buffer ( staging_buffer) ;
137
175
}
0 commit comments