Skip to content

Commit

Permalink
Ported WgpuOptions to bevy_render2
Browse files Browse the repository at this point in the history
  • Loading branch information
folke committed Dec 9, 2021
1 parent 2abf5cc commit fdb33f7
Show file tree
Hide file tree
Showing 2 changed files with 242 additions and 16 deletions.
40 changes: 24 additions & 16 deletions pipelined/bevy_render2/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub mod camera;
pub mod color;
pub mod mesh;
pub mod options;
pub mod primitives;
pub mod render_asset;
pub mod render_component;
Expand All @@ -16,6 +17,7 @@ pub use once_cell;
use crate::{
camera::CameraPlugin,
mesh::MeshPlugin,
options::{WgpuBackend, WgpuPowerOptions},
render_graph::RenderGraph,
render_resource::{RenderPipelineCache, Shader, ShaderLoader},
renderer::render_system,
Expand All @@ -26,7 +28,6 @@ use bevy_app::{App, AppLabel, Plugin};
use bevy_asset::{AddAsset, AssetServer};
use bevy_ecs::prelude::*;
use std::ops::{Deref, DerefMut};
use wgpu::Backends;

/// Contains the default Bevy rendering backend based on wgpu.
#[derive(Default)]
Expand Down Expand Up @@ -90,13 +91,21 @@ struct ScratchRenderWorld(World);
impl Plugin for RenderPlugin {
/// Initializes the renderer, sets up the [`RenderStage`](RenderStage) and creates the rendering sub-app.
fn build(&self, app: &mut App) {
let default_backend = if cfg!(not(target_arch = "wasm32")) {
Backends::PRIMARY
} else {
Backends::GL
let options = app
.world
.get_resource::<options::WgpuOptions>()
.cloned()
.unwrap_or_default();
let backend = match options.backend {
WgpuBackend::Primary => wgpu::Backends::PRIMARY,
WgpuBackend::Vulkan => wgpu::Backends::VULKAN,
WgpuBackend::Metal => wgpu::Backends::METAL,
WgpuBackend::Dx12 => wgpu::Backends::DX12,
WgpuBackend::Dx11 => wgpu::Backends::DX11,
WgpuBackend::Gl => wgpu::Backends::GL,
WgpuBackend::BrowserWgpu => wgpu::Backends::BROWSER_WEBGPU,
};
let backends = wgpu::util::backend_bits_from_env().unwrap_or(default_backend);
let instance = wgpu::Instance::new(backends);
let instance = wgpu::Instance::new(backend);
let surface = {
let world = app.world.cell();
let windows = world.get_resource_mut::<bevy_window::Windows>().unwrap();
Expand All @@ -109,19 +118,18 @@ impl Plugin for RenderPlugin {
let (device, queue) = futures_lite::future::block_on(renderer::initialize_renderer(
&instance,
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
power_preference: match options.power_pref {
WgpuPowerOptions::HighPerformance => wgpu::PowerPreference::HighPerformance,
WgpuPowerOptions::Adaptive => wgpu::PowerPreference::LowPower,
WgpuPowerOptions::LowPower => wgpu::PowerPreference::LowPower,
},
compatible_surface: surface.as_ref(),
..Default::default()
},
&wgpu::DeviceDescriptor {
features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES,
#[cfg(not(target_arch = "wasm32"))]
limits: wgpu::Limits::default(),
#[cfg(target_arch = "wasm32")]
limits: wgpu::Limits {
..wgpu::Limits::downlevel_webgl2_defaults()
},
..Default::default()
label: options.device_label.as_ref().map(|a| a.as_ref()),
features: options.features.into(),
limits: options.limits.into(),
},
));
app.insert_resource(device.clone())
Expand Down
218 changes: 218 additions & 0 deletions pipelined/bevy_render2/src/options.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
use std::borrow::Cow;

#[derive(Clone, Copy)]
pub enum WgpuFeature {
DepthClamping,
TextureCompressionBc,
TimestampQuery,
PipelineStatisticsQuery,
MappablePrimaryBuffers,
UnsizedBindingArray,
MultiDrawIndirect,
MultiDrawIndirectCount,
PushConstants,
AddressModeClampToBorder,
PolygonModeLine,
TextureCompressionEtc2,
TextureCompressionAstcLdr,
TextureAdapterSpecificFormatFeatures,
ShaderFloat64,
VertexAttribute64Bit,
}

#[derive(Clone)]
pub struct WgpuFeatures {
pub features: Vec<WgpuFeature>,
}

impl Default for WgpuFeatures {
fn default() -> Self {
Self {
features: vec![WgpuFeature::TextureAdapterSpecificFormatFeatures],
}
}
}

#[derive(Debug, Clone)]
pub struct WgpuLimits {
pub max_bind_groups: u32,
pub max_dynamic_uniform_buffers_per_pipeline_layout: u32,
pub max_dynamic_storage_buffers_per_pipeline_layout: u32,
pub max_sampled_textures_per_shader_stage: u32,
pub max_samplers_per_shader_stage: u32,
pub max_storage_buffers_per_shader_stage: u32,
pub max_storage_textures_per_shader_stage: u32,
pub max_uniform_buffers_per_shader_stage: u32,
pub max_uniform_buffer_binding_size: u32,
pub max_push_constant_size: u32,
pub max_texture_dimension_1d: u32,
pub max_texture_dimension_2d: u32,
pub max_texture_dimension_3d: u32,
pub max_texture_array_layers: u32,
pub max_storage_buffer_binding_size: u32,
pub max_vertex_buffers: u32,
pub max_vertex_attributes: u32,
pub max_vertex_buffer_array_stride: u32,
pub min_storage_buffer_offset_alignment: u32,
pub min_uniform_buffer_offset_alignment: u32,
}

impl Default for WgpuLimits {
fn default() -> Self {
let default = if cfg!(target_arch = "wasm32") {
wgpu::Limits {
..wgpu::Limits::downlevel_webgl2_defaults()
}
} else {
wgpu::Limits::default()
};
WgpuLimits {
max_bind_groups: default.max_bind_groups,
max_dynamic_uniform_buffers_per_pipeline_layout: default
.max_dynamic_uniform_buffers_per_pipeline_layout,
max_dynamic_storage_buffers_per_pipeline_layout: default
.max_dynamic_storage_buffers_per_pipeline_layout,
max_sampled_textures_per_shader_stage: default.max_sampled_textures_per_shader_stage,
max_samplers_per_shader_stage: default.max_samplers_per_shader_stage,
max_storage_buffers_per_shader_stage: default.max_storage_buffers_per_shader_stage,
max_storage_textures_per_shader_stage: default.max_storage_textures_per_shader_stage,
max_uniform_buffers_per_shader_stage: default.max_uniform_buffers_per_shader_stage,
max_uniform_buffer_binding_size: default.max_uniform_buffer_binding_size,
max_push_constant_size: default.max_push_constant_size,
max_texture_dimension_1d: default.max_texture_dimension_1d,
max_texture_dimension_2d: default.max_texture_dimension_2d,
max_texture_dimension_3d: default.max_texture_dimension_3d,
max_texture_array_layers: default.max_texture_array_layers,
max_storage_buffer_binding_size: default.max_storage_buffer_binding_size,
max_vertex_buffers: default.max_vertex_buffers,
max_vertex_attributes: default.max_vertex_attributes,
max_vertex_buffer_array_stride: default.max_vertex_buffer_array_stride,
min_storage_buffer_offset_alignment: default.min_storage_buffer_offset_alignment,
min_uniform_buffer_offset_alignment: default.min_uniform_buffer_offset_alignment,
}
}
}

#[derive(Default, Clone)]
pub struct WgpuOptions {
pub device_label: Option<Cow<'static, str>>,
pub backend: WgpuBackend,
pub power_pref: WgpuPowerOptions,
pub features: WgpuFeatures,
pub limits: WgpuLimits,
}

#[derive(Clone)]
pub enum WgpuBackend {
Vulkan,
Metal,
Primary,
Dx12,
Dx11,
Gl,
BrowserWgpu,
}

impl WgpuBackend {
fn from_env() -> Self {
if let Ok(backend) = std::env::var("BEVY_WGPU_BACKEND") {
match backend.to_lowercase().as_str() {
"vulkan" => WgpuBackend::Vulkan,
"metal" => WgpuBackend::Metal,
"dx12" => WgpuBackend::Dx12,
"dx11" => WgpuBackend::Dx11,
"gl" => WgpuBackend::Gl,
"webgpu" => WgpuBackend::BrowserWgpu,
other => panic!("Unknown backend: {}", other),
}
} else if cfg!(target_arch = "wasm32") {
WgpuBackend::Gl
} else {
WgpuBackend::Primary
}
}
}

impl Default for WgpuBackend {
fn default() -> Self {
Self::from_env()
}
}

#[derive(Clone)]
pub enum WgpuPowerOptions {
HighPerformance,
Adaptive,
LowPower,
}

impl Default for WgpuPowerOptions {
fn default() -> Self {
WgpuPowerOptions::HighPerformance
}
}

impl From<WgpuFeature> for wgpu::Features {
fn from(value: WgpuFeature) -> Self {
match value {
WgpuFeature::DepthClamping => wgpu::Features::DEPTH_CLAMPING,
WgpuFeature::TextureCompressionBc => wgpu::Features::TEXTURE_COMPRESSION_BC,
WgpuFeature::TimestampQuery => wgpu::Features::TIMESTAMP_QUERY,
WgpuFeature::PipelineStatisticsQuery => wgpu::Features::PIPELINE_STATISTICS_QUERY,
WgpuFeature::MappablePrimaryBuffers => wgpu::Features::MAPPABLE_PRIMARY_BUFFERS,
WgpuFeature::UnsizedBindingArray => wgpu::Features::UNSIZED_BINDING_ARRAY,
WgpuFeature::MultiDrawIndirect => wgpu::Features::MULTI_DRAW_INDIRECT,
WgpuFeature::MultiDrawIndirectCount => wgpu::Features::MULTI_DRAW_INDIRECT_COUNT,
WgpuFeature::PushConstants => wgpu::Features::PUSH_CONSTANTS,
WgpuFeature::AddressModeClampToBorder => wgpu::Features::ADDRESS_MODE_CLAMP_TO_BORDER,
WgpuFeature::PolygonModeLine => wgpu::Features::POLYGON_MODE_LINE,
WgpuFeature::TextureCompressionEtc2 => wgpu::Features::TEXTURE_COMPRESSION_ETC2,
WgpuFeature::TextureCompressionAstcLdr => wgpu::Features::TEXTURE_COMPRESSION_ASTC_LDR,
WgpuFeature::TextureAdapterSpecificFormatFeatures => {
wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES
}
WgpuFeature::ShaderFloat64 => wgpu::Features::SHADER_FLOAT64,
WgpuFeature::VertexAttribute64Bit => wgpu::Features::VERTEX_ATTRIBUTE_64BIT,
}
}
}

impl From<WgpuFeatures> for wgpu::Features {
fn from(features: WgpuFeatures) -> Self {
features
.features
.iter()
.fold(wgpu::Features::empty(), |wgpu_features, feature| {
wgpu_features | (*feature).into()
})
}
}

impl From<WgpuLimits> for wgpu::Limits {
fn from(val: WgpuLimits) -> Self {
wgpu::Limits {
max_bind_groups: val.max_bind_groups,
max_dynamic_uniform_buffers_per_pipeline_layout: val
.max_dynamic_uniform_buffers_per_pipeline_layout,
max_dynamic_storage_buffers_per_pipeline_layout: val
.max_dynamic_storage_buffers_per_pipeline_layout,
max_sampled_textures_per_shader_stage: val.max_sampled_textures_per_shader_stage,
max_samplers_per_shader_stage: val.max_samplers_per_shader_stage,
max_storage_buffers_per_shader_stage: val.max_storage_buffers_per_shader_stage,
max_storage_textures_per_shader_stage: val.max_storage_textures_per_shader_stage,
max_uniform_buffers_per_shader_stage: val.max_uniform_buffers_per_shader_stage,
max_uniform_buffer_binding_size: val.max_uniform_buffer_binding_size,
max_push_constant_size: val.max_push_constant_size,
max_texture_dimension_1d: val.max_texture_dimension_1d,
max_texture_dimension_2d: val.max_texture_dimension_2d,
max_texture_dimension_3d: val.max_texture_dimension_3d,
max_texture_array_layers: val.max_texture_array_layers,
max_storage_buffer_binding_size: val.max_storage_buffer_binding_size,
max_vertex_buffers: val.max_vertex_buffers,
max_vertex_attributes: val.max_vertex_attributes,
max_vertex_buffer_array_stride: val.max_vertex_buffer_array_stride,
min_storage_buffer_offset_alignment: val.min_storage_buffer_offset_alignment,
min_uniform_buffer_offset_alignment: val.min_uniform_buffer_offset_alignment,
}
}
}

0 comments on commit fdb33f7

Please sign in to comment.