use std::sync::Arc;
use bytemuck::{Pod, Zeroable};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RenderTier {
Direct,
Indirect,
Bindless,
}
impl std::fmt::Display for RenderTier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RenderTier::Direct => write!(f, "Direct (Tier 1)"),
RenderTier::Indirect => write!(f, "Indirect (Tier 2)"),
RenderTier::Bindless => write!(f, "Bindless (Tier 3)"),
}
}
}
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DrawType2D {
Quad = 0,
Text = 1,
Image = 2,
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct UnifiedInstance2D {
pub position: [f32; 2],
pub size: [f32; 2],
pub uv_min: [f32; 2],
pub uv_max: [f32; 2],
pub color: [f32; 4],
pub border_radius: f32,
pub border_thickness: f32,
pub texture_index: u32,
pub draw_type: u32,
pub clip_min: [f32; 2],
pub clip_max: [f32; 2],
pub z_depth: f32,
pub _reserved: [f32; 3],
}
unsafe impl Pod for UnifiedInstance2D {}
unsafe impl Zeroable for UnifiedInstance2D {}
impl Default for UnifiedInstance2D {
fn default() -> Self {
Self {
position: [0.0; 2],
size: [0.0; 2],
uv_min: [0.0; 2],
uv_max: [0.0; 2],
color: [1.0, 1.0, 1.0, 1.0],
border_radius: 0.0,
border_thickness: 0.0,
texture_index: 0,
draw_type: DrawType2D::Quad as u32,
clip_min: [f32::NEG_INFINITY, f32::NEG_INFINITY],
clip_max: [f32::INFINITY, f32::INFINITY],
z_depth: 0.0,
_reserved: [0.0; 3],
}
}
}
impl UnifiedInstance2D {
pub fn layout() -> wgpu::VertexBufferLayout<'static> {
const ATTRS: &[wgpu::VertexAttribute] = &wgpu::vertex_attr_array![
2 => Float32x2,
3 => Float32x2,
4 => Float32x2,
5 => Float32x2,
6 => Float32x4,
7 => Float32,
8 => Float32,
9 => Uint32,
10 => Uint32,
11 => Float32x2,
12 => Float32x2,
13 => Float32,
14 => Float32x3,
];
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<UnifiedInstance2D>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Instance,
attributes: ATTRS,
}
}
pub const SIZE: u64 = std::mem::size_of::<Self>() as u64;
}
pub struct TextureSlot2D {
pub id: u64,
pub view: Arc<wgpu::TextureView>,
pub sampler: Arc<wgpu::Sampler>,
}
pub struct DrawBatch2D {
pub instances: Vec<UnifiedInstance2D>,
pub textures: Vec<TextureSlot2D>,
pub projection: [[f32; 4]; 4],
}
#[derive(Debug, Clone, Copy, Default)]
pub struct BatchRenderStats2D {
pub instance_count: u32,
pub opaque_count: u32,
pub transparent_count: u32,
pub draw_calls: u32,
pub bind_group_switches: u32,
pub pipeline_switches: u32,
pub texture_count: u32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_unified_instance_size() {
assert_eq!(std::mem::size_of::<UnifiedInstance2D>(), 96);
}
#[test]
fn test_unified_instance_alignment() {
assert!(std::mem::align_of::<UnifiedInstance2D>() <= 16);
}
#[test]
fn test_draw_type_values() {
assert_eq!(DrawType2D::Quad as u32, 0);
assert_eq!(DrawType2D::Text as u32, 1);
assert_eq!(DrawType2D::Image as u32, 2);
}
}