#[allow(dead_code)]
mod bindless;
pub mod capability;
#[allow(dead_code)]
mod direct;
#[allow(dead_code)]
mod indirect;
#[allow(dead_code)]
mod pipeline;
#[allow(dead_code)]
mod texture_array;
mod traits;
mod types;
pub use capability::{
BestBatchCapability2D, BindlessBatchCapability2D, DirectBatchCapability2D,
IndirectBatchCapability2D,
};
pub use traits::*;
pub use types::*;
use std::sync::Arc;
use crate::context::GraphicsContext;
use crate::features::GpuFeatures;
const BINDLESS_MAX_TEXTURES: u32 = 256;
#[deprecated(
since = "0.2.0",
note = "Use the RenderCapability trait instead (e.g., BestBatchCapability2D, BindlessBatchCapability2D)"
)]
pub fn required_features_for_tier(tier: RenderTier) -> GpuFeatures {
match tier {
RenderTier::Direct => GpuFeatures::empty(),
RenderTier::Indirect => GpuFeatures::INDIRECT_FIRST_INSTANCE,
RenderTier::Bindless => {
GpuFeatures::INDIRECT_FIRST_INSTANCE
| GpuFeatures::TEXTURE_BINDING_ARRAY
| GpuFeatures::PARTIALLY_BOUND_BINDING_ARRAY
| GpuFeatures::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING
}
}
}
#[deprecated(
since = "0.2.0",
note = "Use the RenderCapability trait instead (e.g., BestBatchCapability2D, BindlessBatchCapability2D)"
)]
pub fn required_limits_for_tier(tier: RenderTier) -> wgpu::Limits {
let mut limits = wgpu::Limits::default();
if tier == RenderTier::Bindless {
limits.max_binding_array_elements_per_shader_stage = BINDLESS_MAX_TEXTURES;
}
limits
}
pub fn detect_render_tier(context: &GraphicsContext) -> RenderTier {
let features = context.gpu_features();
let has_indirect_first_instance = features.contains(GpuFeatures::INDIRECT_FIRST_INSTANCE);
let has_texture_binding_array = features.contains(GpuFeatures::TEXTURE_BINDING_ARRAY);
let has_partially_bound = features.contains(GpuFeatures::PARTIALLY_BOUND_BINDING_ARRAY);
let has_non_uniform_indexing = features
.contains(GpuFeatures::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING);
if has_indirect_first_instance
&& has_texture_binding_array
&& has_partially_bound
&& has_non_uniform_indexing
{
RenderTier::Bindless
} else if has_indirect_first_instance {
RenderTier::Indirect
} else {
RenderTier::Direct
}
}
pub fn create_batch_renderer_2d(
context: Arc<GraphicsContext>,
surface_format: wgpu::TextureFormat,
tier_override: Option<RenderTier>,
) -> Box<dyn BatchRenderer2D> {
let tier = tier_override.unwrap_or_else(|| detect_render_tier(&context));
tracing::info!("Creating batch renderer 2D: {tier}");
match tier {
RenderTier::Direct => Box::new(direct::DirectBatchRenderer2D::new(context, surface_format)),
RenderTier::Indirect => Box::new(indirect::IndirectBatchRenderer2D::new(
context,
surface_format,
)),
RenderTier::Bindless => Box::new(bindless::BindlessBatchRenderer2D::new(
context,
surface_format,
)),
}
}