Change mesh pipeline key to a bitfield.
This commit is contained in:
parent
0f9c52cc38
commit
5898d7c17c
@ -17,6 +17,7 @@ bevy = { version = "0.8", default-features = false, features = [
|
||||
"bevy_pbr",
|
||||
"bevy_core_pipeline",
|
||||
] }
|
||||
bitfield = "0.14"
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
|
40
src/draw.rs
40
src/draw.rs
@ -1,4 +1,4 @@
|
||||
use bevy::pbr::{DrawMesh, MeshPipelineKey, MeshUniform, SetMeshBindGroup, SetMeshViewBindGroup};
|
||||
use bevy::pbr::{DrawMesh, MeshUniform, SetMeshBindGroup, SetMeshViewBindGroup};
|
||||
use bevy::prelude::*;
|
||||
use bevy::render::render_asset::RenderAssets;
|
||||
use bevy::render::render_phase::{DrawFunctions, RenderPhase, SetItemPipeline};
|
||||
@ -6,7 +6,7 @@ use bevy::render::render_resource::{PipelineCache, SpecializedMeshPipelines};
|
||||
use bevy::render::view::ExtractedView;
|
||||
|
||||
use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline};
|
||||
use crate::pipeline::{OutlinePipeline, PassType};
|
||||
use crate::pipeline::{OutlinePipeline, PassType, PipelineKey};
|
||||
use crate::uniforms::{
|
||||
OutlineFragmentUniform, SetOutlineStencilBindGroup, SetOutlineVolumeBindGroup,
|
||||
};
|
||||
@ -38,21 +38,17 @@ pub fn queue_outline_stencil_mesh(
|
||||
.get_id::<DrawStencil>()
|
||||
.unwrap();
|
||||
|
||||
let base_key = MeshPipelineKey::from_msaa_samples(msaa.samples);
|
||||
let base_key = PipelineKey::new()
|
||||
.with_msaa_samples(msaa.samples)
|
||||
.with_pass_type(PassType::Stencil);
|
||||
|
||||
for (view, mut stencil_phase) in views.iter_mut() {
|
||||
let rangefinder = view.rangefinder3d();
|
||||
for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() {
|
||||
if let Some(mesh) = render_meshes.get(mesh_handle) {
|
||||
let key =
|
||||
base_key | MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
|
||||
let key = base_key.with_primitive_topology(mesh.primitive_topology);
|
||||
let pipeline = pipelines
|
||||
.specialize(
|
||||
&mut pipeline_cache,
|
||||
&stencil_pipeline,
|
||||
(key, PassType::Stencil),
|
||||
&mesh.layout,
|
||||
)
|
||||
.specialize(&mut pipeline_cache, &stencil_pipeline, key, &mesh.layout)
|
||||
.unwrap();
|
||||
let distance = rangefinder.distance(&mesh_uniform.transform);
|
||||
stencil_phase.add(StencilOutline {
|
||||
@ -100,30 +96,22 @@ pub fn queue_outline_volume_mesh(
|
||||
.get_id::<DrawOutline>()
|
||||
.unwrap();
|
||||
|
||||
let base_key = MeshPipelineKey::from_msaa_samples(msaa.samples);
|
||||
let base_key = PipelineKey::new().with_msaa_samples(msaa.samples);
|
||||
|
||||
for (view, mut opaque_phase, mut transparent_phase) in views.iter_mut() {
|
||||
let rangefinder = view.rangefinder3d();
|
||||
for (entity, mesh_uniform, mesh_handle, outline_fragment) in material_meshes.iter() {
|
||||
if let Some(mesh) = render_meshes.get(mesh_handle) {
|
||||
let transparent = outline_fragment.colour[3] < 1.0;
|
||||
let pass_type;
|
||||
let key = base_key
|
||||
| MeshPipelineKey::from_primitive_topology(mesh.primitive_topology)
|
||||
| if transparent {
|
||||
pass_type = PassType::Transparent;
|
||||
MeshPipelineKey::TRANSPARENT_MAIN_PASS
|
||||
.with_primitive_topology(mesh.primitive_topology)
|
||||
.with_pass_type(if transparent {
|
||||
PassType::Transparent
|
||||
} else {
|
||||
pass_type = PassType::Opaque;
|
||||
MeshPipelineKey::NONE
|
||||
};
|
||||
PassType::Opaque
|
||||
});
|
||||
let pipeline = pipelines
|
||||
.specialize(
|
||||
&mut pipeline_cache,
|
||||
&outline_pipeline,
|
||||
(key, pass_type),
|
||||
&mesh.layout,
|
||||
)
|
||||
.specialize(&mut pipeline_cache, &outline_pipeline, key, &mesh.layout)
|
||||
.unwrap();
|
||||
let distance = rangefinder.distance(&mesh_uniform.transform);
|
||||
if transparent {
|
||||
|
@ -6,12 +6,13 @@ use bevy::render::render_resource::{
|
||||
BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState,
|
||||
BufferBindingType, BufferSize, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
|
||||
DepthStencilState, Face, FragmentState, FrontFace, MultisampleState, PolygonMode,
|
||||
PrimitiveState, ShaderSize, ShaderStages, StencilState, TextureFormat, VertexState,
|
||||
PrimitiveState, PrimitiveTopology, ShaderSize, ShaderStages, StencilState, TextureFormat,
|
||||
VertexState,
|
||||
};
|
||||
use bevy::render::renderer::RenderDevice;
|
||||
use bevy::render::texture::BevyDefault;
|
||||
use bevy::{
|
||||
pbr::{MeshPipeline, MeshPipelineKey},
|
||||
pbr::MeshPipeline,
|
||||
render::{
|
||||
mesh::MeshVertexBufferLayout,
|
||||
render_resource::{
|
||||
@ -19,6 +20,7 @@ use bevy::{
|
||||
},
|
||||
},
|
||||
};
|
||||
use bitfield::{bitfield_bitrange, bitfield_fields};
|
||||
|
||||
use crate::uniforms::{OutlineFragmentUniform, OutlineStencilUniform, OutlineVolumeUniform};
|
||||
use crate::view_uniforms::OutlineViewUniform;
|
||||
@ -30,11 +32,67 @@ pub const OUTLINE_SHADER_HANDLE: HandleUntyped =
|
||||
pub const FRAGMENT_SHADER_HANDLE: HandleUntyped =
|
||||
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 12033806834125368121);
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum PassType {
|
||||
Stencil,
|
||||
Opaque,
|
||||
Transparent,
|
||||
Stencil = 1,
|
||||
Opaque = 2,
|
||||
Transparent = 3,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct PipelineKey(u32);
|
||||
bitfield_bitrange! {struct PipelineKey(u32)}
|
||||
|
||||
impl PipelineKey {
|
||||
bitfield_fields! {
|
||||
u32;
|
||||
msaa_samples_minus_one, set_msaa_samples_minus_one: 5, 0;
|
||||
primitive_topology_int, set_primitive_topology_int: 8, 6;
|
||||
pass_type_int, set_pass_type_int: 10, 9;
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
PipelineKey(0)
|
||||
}
|
||||
|
||||
pub fn with_msaa_samples(mut self, msaa_samples: u32) -> Self {
|
||||
self.set_msaa_samples_minus_one(msaa_samples - 1);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn msaa_samples(&self) -> u32 {
|
||||
self.msaa_samples_minus_one() + 1
|
||||
}
|
||||
|
||||
pub fn with_primitive_topology(mut self, primitive_topology: PrimitiveTopology) -> Self {
|
||||
self.set_primitive_topology_int(primitive_topology as u32);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn primitive_topology(&self) -> PrimitiveTopology {
|
||||
match self.primitive_topology_int() {
|
||||
x if x == PrimitiveTopology::PointList as u32 => PrimitiveTopology::PointList,
|
||||
x if x == PrimitiveTopology::LineList as u32 => PrimitiveTopology::LineList,
|
||||
x if x == PrimitiveTopology::LineStrip as u32 => PrimitiveTopology::LineStrip,
|
||||
x if x == PrimitiveTopology::TriangleList as u32 => PrimitiveTopology::TriangleList,
|
||||
x if x == PrimitiveTopology::TriangleStrip as u32 => PrimitiveTopology::TriangleStrip,
|
||||
x => panic!("Invalid value for PrimitiveTopology: {}", x),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_pass_type(mut self, pass_type: PassType) -> Self {
|
||||
self.set_pass_type_int(pass_type as u32);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn pass_type(&self) -> PassType {
|
||||
match self.pass_type_int() {
|
||||
x if x == PassType::Stencil as u32 => PassType::Stencil,
|
||||
x if x == PassType::Opaque as u32 => PassType::Opaque,
|
||||
x if x == PassType::Transparent as u32 => PassType::Transparent,
|
||||
x => panic!("Invalid value for PassType: {}", x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OutlinePipeline {
|
||||
@ -117,11 +175,11 @@ impl FromWorld for OutlinePipeline {
|
||||
}
|
||||
|
||||
impl SpecializedMeshPipeline for OutlinePipeline {
|
||||
type Key = (MeshPipelineKey, PassType);
|
||||
type Key = PipelineKey;
|
||||
|
||||
fn specialize(
|
||||
&self,
|
||||
(key, pass_type): Self::Key,
|
||||
key: Self::Key,
|
||||
mesh_layout: &MeshVertexBufferLayout,
|
||||
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
|
||||
let mut targets = vec![];
|
||||
@ -142,7 +200,7 @@ impl SpecializedMeshPipeline for OutlinePipeline {
|
||||
},
|
||||
);
|
||||
bind_layouts.push(self.outline_view_bind_group_layout.clone());
|
||||
match pass_type {
|
||||
match key.pass_type() {
|
||||
PassType::Stencil => {
|
||||
vertex_defs.push("OFFSET_ZERO".to_string());
|
||||
bind_layouts.push(self.outline_stencil_bind_group_layout.clone());
|
||||
@ -151,7 +209,7 @@ impl SpecializedMeshPipeline for OutlinePipeline {
|
||||
fragment_defs.push("VOLUME".to_string());
|
||||
targets.push(Some(ColorTargetState {
|
||||
format: TextureFormat::bevy_default(),
|
||||
blend: Some(if pass_type == PassType::Transparent {
|
||||
blend: Some(if key.pass_type() == PassType::Transparent {
|
||||
BlendState::ALPHA_BLENDING
|
||||
} else {
|
||||
BlendState::REPLACE
|
||||
|
Loading…
Reference in New Issue
Block a user