From 05e5ae3c0d90bdbb7c3cad517b0e548db3a84824 Mon Sep 17 00:00:00 2001 From: Rob Parrett Date: Thu, 20 Jan 2022 16:59:15 -0700 Subject: [PATCH 1/7] WIP cull mode specialization --- crates/bevy_pbr/src/material.rs | 20 ++++++++++++++++++++ crates/bevy_pbr/src/pbr_material.rs | 7 +++++++ crates/bevy_pbr/src/render/mesh.rs | 25 ++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index d1c521397511e..7aa240bd89650 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -65,6 +65,12 @@ pub trait Material: Asset + RenderAsset { AlphaMode::Opaque } + /// Returns this material's [`AlphaMode`]. Defaults to [`AlphaMode::Opaque`]. + #[allow(unused_variables)] + fn double_sided(material: &::PreparedAsset) -> bool { + false + } + /// The dynamic uniform indices to set for the given `material`'s [`BindGroup`]. /// Defaults to an empty array / no dynamic uniform indices. #[allow(unused_variables)] @@ -98,6 +104,11 @@ impl SpecializedMaterial for M { ::alpha_mode(material) } + #[inline] + fn double_sided(material: &::PreparedAsset) -> bool { + ::double_sided(material) + } + #[inline] fn vertex_shader(asset_server: &AssetServer) -> Option> { ::vertex_shader(asset_server) @@ -158,6 +169,12 @@ pub trait SpecializedMaterial: Asset + RenderAsset { AlphaMode::Opaque } + /// Returns this material's [`AlphaMode`]. Defaults to [`AlphaMode::Opaque`]. + #[allow(unused_variables)] + fn double_sided(material: &::PreparedAsset) -> bool { + false + } + /// The dynamic uniform indices to set for the given `material`'s [`BindGroup`]. /// Defaults to an empty array / no dynamic uniform indices. #[allow(unused_variables)] @@ -326,6 +343,9 @@ pub fn queue_material_meshes( if let AlphaMode::Blend = alpha_mode { mesh_key |= MeshPipelineKey::TRANSPARENT_MAIN_PASS } + if M::double_sided(material) { + mesh_key |= MeshPipelineKey::from_cull_mode(None) + } let specialized_key = M::key(material); let pipeline_id = pipelines.specialize( diff --git a/crates/bevy_pbr/src/pbr_material.rs b/crates/bevy_pbr/src/pbr_material.rs index 26ed132faf25f..06f8ce67811c0 100644 --- a/crates/bevy_pbr/src/pbr_material.rs +++ b/crates/bevy_pbr/src/pbr_material.rs @@ -153,6 +153,7 @@ pub struct GpuStandardMaterial { pub flags: StandardMaterialFlags, pub base_color_texture: Option>, pub alpha_mode: AlphaMode, + pub double_sided: bool, } impl RenderAsset for StandardMaterial { @@ -320,6 +321,7 @@ impl RenderAsset for StandardMaterial { has_normal_map, base_color_texture: material.base_color_texture, alpha_mode: material.alpha_mode, + double_sided: material.double_sided, }) } } @@ -477,4 +479,9 @@ impl SpecializedMaterial for StandardMaterial { fn alpha_mode(render_asset: &::PreparedAsset) -> AlphaMode { render_asset.alpha_mode } + + #[inline] + fn double_sided(render_asset: &::PreparedAsset) -> bool { + render_asset.double_sided + } } diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 3e8965aa28ee1..7af39252c4cc8 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -372,6 +372,7 @@ bitflags::bitflags! { const TRANSPARENT_MAIN_PASS = (1 << 1); const MSAA_RESERVED_BITS = MeshPipelineKey::MSAA_MASK_BITS << MeshPipelineKey::MSAA_SHIFT_BITS; const PRIMITIVE_TOPOLOGY_RESERVED_BITS = MeshPipelineKey::PRIMITIVE_TOPOLOGY_MASK_BITS << MeshPipelineKey::PRIMITIVE_TOPOLOGY_SHIFT_BITS; + const CULL_MODE_RESERVED_BITS = MeshPipelineKey::CULL_MODE_MASK_BITS << MeshPipelineKey::CULL_MODE_SHIFT_BITS; } } @@ -380,6 +381,8 @@ impl MeshPipelineKey { const MSAA_SHIFT_BITS: u32 = 32 - 6; const PRIMITIVE_TOPOLOGY_MASK_BITS: u32 = 0b111; const PRIMITIVE_TOPOLOGY_SHIFT_BITS: u32 = Self::MSAA_SHIFT_BITS - 3; + const CULL_MODE_MASK_BITS: u32 = 0b11; + const CULL_MODE_SHIFT_BITS: u32 = Self::PRIMITIVE_TOPOLOGY_SHIFT_BITS - 2; pub fn from_msaa_samples(msaa_samples: u32) -> Self { let msaa_bits = ((msaa_samples - 1) & Self::MSAA_MASK_BITS) << Self::MSAA_SHIFT_BITS; @@ -409,6 +412,26 @@ impl MeshPipelineKey { _ => PrimitiveTopology::default(), } } + + pub fn from_cull_mode(cull_mode: Option) -> Self { + let cull_mode = match cull_mode { + Some(Face::Back) => 0, + Some(Face::Front) => 1, + None => 2, + }; + let cull_mode_bits = (cull_mode & Self::CULL_MODE_MASK_BITS) << Self::CULL_MODE_SHIFT_BITS; + MeshPipelineKey::from_bits(cull_mode_bits).unwrap() + } + + pub fn cull_mode(&self) -> Option { + let cull_mode_bits = (self.bits >> Self::CULL_MODE_SHIFT_BITS) & Self::CULL_MODE_MASK_BITS; + match cull_mode_bits { + 0 => Some(Face::Back), + 1 => Some(Face::Front), + 2 => None, + _ => Some(Face::Back), + } + } } impl SpecializedPipeline for MeshPipeline { @@ -519,7 +542,7 @@ impl SpecializedPipeline for MeshPipeline { layout: Some(vec![self.view_layout.clone(), self.mesh_layout.clone()]), primitive: PrimitiveState { front_face: FrontFace::Ccw, - cull_mode: Some(Face::Back), + cull_mode: key.cull_mode(), unclipped_depth: false, polygon_mode: PolygonMode::Fill, conservative: false, From 84e23f3aa25ab8f1cd38eeca14fcfb86b9260110 Mon Sep 17 00:00:00 2001 From: Rob Parrett Date: Fri, 21 Jan 2022 06:31:12 -0700 Subject: [PATCH 2/7] Update crates/bevy_pbr/src/material.rs Co-authored-by: Robert Swain --- crates/bevy_pbr/src/material.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 7aa240bd89650..e5661aec274e7 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -65,7 +65,7 @@ pub trait Material: Asset + RenderAsset { AlphaMode::Opaque } - /// Returns this material's [`AlphaMode`]. Defaults to [`AlphaMode::Opaque`]. + /// Returns whether this material is double-sided. Defaults to [`false`]. #[allow(unused_variables)] fn double_sided(material: &::PreparedAsset) -> bool { false From 6dd3b6afd87e919ec6b3e0da264218dabc29be05 Mon Sep 17 00:00:00 2001 From: Rob Parrett Date: Fri, 21 Jan 2022 06:31:19 -0700 Subject: [PATCH 3/7] Update crates/bevy_pbr/src/material.rs Co-authored-by: Robert Swain --- crates/bevy_pbr/src/material.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index e5661aec274e7..0e707a6b019ed 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -169,7 +169,7 @@ pub trait SpecializedMaterial: Asset + RenderAsset { AlphaMode::Opaque } - /// Returns this material's [`AlphaMode`]. Defaults to [`AlphaMode::Opaque`]. + /// Returns whether this material is double-sided. Defaults to [`false`]. #[allow(unused_variables)] fn double_sided(material: &::PreparedAsset) -> bool { false From 60c8c3c2ff7b5acd7b3ff3b2ce14e33751b15f80 Mon Sep 17 00:00:00 2001 From: Rob Parrett Date: Fri, 21 Jan 2022 06:31:38 -0700 Subject: [PATCH 4/7] Update crates/bevy_pbr/src/render/mesh.rs Co-authored-by: Robert Swain --- crates/bevy_pbr/src/render/mesh.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 7af39252c4cc8..6a5fea1a9ff36 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -415,9 +415,9 @@ impl MeshPipelineKey { pub fn from_cull_mode(cull_mode: Option) -> Self { let cull_mode = match cull_mode { - Some(Face::Back) => 0, + None => 0, Some(Face::Front) => 1, - None => 2, + Some(Face::Back) => 2, }; let cull_mode_bits = (cull_mode & Self::CULL_MODE_MASK_BITS) << Self::CULL_MODE_SHIFT_BITS; MeshPipelineKey::from_bits(cull_mode_bits).unwrap() From a3b06c765478cedbb275c7808d4bdc1c55ce47d6 Mon Sep 17 00:00:00 2001 From: Rob Parrett Date: Fri, 21 Jan 2022 06:31:46 -0700 Subject: [PATCH 5/7] Update crates/bevy_pbr/src/render/mesh.rs Co-authored-by: Robert Swain --- crates/bevy_pbr/src/render/mesh.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 6a5fea1a9ff36..2a8caf975693c 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -426,9 +426,9 @@ impl MeshPipelineKey { pub fn cull_mode(&self) -> Option { let cull_mode_bits = (self.bits >> Self::CULL_MODE_SHIFT_BITS) & Self::CULL_MODE_MASK_BITS; match cull_mode_bits { - 0 => Some(Face::Back), + 0 => None, 1 => Some(Face::Front), - 2 => None, + 2 => Some(Face::Back), _ => Some(Face::Back), } } From 54a6796ebb3e4d9c7737e5a6a676c24342d41153 Mon Sep 17 00:00:00 2001 From: Rob Parrett Date: Fri, 21 Jan 2022 06:34:52 -0700 Subject: [PATCH 6/7] Align fields in MeshPipelineKey bitflags --- crates/bevy_pbr/src/render/mesh.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 2a8caf975693c..df64424366002 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -367,12 +367,12 @@ bitflags::bitflags! { // NOTE: Apparently quadro drivers support up to 64x MSAA. /// MSAA uses the highest 6 bits for the MSAA sample count - 1 to support up to 64x MSAA. pub struct MeshPipelineKey: u32 { - const NONE = 0; - const VERTEX_TANGENTS = (1 << 0); - const TRANSPARENT_MAIN_PASS = (1 << 1); - const MSAA_RESERVED_BITS = MeshPipelineKey::MSAA_MASK_BITS << MeshPipelineKey::MSAA_SHIFT_BITS; + const NONE = 0; + const VERTEX_TANGENTS = (1 << 0); + const TRANSPARENT_MAIN_PASS = (1 << 1); + const MSAA_RESERVED_BITS = MeshPipelineKey::MSAA_MASK_BITS << MeshPipelineKey::MSAA_SHIFT_BITS; const PRIMITIVE_TOPOLOGY_RESERVED_BITS = MeshPipelineKey::PRIMITIVE_TOPOLOGY_MASK_BITS << MeshPipelineKey::PRIMITIVE_TOPOLOGY_SHIFT_BITS; - const CULL_MODE_RESERVED_BITS = MeshPipelineKey::CULL_MODE_MASK_BITS << MeshPipelineKey::CULL_MODE_SHIFT_BITS; + const CULL_MODE_RESERVED_BITS = MeshPipelineKey::CULL_MODE_MASK_BITS << MeshPipelineKey::CULL_MODE_SHIFT_BITS; } } From 075d7d6c27fcdee2d052cc12590af57eaf6a82ef Mon Sep 17 00:00:00 2001 From: Rob Parrett Date: Fri, 21 Jan 2022 06:43:29 -0700 Subject: [PATCH 7/7] Fix cull mode defaulting to None --- crates/bevy_pbr/src/material.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_pbr/src/material.rs b/crates/bevy_pbr/src/material.rs index 0e707a6b019ed..e693b3b0ef56d 100644 --- a/crates/bevy_pbr/src/material.rs +++ b/crates/bevy_pbr/src/material.rs @@ -23,7 +23,7 @@ use bevy_render::{ SetItemPipeline, TrackedRenderPass, }, render_resource::{ - BindGroup, BindGroupLayout, RenderPipelineCache, RenderPipelineDescriptor, Shader, + BindGroup, BindGroupLayout, Face, RenderPipelineCache, RenderPipelineDescriptor, Shader, SpecializedPipeline, SpecializedPipelines, }, renderer::RenderDevice, @@ -343,8 +343,8 @@ pub fn queue_material_meshes( if let AlphaMode::Blend = alpha_mode { mesh_key |= MeshPipelineKey::TRANSPARENT_MAIN_PASS } - if M::double_sided(material) { - mesh_key |= MeshPipelineKey::from_cull_mode(None) + if !M::double_sided(material) { + mesh_key |= MeshPipelineKey::from_cull_mode(Some(Face::Back)) } let specialized_key = M::key(material);