@@ -7,6 +7,8 @@ mod query;
7
7
mod render;
8
8
mod transfer;
9
9
10
+ use std:: num:: NonZeroU32 ;
11
+
10
12
pub use self :: bundle:: * ;
11
13
pub use self :: compute:: * ;
12
14
pub use self :: draw:: * ;
@@ -15,7 +17,9 @@ pub use self::render::*;
15
17
pub use self :: transfer:: * ;
16
18
17
19
use crate :: error:: { ErrorFormatter , PrettyError } ;
20
+ use crate :: init_tracker:: TextureInitRange ;
18
21
use crate :: init_tracker:: { BufferInitTrackerAction , MemoryInitKind , TextureInitTrackerAction } ;
22
+ use crate :: track:: TextureSelector ;
19
23
use crate :: {
20
24
hub:: { Global , GlobalIdentityHandlerFactory , HalApi , Storage , Token } ,
21
25
id,
@@ -68,9 +72,11 @@ pub struct BakedCommands<A: hal::Api> {
68
72
pub ( crate ) list : Vec < A :: CommandBuffer > ,
69
73
pub ( crate ) trackers : TrackerSet ,
70
74
buffer_memory_init_actions : Vec < BufferInitTrackerAction > ,
75
+ texture_memory_init_actions : Vec < TextureInitTrackerAction > ,
71
76
}
72
77
73
78
pub ( crate ) struct DestroyedBufferError ( pub id:: BufferId ) ;
79
+ pub ( crate ) struct DestroyedTextureError ( pub id:: TextureId ) ;
74
80
75
81
impl < A : hal:: Api > BakedCommands < A > {
76
82
pub ( crate ) fn initialize_buffer_memory (
@@ -79,6 +85,7 @@ impl<A: hal::Api> BakedCommands<A> {
79
85
buffer_guard : & mut Storage < Buffer < A > , id:: BufferId > ,
80
86
) -> Result < ( ) , DestroyedBufferError > {
81
87
let mut ranges = Vec :: new ( ) ;
88
+ // TODO: neighboring NeedsInitializedMemory ranges in init_actions are not collapsed!
82
89
for buffer_use in self . buffer_memory_init_actions . drain ( ..) {
83
90
let buffer = buffer_guard
84
91
. get_mut ( buffer_use. id )
@@ -130,7 +137,94 @@ impl<A: hal::Api> BakedCommands<A> {
130
137
}
131
138
}
132
139
}
140
+ Ok ( ( ) )
141
+ }
133
142
143
+ pub ( crate ) fn initialize_texture_memory (
144
+ & mut self ,
145
+ device_tracker : & mut TrackerSet ,
146
+ texture_guard : & mut Storage < Texture < A > , id:: TextureId > ,
147
+ ) -> Result < ( ) , DestroyedTextureError > {
148
+ let mut ranges = Vec :: new ( ) ;
149
+ for texture_use in self . texture_memory_init_actions . drain ( ..) {
150
+ let texture = texture_guard
151
+ . get_mut ( texture_use. id )
152
+ . map_err ( |_| DestroyedTextureError ( texture_use. id ) ) ?;
153
+ let use_range = texture_use. range ;
154
+ let affected_mip_trackers = texture
155
+ . initialization_status
156
+ . mips
157
+ . iter_mut ( )
158
+ . enumerate ( )
159
+ . skip ( use_range. mip_range . start as usize )
160
+ . take ( ( use_range. mip_range . end - use_range. mip_range . start ) as usize ) ;
161
+
162
+ match texture_use. kind {
163
+ MemoryInitKind :: ImplicitlyInitialized => {
164
+ for ( _, mip_tracker) in affected_mip_trackers {
165
+ mip_tracker
166
+ . drain ( use_range. layer_range . clone ( ) )
167
+ . for_each ( drop) ;
168
+ }
169
+ }
170
+ MemoryInitKind :: NeedsInitializedMemory => {
171
+ ranges. clear ( ) ;
172
+ for ( mip_level, mip_tracker) in affected_mip_trackers {
173
+ for layer_range in mip_tracker. drain ( use_range. layer_range . clone ( ) ) {
174
+ // TODO: Don't treat every mip_level separately and collapse equal layer ranges!
175
+ ranges. push ( TextureInitRange {
176
+ mip_range : mip_level as u32 ..( mip_level as u32 + 1 ) ,
177
+ layer_range,
178
+ } )
179
+ }
180
+ }
181
+
182
+ let raw_texture = texture
183
+ . raw
184
+ . as_ref ( )
185
+ . ok_or ( DestroyedTextureError ( texture_use. id ) ) ?;
186
+
187
+ for range in & ranges {
188
+ // TODO: D24 formats are not allowed to support COPY_DST!! (and on the rest we don't enforce it)
189
+ // -> This would mean we need use clear passes whenever applicable and fall back to copies or even shader writes. Need to figure this out.
190
+ // --> Depending on the outcome we may decide to skip all this elaborate range collapsing anyways
191
+
192
+ // Don't do use_replace since the texture may already no longer have a ref_count.
193
+ // However, we *know* that it is currently in use, so the tracker must already know about it.
194
+ let transition = device_tracker. textures . change_replace_tracked (
195
+ id:: Valid ( texture_use. id ) ,
196
+ TextureSelector {
197
+ levels : range. mip_range . clone ( ) ,
198
+ layers : range. layer_range . clone ( ) ,
199
+ } ,
200
+ hal:: TextureUses :: COPY_DST ,
201
+ ) ;
202
+ unsafe {
203
+ self . encoder . transition_textures (
204
+ transition. map ( |pending| pending. into_hal ( texture) ) ,
205
+ ) ;
206
+ self . encoder . clear_texture (
207
+ raw_texture,
208
+ & ranges
209
+ . iter ( )
210
+ . map ( |r| wgt:: ImageSubresourceRange {
211
+ aspect : wgt:: TextureAspect :: All ,
212
+ base_mip_level : r. mip_range . start ,
213
+ mip_level_count : NonZeroU32 :: new (
214
+ r. mip_range . end - r. mip_range . start ,
215
+ ) ,
216
+ base_array_layer : r. layer_range . start ,
217
+ array_layer_count : NonZeroU32 :: new (
218
+ r. layer_range . end - r. layer_range . start ,
219
+ ) ,
220
+ } )
221
+ . collect :: < Vec < wgt:: ImageSubresourceRange > > ( ) ,
222
+ ) ;
223
+ }
224
+ }
225
+ }
226
+ }
227
+ }
134
228
Ok ( ( ) )
135
229
}
136
230
}
@@ -236,6 +330,7 @@ impl<A: hal::Api> CommandBuffer<A> {
236
330
list : self . encoder . list ,
237
331
trackers : self . trackers ,
238
332
buffer_memory_init_actions : self . buffer_memory_init_actions ,
333
+ texture_memory_init_actions : self . texture_memory_init_actions ,
239
334
}
240
335
}
241
336
}
0 commit comments