From 6995ac224935d90931d263d2005610a8dcc73de3 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Tue, 28 Dec 2021 00:02:06 +0100 Subject: [PATCH 1/3] bevy_render: Bump draw_state logs to trace level --- .../src/render_phase/draw_state.rs | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/crates/bevy_render/src/render_phase/draw_state.rs b/crates/bevy_render/src/render_phase/draw_state.rs index e96f2cb234ecd..c27f9bed5d53f 100644 --- a/crates/bevy_render/src/render_phase/draw_state.rs +++ b/crates/bevy_render/src/render_phase/draw_state.rs @@ -5,7 +5,7 @@ use crate::{ ShaderStages, }, }; -use bevy_utils::tracing::debug; +use bevy_utils::tracing::trace; use std::ops::Range; use wgpu::{IndexFormat, RenderPass}; @@ -108,7 +108,7 @@ impl<'a> TrackedRenderPass<'a> { /// /// Subsequent draw calls will exhibit the behavior defined by the `pipeline`. pub fn set_render_pipeline(&mut self, pipeline: &'a RenderPipeline) { - debug!("set pipeline: {:?}", pipeline); + trace!("set pipeline: {:?}", pipeline); if self.state.is_pipeline_set(pipeline.id()) { return; } @@ -128,15 +128,19 @@ impl<'a> TrackedRenderPass<'a> { .state .is_bind_group_set(index as usize, bind_group.id(), dynamic_uniform_indices) { - debug!( + trace!( "set bind_group {} (already set): {:?} ({:?})", - index, bind_group, dynamic_uniform_indices + index, + bind_group, + dynamic_uniform_indices ); return; } else { - debug!( + trace!( "set bind_group {}: {:?} ({:?})", - index, bind_group, dynamic_uniform_indices + index, + bind_group, + dynamic_uniform_indices ); } self.pass @@ -158,7 +162,7 @@ impl<'a> TrackedRenderPass<'a> { .state .is_vertex_buffer_set(slot_index, buffer_slice.id(), offset) { - debug!( + trace!( "set vertex buffer {} (already set): {:?} ({})", slot_index, buffer_slice.id(), @@ -166,7 +170,7 @@ impl<'a> TrackedRenderPass<'a> { ); return; } else { - debug!( + trace!( "set vertex buffer {}: {:?} ({})", slot_index, buffer_slice.id(), @@ -193,14 +197,14 @@ impl<'a> TrackedRenderPass<'a> { .state .is_index_buffer_set(buffer_slice.id(), offset, index_format) { - debug!( + trace!( "set index buffer (already set): {:?} ({})", buffer_slice.id(), offset ); return; } else { - debug!("set index buffer: {:?} ({})", buffer_slice.id(), offset); + trace!("set index buffer: {:?} ({})", buffer_slice.id(), offset); } self.pass.set_index_buffer(*buffer_slice, index_format); self.state @@ -211,7 +215,7 @@ impl<'a> TrackedRenderPass<'a> { /// /// The active vertex buffer(s) can be set with [`TrackedRenderPass::set_vertex_buffer`]. pub fn draw(&mut self, vertices: Range, instances: Range) { - debug!("draw: {:?} {:?}", vertices, instances); + trace!("draw: {:?} {:?}", vertices, instances); self.pass.draw(vertices, instances); } @@ -220,15 +224,17 @@ impl<'a> TrackedRenderPass<'a> { /// The active index buffer can be set with [`TrackedRenderPass::set_index_buffer`], while the /// active vertex buffer(s) can be set with [`TrackedRenderPass::set_vertex_buffer`]. pub fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { - debug!( + trace!( "draw indexed: {:?} {} {:?}", - indices, base_vertex, instances + indices, + base_vertex, + instances ); self.pass.draw_indexed(indices, base_vertex, instances); } pub fn set_stencil_reference(&mut self, reference: u32) { - debug!("set stencil reference: {}", reference); + trace!("set stencil reference: {}", reference); self.pass.set_stencil_reference(reference); } @@ -237,7 +243,7 @@ impl<'a> TrackedRenderPass<'a> { /// /// Subsequent draw calls will discard any fragments that fall outside this region. pub fn set_scissor_rect(&mut self, x: u32, y: u32, width: u32, height: u32) { - debug!("set_scissor_rect: {} {} {} {}", x, y, width, height); + trace!("set_scissor_rect: {} {} {} {}", x, y, width, height); self.pass.set_scissor_rect(x, y, width, height); } @@ -245,7 +251,7 @@ impl<'a> TrackedRenderPass<'a> { /// /// Features::PUSH_CONSTANTS must be enabled on the device in order to call these functions. pub fn set_push_constants(&mut self, stages: ShaderStages, offset: u32, data: &[u8]) { - debug!( + trace!( "set push constants: {:?} offset: {} data.len: {}", stages, offset, @@ -266,9 +272,14 @@ impl<'a> TrackedRenderPass<'a> { min_depth: f32, max_depth: f32, ) { - debug!( + trace!( "set viewport: {} {} {} {} {} {}", - x, y, width, height, min_depth, max_depth + x, + y, + width, + height, + min_depth, + max_depth ); self.pass .set_viewport(x, y, width, height, min_depth, max_depth) @@ -278,7 +289,7 @@ impl<'a> TrackedRenderPass<'a> { /// /// This is a GPU debugging feature. This has no effect on the rendering itself. pub fn insert_debug_marker(&mut self, label: &str) { - debug!("insert debug marker: {}", label); + trace!("insert debug marker: {}", label); self.pass.insert_debug_marker(label) } @@ -303,7 +314,7 @@ impl<'a> TrackedRenderPass<'a> { /// [`push_debug_group`]: TrackedRenderPass::push_debug_group /// [`pop_debug_group`]: TrackedRenderPass::pop_debug_group pub fn push_debug_group(&mut self, label: &str) { - debug!("push_debug_group marker: {}", label); + trace!("push_debug_group marker: {}", label); self.pass.push_debug_group(label) } @@ -320,12 +331,12 @@ impl<'a> TrackedRenderPass<'a> { /// [`push_debug_group`]: TrackedRenderPass::push_debug_group /// [`pop_debug_group`]: TrackedRenderPass::pop_debug_group pub fn pop_debug_group(&mut self) { - debug!("pop_debug_group"); + trace!("pop_debug_group"); self.pass.pop_debug_group() } pub fn set_blend_constant(&mut self, color: Color) { - debug!("set blend constant: {:?}", color); + trace!("set blend constant: {:?}", color); self.pass.set_blend_constant(wgpu::Color::from(color)) } } From aeb156533b97dae9d60b76a8475d6bff2ddbf513 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Tue, 28 Dec 2021 00:03:53 +0100 Subject: [PATCH 2/3] bevy_render: Default to maximum adapter wgpu features/limits Update WgpuOptions with the changes. Expose WgpuOptions resource to render app. --- crates/bevy_render/src/lib.rs | 24 ++++++------ crates/bevy_render/src/options.rs | 52 ++++++++++++++++++++------ crates/bevy_render/src/renderer/mod.rs | 20 ++++++++-- 3 files changed, 70 insertions(+), 26 deletions(-) diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 9e3b4a89a5a4a..69ee3ff2e91b1 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -27,6 +27,7 @@ pub mod prelude { }; } +use bevy_utils::tracing::debug; pub use once_cell; use crate::{ @@ -107,7 +108,7 @@ 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 options = app + let mut options = app .world .get_resource::() .cloned() @@ -122,21 +123,21 @@ impl Plugin for RenderPlugin { }); raw_handle }; + let request_adapter_options = wgpu::RequestAdapterOptions { + power_preference: options.power_preference, + compatible_surface: surface.as_ref(), + ..Default::default() + }; let (device, queue) = futures_lite::future::block_on(renderer::initialize_renderer( &instance, - &wgpu::RequestAdapterOptions { - power_preference: options.power_preference, - compatible_surface: surface.as_ref(), - ..Default::default() - }, - &wgpu::DeviceDescriptor { - label: options.device_label.as_ref().map(|a| a.as_ref()), - features: options.features, - limits: options.limits, - }, + &mut options, + &request_adapter_options, )); + debug!("Configured wgpu adapter Limits: {:#?}", &options.limits); + debug!("Configured wgpu adapter Features: {:#?}", &options.features); app.insert_resource(device.clone()) .insert_resource(queue.clone()) + .insert_resource(options.clone()) .add_asset::() .init_asset_loader::() .init_resource::() @@ -167,6 +168,7 @@ impl Plugin for RenderPlugin { .insert_resource(instance) .insert_resource(device) .insert_resource(queue) + .insert_resource(options) .insert_resource(render_pipeline_cache) .insert_resource(asset_server) .init_resource::(); diff --git a/crates/bevy_render/src/options.rs b/crates/bevy_render/src/options.rs index e517140c65fc0..ffaaf855ceb57 100644 --- a/crates/bevy_render/src/options.rs +++ b/crates/bevy_render/src/options.rs @@ -2,11 +2,19 @@ use std::borrow::Cow; pub use wgpu::{Backends, Features as WgpuFeatures, Limits as WgpuLimits, PowerPreference}; +#[derive(Clone)] +pub enum WgpuOptionsPriority { + Compatibility, + Functionality, + WebGL2, +} + #[derive(Clone)] pub struct WgpuOptions { pub device_label: Option>, pub backends: Backends, pub power_preference: PowerPreference, + pub priority: WgpuOptionsPriority, pub features: WgpuFeatures, pub limits: WgpuLimits, } @@ -21,25 +29,45 @@ impl Default for WgpuOptions { let backends = wgpu::util::backend_bits_from_env().unwrap_or(default_backends); - let limits = if cfg!(feature = "webgl") { - wgpu::Limits::downlevel_webgl2_defaults() - } else { - #[allow(unused_mut)] - let mut limits = wgpu::Limits::default(); - #[cfg(feature = "ci_limits")] - { - limits.max_storage_textures_per_shader_stage = 4; - limits.max_texture_dimension_3d = 1024; - } - limits - }; + let priority = options_priority_from_env().unwrap_or(WgpuOptionsPriority::Functionality); + + let limits = + if cfg!(feature = "webgl") || matches!(priority, WgpuOptionsPriority::WebGL2) { + wgpu::Limits::downlevel_webgl2_defaults() + } else { + #[allow(unused_mut)] + let mut limits = wgpu::Limits::default(); + #[cfg(feature = "ci_limits")] + { + limits.max_storage_textures_per_shader_stage = 4; + limits.max_texture_dimension_3d = 1024; + } + limits + }; Self { device_label: Default::default(), backends, power_preference: PowerPreference::HighPerformance, + priority, features: wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES, limits, } } } + +/// Get a features/limits priority from the environment variable WGPU_OPTIONS_PRIO +pub fn options_priority_from_env() -> Option { + Some( + match std::env::var("WGPU_OPTIONS_PRIO") + .as_deref() + .map(str::to_lowercase) + .as_deref() + { + Ok("compatibility") => WgpuOptionsPriority::Compatibility, + Ok("functionality") => WgpuOptionsPriority::Functionality, + Ok("webgl2") => WgpuOptionsPriority::WebGL2, + _ => return None, + }, + ) +} diff --git a/crates/bevy_render/src/renderer/mod.rs b/crates/bevy_render/src/renderer/mod.rs index 1f05d04e66a66..088ed97ad98dd 100644 --- a/crates/bevy_render/src/renderer/mod.rs +++ b/crates/bevy_render/src/renderer/mod.rs @@ -6,12 +6,13 @@ pub use graph_runner::*; pub use render_device::*; use crate::{ + options::{WgpuOptions, WgpuOptionsPriority}, render_graph::RenderGraph, view::{ExtractedWindows, ViewTarget}, }; use bevy_ecs::prelude::*; use std::sync::Arc; -use wgpu::{CommandEncoder, DeviceDescriptor, Instance, Queue, RequestAdapterOptions}; +use wgpu::{CommandEncoder, Instance, Queue, RequestAdapterOptions}; /// Updates the [`RenderGraph`] with all of its nodes and then runs it to render the entire frame. pub fn render_system(world: &mut World) { @@ -64,8 +65,8 @@ pub type RenderInstance = Instance; /// for the specified backend. pub async fn initialize_renderer( instance: &Instance, + options: &mut WgpuOptions, request_adapter_options: &RequestAdapterOptions<'_>, - device_descriptor: &DeviceDescriptor<'_>, ) -> (RenderDevice, RenderQueue) { let adapter = instance .request_adapter(request_adapter_options) @@ -84,8 +85,21 @@ pub async fn initialize_renderer( #[cfg(not(feature = "wgpu_trace"))] let trace_path = None; + if matches!(options.priority, WgpuOptionsPriority::Functionality) { + options.features = + adapter.features() | wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES; + options.limits = adapter.limits(); + } + let (device, queue) = adapter - .request_device(device_descriptor, trace_path) + .request_device( + &wgpu::DeviceDescriptor { + label: options.device_label.as_ref().map(|a| a.as_ref()), + features: options.features, + limits: options.limits.clone(), + }, + trace_path, + ) .await .unwrap(); let device = Arc::new(device); From 18b663e54245cc1f052e852defc404c030ea9d48 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Tue, 28 Dec 2021 00:04:34 +0100 Subject: [PATCH 3/3] bevy_pbr: Limit directional light shadow map texture to max texture size --- crates/bevy_pbr/src/render/light.rs | 8 ++++++-- crates/bevy_render/src/options.rs | 25 ++++++++++++------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index 0b7cbe8a12197..e824aa3f7db28 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -15,6 +15,7 @@ use bevy_render::{ camera::{Camera, CameraProjection}, color::Color, mesh::Mesh, + options::WgpuOptions, render_asset::RenderAssets, render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType}, render_phase::{ @@ -576,6 +577,7 @@ pub fn prepare_lights( directional_light_shadow_map: Res, point_lights: Query<(Entity, &ExtractedPointLight)>, directional_lights: Query<(Entity, &ExtractedDirectionalLight)>, + wgpu_options: Res, ) { light_meta.view_gpu_lights.clear(); @@ -664,8 +666,10 @@ pub fn prepare_lights( &render_device, TextureDescriptor { size: Extent3d { - width: directional_light_shadow_map.size as u32, - height: directional_light_shadow_map.size as u32, + width: (directional_light_shadow_map.size as u32) + .min(wgpu_options.limits.max_texture_dimension_2d), + height: (directional_light_shadow_map.size as u32) + .min(wgpu_options.limits.max_texture_dimension_2d), depth_or_array_layers: DIRECTIONAL_SHADOW_LAYERS, }, mip_level_count: 1, diff --git a/crates/bevy_render/src/options.rs b/crates/bevy_render/src/options.rs index ffaaf855ceb57..294582af2cb81 100644 --- a/crates/bevy_render/src/options.rs +++ b/crates/bevy_render/src/options.rs @@ -31,19 +31,18 @@ impl Default for WgpuOptions { let priority = options_priority_from_env().unwrap_or(WgpuOptionsPriority::Functionality); - let limits = - if cfg!(feature = "webgl") || matches!(priority, WgpuOptionsPriority::WebGL2) { - wgpu::Limits::downlevel_webgl2_defaults() - } else { - #[allow(unused_mut)] - let mut limits = wgpu::Limits::default(); - #[cfg(feature = "ci_limits")] - { - limits.max_storage_textures_per_shader_stage = 4; - limits.max_texture_dimension_3d = 1024; - } - limits - }; + let limits = if cfg!(feature = "webgl") || matches!(priority, WgpuOptionsPriority::WebGL2) { + wgpu::Limits::downlevel_webgl2_defaults() + } else { + #[allow(unused_mut)] + let mut limits = wgpu::Limits::default(); + #[cfg(feature = "ci_limits")] + { + limits.max_storage_textures_per_shader_stage = 4; + limits.max_texture_dimension_3d = 1024; + } + limits + }; Self { device_label: Default::default(),