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_pbr",
|
||||||
"bevy_core_pipeline",
|
"bevy_core_pipeline",
|
||||||
] }
|
] }
|
||||||
|
bitfield = "0.14"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[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::prelude::*;
|
||||||
use bevy::render::render_asset::RenderAssets;
|
use bevy::render::render_asset::RenderAssets;
|
||||||
use bevy::render::render_phase::{DrawFunctions, RenderPhase, SetItemPipeline};
|
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 bevy::render::view::ExtractedView;
|
||||||
|
|
||||||
use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline};
|
use crate::node::{OpaqueOutline, StencilOutline, TransparentOutline};
|
||||||
use crate::pipeline::{OutlinePipeline, PassType};
|
use crate::pipeline::{OutlinePipeline, PassType, PipelineKey};
|
||||||
use crate::uniforms::{
|
use crate::uniforms::{
|
||||||
OutlineFragmentUniform, SetOutlineStencilBindGroup, SetOutlineVolumeBindGroup,
|
OutlineFragmentUniform, SetOutlineStencilBindGroup, SetOutlineVolumeBindGroup,
|
||||||
};
|
};
|
||||||
@ -38,21 +38,17 @@ pub fn queue_outline_stencil_mesh(
|
|||||||
.get_id::<DrawStencil>()
|
.get_id::<DrawStencil>()
|
||||||
.unwrap();
|
.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() {
|
for (view, mut stencil_phase) in views.iter_mut() {
|
||||||
let rangefinder = view.rangefinder3d();
|
let rangefinder = view.rangefinder3d();
|
||||||
for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() {
|
for (entity, mesh_uniform, mesh_handle) in material_meshes.iter() {
|
||||||
if let Some(mesh) = render_meshes.get(mesh_handle) {
|
if let Some(mesh) = render_meshes.get(mesh_handle) {
|
||||||
let key =
|
let key = base_key.with_primitive_topology(mesh.primitive_topology);
|
||||||
base_key | MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
|
|
||||||
let pipeline = pipelines
|
let pipeline = pipelines
|
||||||
.specialize(
|
.specialize(&mut pipeline_cache, &stencil_pipeline, key, &mesh.layout)
|
||||||
&mut pipeline_cache,
|
|
||||||
&stencil_pipeline,
|
|
||||||
(key, PassType::Stencil),
|
|
||||||
&mesh.layout,
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let distance = rangefinder.distance(&mesh_uniform.transform);
|
let distance = rangefinder.distance(&mesh_uniform.transform);
|
||||||
stencil_phase.add(StencilOutline {
|
stencil_phase.add(StencilOutline {
|
||||||
@ -100,30 +96,22 @@ pub fn queue_outline_volume_mesh(
|
|||||||
.get_id::<DrawOutline>()
|
.get_id::<DrawOutline>()
|
||||||
.unwrap();
|
.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() {
|
for (view, mut opaque_phase, mut transparent_phase) in views.iter_mut() {
|
||||||
let rangefinder = view.rangefinder3d();
|
let rangefinder = view.rangefinder3d();
|
||||||
for (entity, mesh_uniform, mesh_handle, outline_fragment) in material_meshes.iter() {
|
for (entity, mesh_uniform, mesh_handle, outline_fragment) in material_meshes.iter() {
|
||||||
if let Some(mesh) = render_meshes.get(mesh_handle) {
|
if let Some(mesh) = render_meshes.get(mesh_handle) {
|
||||||
let transparent = outline_fragment.colour[3] < 1.0;
|
let transparent = outline_fragment.colour[3] < 1.0;
|
||||||
let pass_type;
|
|
||||||
let key = base_key
|
let key = base_key
|
||||||
| MeshPipelineKey::from_primitive_topology(mesh.primitive_topology)
|
.with_primitive_topology(mesh.primitive_topology)
|
||||||
| if transparent {
|
.with_pass_type(if transparent {
|
||||||
pass_type = PassType::Transparent;
|
PassType::Transparent
|
||||||
MeshPipelineKey::TRANSPARENT_MAIN_PASS
|
|
||||||
} else {
|
} else {
|
||||||
pass_type = PassType::Opaque;
|
PassType::Opaque
|
||||||
MeshPipelineKey::NONE
|
});
|
||||||
};
|
|
||||||
let pipeline = pipelines
|
let pipeline = pipelines
|
||||||
.specialize(
|
.specialize(&mut pipeline_cache, &outline_pipeline, key, &mesh.layout)
|
||||||
&mut pipeline_cache,
|
|
||||||
&outline_pipeline,
|
|
||||||
(key, pass_type),
|
|
||||||
&mesh.layout,
|
|
||||||
)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let distance = rangefinder.distance(&mesh_uniform.transform);
|
let distance = rangefinder.distance(&mesh_uniform.transform);
|
||||||
if transparent {
|
if transparent {
|
||||||
|
@ -6,12 +6,13 @@ use bevy::render::render_resource::{
|
|||||||
BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState,
|
BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState,
|
||||||
BufferBindingType, BufferSize, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
|
BufferBindingType, BufferSize, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
|
||||||
DepthStencilState, Face, FragmentState, FrontFace, MultisampleState, PolygonMode,
|
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::renderer::RenderDevice;
|
||||||
use bevy::render::texture::BevyDefault;
|
use bevy::render::texture::BevyDefault;
|
||||||
use bevy::{
|
use bevy::{
|
||||||
pbr::{MeshPipeline, MeshPipelineKey},
|
pbr::MeshPipeline,
|
||||||
render::{
|
render::{
|
||||||
mesh::MeshVertexBufferLayout,
|
mesh::MeshVertexBufferLayout,
|
||||||
render_resource::{
|
render_resource::{
|
||||||
@ -19,6 +20,7 @@ use bevy::{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use bitfield::{bitfield_bitrange, bitfield_fields};
|
||||||
|
|
||||||
use crate::uniforms::{OutlineFragmentUniform, OutlineStencilUniform, OutlineVolumeUniform};
|
use crate::uniforms::{OutlineFragmentUniform, OutlineStencilUniform, OutlineVolumeUniform};
|
||||||
use crate::view_uniforms::OutlineViewUniform;
|
use crate::view_uniforms::OutlineViewUniform;
|
||||||
@ -30,11 +32,67 @@ pub const OUTLINE_SHADER_HANDLE: HandleUntyped =
|
|||||||
pub const FRAGMENT_SHADER_HANDLE: HandleUntyped =
|
pub const FRAGMENT_SHADER_HANDLE: HandleUntyped =
|
||||||
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 12033806834125368121);
|
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 12033806834125368121);
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum PassType {
|
pub enum PassType {
|
||||||
Stencil,
|
Stencil = 1,
|
||||||
Opaque,
|
Opaque = 2,
|
||||||
Transparent,
|
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 {
|
pub struct OutlinePipeline {
|
||||||
@ -117,11 +175,11 @@ impl FromWorld for OutlinePipeline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SpecializedMeshPipeline for OutlinePipeline {
|
impl SpecializedMeshPipeline for OutlinePipeline {
|
||||||
type Key = (MeshPipelineKey, PassType);
|
type Key = PipelineKey;
|
||||||
|
|
||||||
fn specialize(
|
fn specialize(
|
||||||
&self,
|
&self,
|
||||||
(key, pass_type): Self::Key,
|
key: Self::Key,
|
||||||
mesh_layout: &MeshVertexBufferLayout,
|
mesh_layout: &MeshVertexBufferLayout,
|
||||||
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
|
) -> Result<RenderPipelineDescriptor, SpecializedMeshPipelineError> {
|
||||||
let mut targets = vec![];
|
let mut targets = vec![];
|
||||||
@ -142,7 +200,7 @@ impl SpecializedMeshPipeline for OutlinePipeline {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
bind_layouts.push(self.outline_view_bind_group_layout.clone());
|
bind_layouts.push(self.outline_view_bind_group_layout.clone());
|
||||||
match pass_type {
|
match key.pass_type() {
|
||||||
PassType::Stencil => {
|
PassType::Stencil => {
|
||||||
vertex_defs.push("OFFSET_ZERO".to_string());
|
vertex_defs.push("OFFSET_ZERO".to_string());
|
||||||
bind_layouts.push(self.outline_stencil_bind_group_layout.clone());
|
bind_layouts.push(self.outline_stencil_bind_group_layout.clone());
|
||||||
@ -151,7 +209,7 @@ impl SpecializedMeshPipeline for OutlinePipeline {
|
|||||||
fragment_defs.push("VOLUME".to_string());
|
fragment_defs.push("VOLUME".to_string());
|
||||||
targets.push(Some(ColorTargetState {
|
targets.push(Some(ColorTargetState {
|
||||||
format: TextureFormat::bevy_default(),
|
format: TextureFormat::bevy_default(),
|
||||||
blend: Some(if pass_type == PassType::Transparent {
|
blend: Some(if key.pass_type() == PassType::Transparent {
|
||||||
BlendState::ALPHA_BLENDING
|
BlendState::ALPHA_BLENDING
|
||||||
} else {
|
} else {
|
||||||
BlendState::REPLACE
|
BlendState::REPLACE
|
||||||
|
Loading…
Reference in New Issue
Block a user