@@ -24,11 +24,18 @@ use wgpu::{
24
24
VertexBufferLayout as RawVertexBufferLayout ,
25
25
} ;
26
26
27
+ /// A descriptor for a [`Pipeline`].
28
+ ///
29
+ /// Used to store an heterogenous collection of render and compute pipeline descriptors together.
30
+ #[ derive( Debug ) ]
27
31
pub enum PipelineDescriptor {
28
32
RenderPipelineDescriptor ( Box < RenderPipelineDescriptor > ) ,
29
33
ComputePipelineDescriptor ( Box < ComputePipelineDescriptor > ) ,
30
34
}
31
35
36
+ /// A pipeline defining the data layout and shader logic for a specific GPU task.
37
+ ///
38
+ /// Used to store an heterogenous collection of render and compute pipelines together.
32
39
#[ derive( Debug ) ]
33
40
pub enum Pipeline {
34
41
RenderPipeline ( RenderPipeline ) ,
@@ -37,17 +44,21 @@ pub enum Pipeline {
37
44
38
45
type CachedPipelineId = usize ;
39
46
47
+ /// Index of a cached render pipeline in a [`PipelineCache`].
40
48
#[ derive( Copy , Clone , Debug , Hash , Eq , PartialEq ) ]
41
49
pub struct CachedRenderPipelineId ( CachedPipelineId ) ;
42
50
43
51
impl CachedRenderPipelineId {
52
+ /// An invalid cached render pipeline index, often used to initialize a variable.
44
53
pub const INVALID : Self = CachedRenderPipelineId ( usize:: MAX ) ;
45
54
}
46
55
56
+ /// Index of a cached compute pipeline in a [`PipelineCache`].
47
57
#[ derive( Copy , Clone , Debug , Hash , Eq , PartialEq ) ]
48
58
pub struct CachedComputePipelineId ( CachedPipelineId ) ;
49
59
50
60
impl CachedComputePipelineId {
61
+ /// An invalid cached compute pipeline index, often used to initialize a variable.
51
62
pub const INVALID : Self = CachedComputePipelineId ( usize:: MAX ) ;
52
63
}
53
64
@@ -56,14 +67,28 @@ pub struct CachedPipeline {
56
67
pub state : CachedPipelineState ,
57
68
}
58
69
70
+ /// State of a cached pipeline inserted into a [`PipelineCache`].
59
71
#[ derive( Debug ) ]
60
72
pub enum CachedPipelineState {
73
+ /// The pipeline GPU object is queued for creation.
61
74
Queued ,
75
+ /// The pipeline GPU object was created successfully and is available (allocated on the GPU).
62
76
Ok ( Pipeline ) ,
77
+ /// An error occurred while trying to create the pipeline GPU object.
63
78
Err ( PipelineCacheError ) ,
64
79
}
65
80
66
81
impl CachedPipelineState {
82
+ /// Convenience method to "unwrap" a pipeline state into its underlying GPU object.
83
+ ///
84
+ /// # Returns
85
+ ///
86
+ /// The method returns the allocated pipeline GPU object.
87
+ ///
88
+ /// # Panics
89
+ ///
90
+ /// This method panics if the pipeline GPU object is not available, either because it is
91
+ /// pending creation or because an error occurred while attempting to create GPU object.
67
92
pub fn unwrap ( & self ) -> & Pipeline {
68
93
match self {
69
94
CachedPipelineState :: Ok ( pipeline) => pipeline,
@@ -271,6 +296,18 @@ impl LayoutCache {
271
296
}
272
297
}
273
298
299
+ /// Cache for render and compute pipelines.
300
+ ///
301
+ /// The cache stores existing render and compute pipelines allocated on the GPU, as well as
302
+ /// pending creation. Pipelines inserted into the cache are identified by a unique ID, which
303
+ /// can be used to retrieve the actual GPU object once it's ready. The creation of the GPU
304
+ /// pipeline object is deferred to the [`RenderStage::Render`] stage, just before the render
305
+ /// graph starts being processed, as this requires access to the GPU.
306
+ ///
307
+ /// Note that the cache do not perform automatic deduplication of identical pipelines. It is
308
+ /// up to the user not to insert the same pipeline twice to avoid wasting GPU resources.
309
+ ///
310
+ /// [`RenderStage::Render`]: crate::RenderStage::Render
274
311
#[ derive( Resource ) ]
275
312
pub struct PipelineCache {
276
313
layout_cache : LayoutCache ,
@@ -285,6 +322,7 @@ impl PipelineCache {
285
322
self . pipelines . iter ( )
286
323
}
287
324
325
+ /// Create a new pipeline cache associated with the given render device.
288
326
pub fn new ( device : RenderDevice ) -> Self {
289
327
Self {
290
328
device,
@@ -295,16 +333,25 @@ impl PipelineCache {
295
333
}
296
334
}
297
335
336
+ /// Get the state of a cached render pipeline.
337
+ ///
338
+ /// See [`PipelineCache::queue_render_pipeline()`].
298
339
#[ inline]
299
340
pub fn get_render_pipeline_state ( & self , id : CachedRenderPipelineId ) -> & CachedPipelineState {
300
341
& self . pipelines [ id. 0 ] . state
301
342
}
302
343
344
+ /// Get the state of a cached compute pipeline.
345
+ ///
346
+ /// See [`PipelineCache::queue_compute_pipeline()`].
303
347
#[ inline]
304
348
pub fn get_compute_pipeline_state ( & self , id : CachedComputePipelineId ) -> & CachedPipelineState {
305
349
& self . pipelines [ id. 0 ] . state
306
350
}
307
351
352
+ /// Get the render pipeline descriptor a cached render pipeline was inserted from.
353
+ ///
354
+ /// See [`PipelineCache::queue_render_pipeline()`].
308
355
#[ inline]
309
356
pub fn get_render_pipeline_descriptor (
310
357
& self ,
@@ -316,6 +363,9 @@ impl PipelineCache {
316
363
}
317
364
}
318
365
366
+ /// Get the compute pipeline descriptor a cached render pipeline was inserted from.
367
+ ///
368
+ /// See [`PipelineCache::queue_compute_pipeline()`].
319
369
#[ inline]
320
370
pub fn get_compute_pipeline_descriptor (
321
371
& self ,
@@ -327,6 +377,13 @@ impl PipelineCache {
327
377
}
328
378
}
329
379
380
+ /// Try to retrieve a render pipeline GPU object from a cached ID.
381
+ ///
382
+ /// # Returns
383
+ ///
384
+ /// This method returns a successfully created render pipeline if any, or `None` if the pipeline
385
+ /// was not created yet or if there was an error during creation. You can check the actual creation
386
+ /// state with [`PipelineCache::get_render_pipeline_state()`].
330
387
#[ inline]
331
388
pub fn get_render_pipeline ( & self , id : CachedRenderPipelineId ) -> Option < & RenderPipeline > {
332
389
if let CachedPipelineState :: Ok ( Pipeline :: RenderPipeline ( pipeline) ) =
@@ -338,6 +395,13 @@ impl PipelineCache {
338
395
}
339
396
}
340
397
398
+ /// Try to retrieve a compute pipeline GPU object from a cached ID.
399
+ ///
400
+ /// # Returns
401
+ ///
402
+ /// This method returns a successfully created compute pipeline if any, or `None` if the pipeline
403
+ /// was not created yet or if there was an error during creation. You can check the actual creation
404
+ /// state with [`PipelineCache::get_compute_pipeline_state()`].
341
405
#[ inline]
342
406
pub fn get_compute_pipeline ( & self , id : CachedComputePipelineId ) -> Option < & ComputePipeline > {
343
407
if let CachedPipelineState :: Ok ( Pipeline :: ComputePipeline ( pipeline) ) =
@@ -349,6 +413,19 @@ impl PipelineCache {
349
413
}
350
414
}
351
415
416
+ /// Insert a render pipeline into the cache, and queue its creation.
417
+ ///
418
+ /// The pipeline is always inserted and queued for creation. There is no attempt to deduplicate it with
419
+ /// an already cached pipeline.
420
+ ///
421
+ /// # Returns
422
+ ///
423
+ /// This method returns the unique render shader ID of the cached pipeline, which can be used to query
424
+ /// the caching state with [`get_render_pipeline_state()`] and to retrieve the created GPU pipeline once
425
+ /// it's ready with [`get_render_pipeline()`].
426
+ ///
427
+ /// [`get_render_pipeline_state()`]: PipelineCache::get_render_pipeline_state
428
+ /// [`get_render_pipeline()`]: PipelineCache::get_render_pipeline
352
429
pub fn queue_render_pipeline (
353
430
& mut self ,
354
431
descriptor : RenderPipelineDescriptor ,
@@ -362,6 +439,19 @@ impl PipelineCache {
362
439
id
363
440
}
364
441
442
+ /// Insert a compute pipeline into the cache, and queue its creation.
443
+ ///
444
+ /// The pipeline is always inserted and queued for creation. There is no attempt to deduplicate it with
445
+ /// an already cached pipeline.
446
+ ///
447
+ /// # Returns
448
+ ///
449
+ /// This method returns the unique compute shader ID of the cached pipeline, which can be used to query
450
+ /// the caching state with [`get_compute_pipeline_state()`] and to retrieve the created GPU pipeline once
451
+ /// it's ready with [`get_compute_pipeline()`].
452
+ ///
453
+ /// [`get_compute_pipeline_state()`]: PipelineCache::get_compute_pipeline_state
454
+ /// [`get_compute_pipeline()`]: PipelineCache::get_compute_pipeline
365
455
pub fn queue_compute_pipeline (
366
456
& mut self ,
367
457
descriptor : ComputePipelineDescriptor ,
@@ -507,6 +597,12 @@ impl PipelineCache {
507
597
CachedPipelineState :: Ok ( Pipeline :: ComputePipeline ( pipeline) )
508
598
}
509
599
600
+ /// Process the pipeline queue and create all pending pipelines if possible.
601
+ ///
602
+ /// This is generally called automatically during the [`RenderStage::Render`] stage, but can
603
+ /// be called manually to force creation at a different time.
604
+ ///
605
+ /// [`RenderStage::Render`]: crate::RenderStage::Render
510
606
pub fn process_queue ( & mut self ) {
511
607
let waiting_pipelines = mem:: take ( & mut self . waiting_pipelines ) ;
512
608
let mut pipelines = mem:: take ( & mut self . pipelines ) ;
@@ -667,6 +763,7 @@ fn log_shader_error(source: &ProcessedShader, error: &AsModuleDescriptorError) {
667
763
}
668
764
}
669
765
766
+ /// Type of error returned by a [`PipelineCache`] when the creation of a GPU pipeline object failed.
670
767
#[ derive( Error , Debug ) ]
671
768
pub enum PipelineCacheError {
672
769
#[ error(
0 commit comments