Support topologies other than TriangleList (#3349)

# Objective

Fixes https://github.com/bevyengine/bevy/issues/3346

## Solution

I've encoded the topology in the `MeshKey` similar to how MSAA samples are handled.
This commit is contained in:
Dusty DeWeese 2021-12-18 20:55:40 +00:00
parent 6eb8e15e3d
commit 73f524f61c
3 changed files with 28 additions and 1 deletions

View File

@ -370,12 +370,15 @@ bitflags::bitflags! {
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;
}
}
impl MeshPipelineKey {
const MSAA_MASK_BITS: u32 = 0b111111;
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;
pub fn from_msaa_samples(msaa_samples: u32) -> Self {
let msaa_bits = ((msaa_samples - 1) & Self::MSAA_MASK_BITS) << Self::MSAA_SHIFT_BITS;
@ -385,6 +388,26 @@ impl MeshPipelineKey {
pub fn msaa_samples(&self) -> u32 {
((self.bits >> Self::MSAA_SHIFT_BITS) & Self::MSAA_MASK_BITS) + 1
}
pub fn from_primitive_topology(primitive_topology: PrimitiveTopology) -> Self {
let primitive_topology_bits = ((primitive_topology as u32)
& Self::PRIMITIVE_TOPOLOGY_MASK_BITS)
<< Self::PRIMITIVE_TOPOLOGY_SHIFT_BITS;
MeshPipelineKey::from_bits(primitive_topology_bits).unwrap()
}
pub fn primitive_topology(&self) -> PrimitiveTopology {
let primitive_topology_bits =
(self.bits >> Self::PRIMITIVE_TOPOLOGY_SHIFT_BITS) & Self::PRIMITIVE_TOPOLOGY_MASK_BITS;
match primitive_topology_bits {
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,
_ => PrimitiveTopology::default(),
}
}
}
impl SpecializedPipeline for MeshPipeline {
@ -496,7 +519,7 @@ impl SpecializedPipeline for MeshPipeline {
polygon_mode: PolygonMode::Fill,
clamp_depth: false,
conservative: false,
topology: PrimitiveTopology::TriangleList,
topology: key.primitive_topology(),
strip_index_format: None,
},
depth_stencil: Some(DepthStencilState {

View File

@ -269,6 +269,8 @@ pub fn queue_meshes(
if mesh.has_tangents {
pbr_key.mesh_key |= MeshPipelineKey::VERTEX_TANGENTS;
}
pbr_key.mesh_key |=
MeshPipelineKey::from_primitive_topology(mesh.primitive_topology);
}
if let AlphaMode::Blend = material.alpha_mode {

View File

@ -593,6 +593,7 @@ pub struct GpuMesh {
pub vertex_buffer: Buffer,
pub index_info: Option<GpuIndexInfo>,
pub has_tangents: bool,
pub primitive_topology: PrimitiveTopology,
}
/// The index info of a [`GpuMesh`].
@ -640,6 +641,7 @@ impl RenderAsset for Mesh {
vertex_buffer,
index_info,
has_tangents: mesh.attributes.contains_key(Mesh::ATTRIBUTE_TANGENT),
primitive_topology: mesh.primitive_topology(),
})
}
}