Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP cull mode specialization #3734

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ pub trait Material: Asset + RenderAsset {
AlphaMode::Opaque
}

/// Returns this material's [`AlphaMode`]. Defaults to [`AlphaMode::Opaque`].
rparrett marked this conversation as resolved.
Show resolved Hide resolved
#[allow(unused_variables)]
fn double_sided(material: &<Self as RenderAsset>::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)]
Expand Down Expand Up @@ -98,6 +104,11 @@ impl<M: Material> SpecializedMaterial for M {
<M as Material>::alpha_mode(material)
}

#[inline]
fn double_sided(material: &<Self as RenderAsset>::PreparedAsset) -> bool {
<M as Material>::double_sided(material)
}

#[inline]
fn vertex_shader(asset_server: &AssetServer) -> Option<Handle<Shader>> {
<M as Material>::vertex_shader(asset_server)
Expand Down Expand Up @@ -158,6 +169,12 @@ pub trait SpecializedMaterial: Asset + RenderAsset {
AlphaMode::Opaque
}

/// Returns this material's [`AlphaMode`]. Defaults to [`AlphaMode::Opaque`].
rparrett marked this conversation as resolved.
Show resolved Hide resolved
#[allow(unused_variables)]
fn double_sided(material: &<Self as RenderAsset>::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)]
Expand Down Expand Up @@ -326,6 +343,9 @@ pub fn queue_material_meshes<M: SpecializedMaterial>(
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(
Expand Down
7 changes: 7 additions & 0 deletions crates/bevy_pbr/src/pbr_material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ pub struct GpuStandardMaterial {
pub flags: StandardMaterialFlags,
pub base_color_texture: Option<Handle<Image>>,
pub alpha_mode: AlphaMode,
pub double_sided: bool,
}

impl RenderAsset for StandardMaterial {
Expand Down Expand Up @@ -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,
})
}
}
Expand Down Expand Up @@ -477,4 +479,9 @@ impl SpecializedMaterial for StandardMaterial {
fn alpha_mode(render_asset: &<Self as RenderAsset>::PreparedAsset) -> AlphaMode {
render_asset.alpha_mode
}

#[inline]
fn double_sided(render_asset: &<Self as RenderAsset>::PreparedAsset) -> bool {
render_asset.double_sided
}
}
25 changes: 24 additions & 1 deletion crates/bevy_pbr/src/render/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
rparrett marked this conversation as resolved.
Show resolved Hide resolved
rparrett marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand All @@ -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;
Expand Down Expand Up @@ -409,6 +412,26 @@ impl MeshPipelineKey {
_ => PrimitiveTopology::default(),
}
}

pub fn from_cull_mode(cull_mode: Option<Face>) -> Self {
let cull_mode = match cull_mode {
Some(Face::Back) => 0,
Some(Face::Front) => 1,
None => 2,
rparrett marked this conversation as resolved.
Show resolved Hide resolved
};
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<Face> {
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,
rparrett marked this conversation as resolved.
Show resolved Hide resolved
_ => Some(Face::Back),
}
}
}

impl SpecializedPipeline for MeshPipeline {
Expand Down Expand Up @@ -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,
Expand Down