From 3847a6807afa58efa9225973f9112b57f6f17058 Mon Sep 17 00:00:00 2001 From: Jerome Humbert Date: Sat, 6 Aug 2022 23:34:00 +0100 Subject: [PATCH 1/5] Document `PipelineCache` and related types Add documenting comments to `PipelineCache` and a few other related types in the same file. --- .../src/render_resource/pipeline_cache.rs | 91 ++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 341e3b21646ef..f81acb90ddc7e 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -25,6 +25,9 @@ enum PipelineDescriptor { ComputePipelineDescriptor(Box), } +/// Union of a render and compute pipeline. +/// +/// Used to store an heterogenous collection of render and compute pipelines together. #[derive(Debug)] pub enum Pipeline { RenderPipeline(RenderPipeline), @@ -52,14 +55,28 @@ struct CachedPipeline { state: CachedPipelineState, } +/// State of a cached render pipeline. #[derive(Debug)] pub enum CachedPipelineState { + /// The pipeline GPU object is queued for creation. Queued, + /// The pipeline GPU object was created successfully and is available (allocated on the GPU). Ok(Pipeline), + /// An error occurred while trying to create the pipeline GPU object. Err(PipelineCacheError), } impl CachedPipelineState { + /// Convenience method to "unwrap" a pipeline state into its underlying GPU object. + /// + /// # Returns + /// + /// The method returns the allocated pipeline GPU object. + /// + /// # Panics + /// + /// This method panics if the pipeline GPU object is not available, either because it is + /// pending creation or because an error occurred while attempting to create GPU object. pub fn unwrap(&self) -> &Pipeline { match self { CachedPipelineState::Ok(pipeline) => pipeline, @@ -72,7 +89,7 @@ impl CachedPipelineState { } #[derive(Default)] -pub struct ShaderData { +struct ShaderData { pipelines: HashSet, processed_shaders: HashMap, Arc>, resolved_imports: HashMap>, @@ -263,6 +280,18 @@ impl LayoutCache { } } +/// Cache for render and compute pipelines. +/// +/// The cache stores existing render and compute pipelines allocated on the GPU, as well as +/// pending creation. Pipelines inserted into the cache are identified by a unique ID, which +/// can be used to retrieve the actual GPU object once it's ready. The creation of the GPU +/// pipeline object is deferred to the [`RenderStage::Render`] stage, just before the render +/// graph starts being processed, as this requires access to the GPU. +/// +/// Note that the cache do not perform automatic deduplication of identical pipelines. It is +/// up to the user not to insert the same pipeline twice to avoid wasting GPU resources. +/// +/// [`RenderStage::Render`]: crate::RenderStage::Render pub struct PipelineCache { layout_cache: LayoutCache, shader_cache: ShaderCache, @@ -272,6 +301,7 @@ pub struct PipelineCache { } impl PipelineCache { + /// Create a new pipeline cache associated with the given render device. pub fn new(device: RenderDevice) -> Self { Self { device, @@ -282,16 +312,25 @@ impl PipelineCache { } } + /// Get the state of a cached render pipeline. + /// + /// See [`PipelineCache::queue_render_pipeline()`]. #[inline] pub fn get_render_pipeline_state(&self, id: CachedRenderPipelineId) -> &CachedPipelineState { &self.pipelines[id.0].state } + /// Get the state of a cached compute pipeline. + /// + /// See [`PipelineCache::queue_compute_pipeline()`]. #[inline] pub fn get_compute_pipeline_state(&self, id: CachedComputePipelineId) -> &CachedPipelineState { &self.pipelines[id.0].state } + /// Get the render pipeline descriptor a cached render pipeline was inserted from. + /// + /// See [`PipelineCache::queue_render_pipeline()`]. #[inline] pub fn get_render_pipeline_descriptor( &self, @@ -303,6 +342,9 @@ impl PipelineCache { } } + /// Get the compute pipeline descriptor a cached render pipeline was inserted from. + /// + /// See [`PipelineCache::queue_compute_pipeline()`]. #[inline] pub fn get_compute_pipeline_descriptor( &self, @@ -314,6 +356,13 @@ impl PipelineCache { } } + /// Try to retrieve a render pipeline GPU object from a cached ID. + /// + /// # Returns + /// + /// This method returns a successfully created render pipeline if any, or `None` if the pipeline + /// was not created yet or if there was an error during creation. You can check the actual creation + /// state with [`PipelineCache::get_render_pipeline_state()`]. #[inline] pub fn get_render_pipeline(&self, id: CachedRenderPipelineId) -> Option<&RenderPipeline> { if let CachedPipelineState::Ok(Pipeline::RenderPipeline(pipeline)) = @@ -325,6 +374,13 @@ impl PipelineCache { } } + /// Try to retrieve a compute pipeline GPU object from a cached ID. + /// + /// # Returns + /// + /// This method returns a successfully created compute pipeline if any, or `None` if the pipeline + /// was not created yet or if there was an error during creation. You can check the actual creation + /// state with [`PipelineCache::get_compute_pipeline_state()`]. #[inline] pub fn get_compute_pipeline(&self, id: CachedComputePipelineId) -> Option<&ComputePipeline> { if let CachedPipelineState::Ok(Pipeline::ComputePipeline(pipeline)) = @@ -336,6 +392,19 @@ impl PipelineCache { } } + /// Insert a render pipeline into the cache, and queue its creation. + /// + /// The pipeline is always inserted and queued for creation. There is no attempt to deduplicate it with + /// an already cached pipeline. + /// + /// # Returns + /// + /// This method returns the unique render shader ID of the cached pipeline, which can be used to query + /// the caching state with [`get_render_pipeline_state()`] and to retrieve the created GPU pipeline once + /// it's ready with [`get_render_pipeline()`]. + /// + /// [`get_render_pipeline_state()`]: PipelineCache::get_render_pipeline_state + /// [`get_render_pipeline()`]: PipelineCache::get_render_pipeline pub fn queue_render_pipeline( &mut self, descriptor: RenderPipelineDescriptor, @@ -349,6 +418,19 @@ impl PipelineCache { id } + /// Insert a compute pipeline into the cache, and queue its creation. + /// + /// The pipeline is always inserted and queued for creation. There is no attempt to deduplicate it with + /// an already cached pipeline. + /// + /// # Returns + /// + /// This method returns the unique compute shader ID of the cached pipeline, which can be used to query + /// the caching state with [`get_compute_pipeline_state()`] and to retrieve the created GPU pipeline once + /// it's ready with [`get_compute_pipeline()`]. + /// + /// [`get_compute_pipeline_state()`]: PipelineCache::get_compute_pipeline_state + /// [`get_compute_pipeline()`]: PipelineCache::get_compute_pipeline pub fn queue_compute_pipeline( &mut self, descriptor: ComputePipelineDescriptor, @@ -494,6 +576,12 @@ impl PipelineCache { CachedPipelineState::Ok(Pipeline::ComputePipeline(pipeline)) } + /// Process the pipeline queue and create all pending pipelines if possible. + /// + /// This is generally called automatically during the [`RenderStage::Render`] stage, but can + /// be called manually to force creation at a different time. + /// + /// [`RenderStage::Render`]: crate::RenderStage::Render pub fn process_queue(&mut self) { let waiting_pipelines = mem::take(&mut self.waiting_pipelines); let mut pipelines = mem::take(&mut self.pipelines); @@ -654,6 +742,7 @@ fn log_shader_error(source: &ProcessedShader, error: &AsModuleDescriptorError) { } } +/// Type of error returned by a [`PipelineCache`] when the creation of a GPU pipeline object failed. #[derive(Error, Debug)] pub enum PipelineCacheError { #[error( From 4995b59028a0f18c95b9441d3c307c6b0b8b21e0 Mon Sep 17 00:00:00 2001 From: Jerome Humbert Date: Sun, 7 Aug 2022 20:45:34 +0100 Subject: [PATCH 2/5] Update crates/bevy_render/src/render_resource/pipeline_cache.rs Co-authored-by: Alice Cecile --- crates/bevy_render/src/render_resource/pipeline_cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index f81acb90ddc7e..ebef7621dc56c 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -25,7 +25,7 @@ enum PipelineDescriptor { ComputePipelineDescriptor(Box), } -/// Union of a render and compute pipeline. +/// A pipeline used to send data to the GPU. /// /// Used to store an heterogenous collection of render and compute pipelines together. #[derive(Debug)] From 753bf37deaa3658dabbe3043c2529b96664b8186 Mon Sep 17 00:00:00 2001 From: Jerome Humbert Date: Sun, 7 Aug 2022 20:46:18 +0100 Subject: [PATCH 3/5] Revert pub change of ShaderData --- crates/bevy_render/src/render_resource/pipeline_cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index ebef7621dc56c..d174fdc7f891d 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -89,7 +89,7 @@ impl CachedPipelineState { } #[derive(Default)] -struct ShaderData { +pub struct ShaderData { pipelines: HashSet, processed_shaders: HashMap, Arc>, resolved_imports: HashMap>, From 0daea6767e6f5a2eec8672da0859a7f11b789742 Mon Sep 17 00:00:00 2001 From: Jerome Humbert Date: Fri, 2 Sep 2022 09:47:51 +0100 Subject: [PATCH 4/5] Fix from cart's comment --- crates/bevy_render/src/render_resource/pipeline_cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 1b359bdc511ce..50381049f4228 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -25,7 +25,7 @@ enum PipelineDescriptor { ComputePipelineDescriptor(Box), } -/// A pipeline used to send data to the GPU. +/// A pipeline defining the data layout and shader logic for a specific GPU task. /// /// Used to store an heterogenous collection of render and compute pipelines together. #[derive(Debug)] From 15aa401a0cec9977633a3991feb40701d47afa14 Mon Sep 17 00:00:00 2001 From: Jerome Humbert Date: Fri, 2 Sep 2022 14:51:30 +0100 Subject: [PATCH 5/5] Document newly public items --- .../bevy_render/src/render_resource/pipeline_cache.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/bevy_render/src/render_resource/pipeline_cache.rs b/crates/bevy_render/src/render_resource/pipeline_cache.rs index 5e535a4cf560d..dbcc5ef93efd9 100644 --- a/crates/bevy_render/src/render_resource/pipeline_cache.rs +++ b/crates/bevy_render/src/render_resource/pipeline_cache.rs @@ -24,6 +24,10 @@ use wgpu::{ VertexBufferLayout as RawVertexBufferLayout, }; +/// A descriptor for a [`Pipeline`]. +/// +/// Used to store an heterogenous collection of render and compute pipeline descriptors together. +#[derive(Debug)] pub enum PipelineDescriptor { RenderPipelineDescriptor(Box), ComputePipelineDescriptor(Box), @@ -40,17 +44,21 @@ pub enum Pipeline { type CachedPipelineId = usize; +/// Index of a cached render pipeline in a [`PipelineCache`]. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub struct CachedRenderPipelineId(CachedPipelineId); impl CachedRenderPipelineId { + /// An invalid cached render pipeline index, often used to initialize a variable. pub const INVALID: Self = CachedRenderPipelineId(usize::MAX); } +/// Index of a cached compute pipeline in a [`PipelineCache`]. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub struct CachedComputePipelineId(CachedPipelineId); impl CachedComputePipelineId { + /// An invalid cached compute pipeline index, often used to initialize a variable. pub const INVALID: Self = CachedComputePipelineId(usize::MAX); } @@ -59,7 +67,7 @@ pub struct CachedPipeline { pub state: CachedPipelineState, } -/// State of a cached render pipeline. +/// State of a cached pipeline inserted into a [`PipelineCache`]. #[derive(Debug)] pub enum CachedPipelineState { /// The pipeline GPU object is queued for creation.