This commit is contained in:
andriyDev 2025-07-16 19:05:28 -04:00 committed by GitHub
commit 2d1fd85fbe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -18,11 +18,35 @@ use core::{fmt::Debug, hash::Hash};
use thiserror::Error;
use tracing::error;
/// A trait that allows constructing different variants of a render pipeline from a key.
///
/// Note: This is intended for modifying your pipeline descriptor on the basis of a key. If your key
/// contains no data then you don't need to specialize. For example, if you are using the
/// [`AsBindGroup`](crate::render_resource::AsBindGroup) without the `#[bind_group_data]` attribute,
/// you don't need to specialize. Instead, create the pipeline directly from [`PipelineCache`] and
/// store its ID.
///
/// See [`SpecializedRenderPipelines`] for more info.
pub trait SpecializedRenderPipeline {
/// The key that defines each "variant" of the render pipeline.
type Key: Clone + Hash + PartialEq + Eq;
/// Construct a new render pipeline based on the provided key.
fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor;
}
/// A convenience cache for creating different variants of a render pipeline based on some key.
///
/// Some render pipelines may need to be configured differently depending on the exact situation.
/// This cache allows constructing different render pipelines for each situation based on a key,
/// making it easy to A) construct the necessary pipelines, and B) reuse already constructed
/// pipelines.
///
/// Note: This is intended for modifying your pipeline descriptor on the basis of a key. If your key
/// contains no data then you don't need to specialize. For example, if you are using the
/// [`AsBindGroup`](crate::render_resource::AsBindGroup) without the `#[bind_group_data]` attribute,
/// you don't need to specialize. Instead, create the pipeline directly from [`PipelineCache`] and
/// store its ID.
#[derive(Resource)]
pub struct SpecializedRenderPipelines<S: SpecializedRenderPipeline> {
cache: HashMap<S::Key, CachedRenderPipelineId>,
@ -35,24 +59,49 @@ impl<S: SpecializedRenderPipeline> Default for SpecializedRenderPipelines<S> {
}
impl<S: SpecializedRenderPipeline> SpecializedRenderPipelines<S> {
/// Get or create a specialized instance of the pipeline corresponding to `key`.
pub fn specialize(
&mut self,
cache: &PipelineCache,
specialize_pipeline: &S,
pipeline_specializer: &S,
key: S::Key,
) -> CachedRenderPipelineId {
*self.cache.entry(key.clone()).or_insert_with(|| {
let descriptor = specialize_pipeline.specialize(key);
let descriptor = pipeline_specializer.specialize(key);
cache.queue_render_pipeline(descriptor)
})
}
}
/// A trait that allows constructing different variants of a compute pipeline from a key.
///
/// Note: This is intended for modifying your pipeline descriptor on the basis of a key. If your key
/// contains no data then you don't need to specialize. For example, if you are using the
/// [`AsBindGroup`](crate::render_resource::AsBindGroup) without the `#[bind_group_data]` attribute,
/// you don't need to specialize. Instead, create the pipeline directly from [`PipelineCache`] and
/// store its ID.
///
/// See [`SpecializedComputePipelines`] for more info.
pub trait SpecializedComputePipeline {
/// The key that defines each "variant" of the compute pipeline.
type Key: Clone + Hash + PartialEq + Eq;
/// Construct a new compute pipeline based on the provided key.
fn specialize(&self, key: Self::Key) -> ComputePipelineDescriptor;
}
/// A convenience cache for creating different variants of a compute pipeline based on some key.
///
/// Some compute pipelines may need to be configured differently depending on the exact situation.
/// This cache allows constructing different compute pipelines for each situation based on a key,
/// making it easy to A) construct the necessary pipelines, and B) reuse already constructed
/// pipelines.
///
/// Note: This is intended for modifying your pipeline descriptor on the basis of a key. If your key
/// contains no data then you don't need to specialize. For example, if you are using the
/// [`AsBindGroup`](crate::render_resource::AsBindGroup) without the `#[bind_group_data]` attribute,
/// you don't need to specialize. Instead, create the pipeline directly from [`PipelineCache`] and
/// store its ID.
#[derive(Resource)]
pub struct SpecializedComputePipelines<S: SpecializedComputePipeline> {
cache: HashMap<S::Key, CachedComputePipelineId>,
@ -65,6 +114,7 @@ impl<S: SpecializedComputePipeline> Default for SpecializedComputePipelines<S> {
}
impl<S: SpecializedComputePipeline> SpecializedComputePipelines<S> {
/// Get or create a specialized instance of the pipeline corresponding to `key`.
pub fn specialize(
&mut self,
cache: &PipelineCache,
@ -78,8 +128,18 @@ impl<S: SpecializedComputePipeline> SpecializedComputePipelines<S> {
}
}
/// A trait that allows constructing different variants of a render pipeline from a key and the
/// particular mesh's vertex buffer layout.
///
/// See [`SpecializedMeshPipelines`] for more info.
pub trait SpecializedMeshPipeline {
/// The key that defines each "variant" of the render pipeline.
type Key: Clone + Hash + PartialEq + Eq;
/// Construct a new render pipeline based on the provided key and vertex layout.
///
/// The returned pipeline descriptor should have a single vertex buffer, which is derived from
/// `layout`.
fn specialize(
&self,
key: Self::Key,
@ -87,13 +147,15 @@ pub trait SpecializedMeshPipeline {
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError>;
}
/// A cache of different variants of a render pipeline based on a key and the particular mesh's
/// vertex buffer layout.
#[derive(Resource)]
pub struct SpecializedMeshPipelines<S: SpecializedMeshPipeline> {
mesh_layout_cache: HashMap<(MeshVertexBufferLayoutRef, S::Key), CachedRenderPipelineId>,
vertex_layout_cache: VertexLayoutCache<S>,
}
pub type VertexLayoutCache<S> = HashMap<
type VertexLayoutCache<S> = HashMap<
VertexBufferLayout,
HashMap<<S as SpecializedMeshPipeline>::Key, CachedRenderPipelineId>,
>;
@ -108,11 +170,13 @@ impl<S: SpecializedMeshPipeline> Default for SpecializedMeshPipelines<S> {
}
impl<S: SpecializedMeshPipeline> SpecializedMeshPipelines<S> {
/// Construct a new render pipeline based on the provided key and the mesh's vertex buffer
/// layout.
#[inline]
pub fn specialize(
&mut self,
cache: &PipelineCache,
specialize_pipeline: &S,
pipeline_specializer: &S,
key: S::Key,
layout: &MeshVertexBufferLayoutRef,
) -> Result<CachedRenderPipelineId, SpecializedMeshPipelineError> {
@ -121,7 +185,7 @@ impl<S: SpecializedMeshPipeline> SpecializedMeshPipelines<S> {
Entry::Vacant(entry) => specialize_slow(
&mut self.vertex_layout_cache,
cache,
specialize_pipeline,
pipeline_specializer,
key,
layout,
entry,