Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - bevy_render: Use RenderDevice to get limits/features and expose AdapterInfo #3931

Closed
wants to merge 8 commits into from
6 changes: 2 additions & 4 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use bevy_render::{
camera::{Camera, CameraProjection},
color::Color,
mesh::Mesh,
options::WgpuOptions,
render_asset::RenderAssets,
render_graph::{Node, NodeRunError, RenderGraphContext, SlotInfo, SlotType},
render_phase::{
Expand Down Expand Up @@ -607,7 +606,6 @@ pub fn prepare_lights(
directional_light_shadow_map: Res<ExtractedDirectionalLightShadowMap>,
point_lights: Query<(Entity, &ExtractedPointLight)>,
directional_lights: Query<(Entity, &ExtractedDirectionalLight)>,
wgpu_options: Res<WgpuOptions>,
) {
light_meta.view_gpu_lights.clear();

Expand Down Expand Up @@ -697,9 +695,9 @@ pub fn prepare_lights(
TextureDescriptor {
size: Extent3d {
width: (directional_light_shadow_map.size as u32)
.min(wgpu_options.limits.max_texture_dimension_2d),
.min(render_device.limits().max_texture_dimension_2d),
height: (directional_light_shadow_map.size as u32)
.min(wgpu_options.limits.max_texture_dimension_2d),
.min(render_device.limits().max_texture_dimension_2d),
depth_or_array_layers: DIRECTIONAL_SHADOW_LAYERS,
},
mip_level_count: 1,
Expand Down
22 changes: 10 additions & 12 deletions crates/bevy_render/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
pub mod camera;
pub mod color;
pub mod mesh;
pub mod options;
pub mod primitives;
pub mod render_asset;
pub mod render_component;
pub mod render_graph;
pub mod render_phase;
pub mod render_resource;
pub mod renderer;
pub mod settings;
pub mod texture;
pub mod view;

Expand Down Expand Up @@ -108,9 +108,9 @@ 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 mut options = app
let options = app
.world
.get_resource::<options::WgpuOptions>()
.get_resource::<settings::WgpuSettings>()
.cloned()
.unwrap_or_default();

Expand All @@ -134,16 +134,14 @@ impl Plugin for RenderPlugin {
compatible_surface: surface.as_ref(),
..Default::default()
};
let (device, queue) = futures_lite::future::block_on(renderer::initialize_renderer(
&instance,
&mut options,
&request_adapter_options,
));
debug!("Configured wgpu adapter Limits: {:#?}", &options.limits);
debug!("Configured wgpu adapter Features: {:#?}", &options.features);
let (device, queue, adapter_info) = futures_lite::future::block_on(
renderer::initialize_renderer(&instance, &options, &request_adapter_options),
);
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
debug!("Configured wgpu adapter Features: {:#?}", device.features());
app.insert_resource(device.clone())
.insert_resource(queue.clone())
.insert_resource(options.clone())
.insert_resource(adapter_info.clone())
.init_resource::<ScratchRenderWorld>()
.register_type::<Frustum>()
.register_type::<CubemapFrusta>();
Expand Down Expand Up @@ -171,7 +169,7 @@ impl Plugin for RenderPlugin {
.insert_resource(instance)
.insert_resource(device)
.insert_resource(queue)
.insert_resource(options)
.insert_resource(adapter_info)
.insert_resource(render_pipeline_cache)
.insert_resource(asset_server)
.init_resource::<RenderGraph>();
Expand Down
35 changes: 18 additions & 17 deletions crates/bevy_render/src/render_resource/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,24 @@ pub use uniform_vec::*;

// TODO: decide where re-exports should go
pub use wgpu::{
util::BufferInitDescriptor, AddressMode, BindGroupDescriptor, BindGroupEntry,
BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType, BlendComponent,
BlendFactor, BlendOperation, BlendState, BufferAddress, BufferBinding, BufferBindingType,
BufferDescriptor, BufferSize, BufferUsages, ColorTargetState, ColorWrites, CommandEncoder,
CommandEncoderDescriptor, CompareFunction, ComputePassDescriptor, ComputePipelineDescriptor,
DepthBiasState, DepthStencilState, Extent3d, Face, Features as WgpuFeatures, FilterMode,
FragmentState as RawFragmentState, FrontFace, ImageCopyBuffer, ImageCopyBufferBase,
ImageCopyTexture, ImageCopyTextureBase, ImageDataLayout, ImageSubresourceRange, IndexFormat,
Limits as WgpuLimits, LoadOp, MapMode, MultisampleState, Operations, Origin3d, PipelineLayout,
PipelineLayoutDescriptor, PolygonMode, PrimitiveState, PrimitiveTopology,
RenderPassColorAttachment, RenderPassDepthStencilAttachment, RenderPassDescriptor,
RenderPipelineDescriptor as RawRenderPipelineDescriptor, SamplerBindingType, SamplerDescriptor,
ShaderModule, ShaderModuleDescriptor, ShaderSource, ShaderStages, StencilFaceState,
StencilOperation, StencilState, StorageTextureAccess, TextureAspect, TextureDescriptor,
TextureDimension, TextureFormat, TextureSampleType, TextureUsages, TextureViewDescriptor,
TextureViewDimension, VertexAttribute, VertexBufferLayout as RawVertexBufferLayout,
VertexFormat, VertexState as RawVertexState, VertexStepMode,
util::BufferInitDescriptor, AdapterInfo as WgpuAdapterInfo, AddressMode, BindGroupDescriptor,
BindGroupEntry, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingResource, BindingType,
BlendComponent, BlendFactor, BlendOperation, BlendState, BufferAddress, BufferBinding,
BufferBindingType, BufferDescriptor, BufferSize, BufferUsages, ColorTargetState, ColorWrites,
CommandEncoder, CommandEncoderDescriptor, CompareFunction, ComputePassDescriptor,
ComputePipelineDescriptor, DepthBiasState, DepthStencilState, Extent3d, Face,
Features as WgpuFeatures, FilterMode, FragmentState as RawFragmentState, FrontFace,
ImageCopyBuffer, ImageCopyBufferBase, ImageCopyTexture, ImageCopyTextureBase, ImageDataLayout,
ImageSubresourceRange, IndexFormat, Limits as WgpuLimits, LoadOp, MapMode, MultisampleState,
Operations, Origin3d, PipelineLayout, PipelineLayoutDescriptor, PolygonMode, PrimitiveState,
PrimitiveTopology, RenderPassColorAttachment, RenderPassDepthStencilAttachment,
RenderPassDescriptor, RenderPipelineDescriptor as RawRenderPipelineDescriptor,
SamplerBindingType, SamplerDescriptor, ShaderModule, ShaderModuleDescriptor, ShaderSource,
ShaderStages, StencilFaceState, StencilOperation, StencilState, StorageTextureAccess,
TextureAspect, TextureDescriptor, TextureDimension, TextureFormat, TextureSampleType,
TextureUsages, TextureViewDescriptor, TextureViewDimension, VertexAttribute,
VertexBufferLayout as RawVertexBufferLayout, VertexFormat, VertexState as RawVertexState,
VertexStepMode,
};

pub use bevy_crevice::*;
Expand Down
22 changes: 10 additions & 12 deletions crates/bevy_render/src/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ pub use graph_runner::*;
pub use render_device::*;

use crate::{
options::{WgpuOptions, WgpuOptionsPriority},
render_graph::RenderGraph,
settings::{WgpuSettings, WgpuSettingsPriority},
view::{ExtractedWindows, ViewTarget},
};
use bevy_ecs::prelude::*;
use std::sync::Arc;
use wgpu::{CommandEncoder, Instance, Queue, RequestAdapterOptions};
use wgpu::{AdapterInfo, 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) {
Expand Down Expand Up @@ -65,9 +65,9 @@ pub type RenderInstance = Instance;
/// for the specified backend.
pub async fn initialize_renderer(
instance: &Instance,
options: &mut WgpuOptions,
options: &WgpuSettings,
request_adapter_options: &RequestAdapterOptions<'_>,
) -> (RenderDevice, RenderQueue) {
) -> (RenderDevice, RenderQueue, AdapterInfo) {
let adapter = instance
.request_adapter(request_adapter_options)
.await
Expand All @@ -89,7 +89,7 @@ pub async fn initialize_renderer(
// Maybe get features and limits based on what is supported by the adapter/backend
let mut features = wgpu::Features::empty();
let mut limits = options.limits.clone();
if matches!(options.priority, WgpuOptionsPriority::Functionality) {
if matches!(options.priority, WgpuSettingsPriority::Functionality) {
features = adapter.features() | wgpu::Features::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES;
if adapter_info.device_type == wgpu::DeviceType::DiscreteGpu {
// `MAPPABLE_PRIMARY_BUFFERS` can have a significant, negative performance impact for
Expand All @@ -106,7 +106,7 @@ pub async fn initialize_renderer(
features -= disabled_features;
}
// NOTE: |= is used here to ensure that any explicitly-enabled features are respected.
options.features |= features;
features |= options.features;

// Enforce the limit constraints
if let Some(constrained_limits) = options.constrained_limits.as_ref() {
Expand All @@ -115,7 +115,7 @@ pub async fn initialize_renderer(
// specified max_limits. For 'min' limits, take the maximum instead. This is intended to
// err on the side of being conservative. We can't claim 'higher' limits that are supported
// but we can constrain to 'lower' limits.
options.limits = wgpu::Limits {
limits = wgpu::Limits {
max_texture_dimension_1d: limits
.max_texture_dimension_1d
.min(constrained_limits.max_texture_dimension_1d),
Expand Down Expand Up @@ -198,24 +198,22 @@ pub async fn initialize_renderer(
.max_compute_workgroups_per_dimension
.min(constrained_limits.max_compute_workgroups_per_dimension),
};
} else {
options.limits = limits;
}

let (device, queue) = adapter
.request_device(
&wgpu::DeviceDescriptor {
label: options.device_label.as_ref().map(|a| a.as_ref()),
features: options.features,
limits: options.limits.clone(),
features,
limits,
},
trace_path,
)
.await
.unwrap();
let device = Arc::new(device);
let queue = Arc::new(queue);
(RenderDevice::from(device), queue)
(RenderDevice::from(device), queue, adapter_info)
}

/// The context with all information required to interact with the GPU.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,33 @@ use std::borrow::Cow;
pub use wgpu::{Backends, Features as WgpuFeatures, Limits as WgpuLimits, PowerPreference};

#[derive(Clone)]
pub enum WgpuOptionsPriority {
pub enum WgpuSettingsPriority {
Compatibility,
Functionality,
WebGL2,
}

/// Provides configuration for renderer initialization. Use [RenderDevice::features](crate::renderer::RenderDevice::features),
/// [RenderDevice::limits](crate::renderer::RenderDevice::limits), and the [WgpuAdapterInfo](crate::render_resource::WgpuAdapterInfo)
/// resource to get runtime information about the actual adapter, backend, features, and limits.
#[derive(Clone)]
pub struct WgpuOptions {
pub struct WgpuSettings {
pub device_label: Option<Cow<'static, str>>,
pub backends: Option<Backends>,
pub power_preference: PowerPreference,
pub priority: WgpuOptionsPriority,
/// The enabled features. Setting features will require them to be enabled when initializing
/// the renderer.
pub priority: WgpuSettingsPriority,
/// The features to ensure are enabled regardless of what the adapter/backend supports.
/// Setting these explicitly may cause renderer initialization to fail.
pub features: WgpuFeatures,
/// The features to ensure are disabled regardless of what the adapter/backend supports
pub disabled_features: Option<WgpuFeatures>,
/// The imposed limits. Updated based on adapter/backend limits when initializing the renderer
/// if using WgpuOptionsPriority::Functionality
/// The imposed limits.
pub limits: WgpuLimits,
/// The constraints on limits allowed regardless of what the adapter/backend supports
pub constrained_limits: Option<WgpuLimits>,
}

impl Default for WgpuOptions {
impl Default for WgpuSettings {
fn default() -> Self {
let default_backends = if cfg!(feature = "webgl") {
Backends::GL
Expand All @@ -37,9 +39,10 @@ impl Default for WgpuOptions {

let backends = Some(wgpu::util::backend_bits_from_env().unwrap_or(default_backends));

let priority = options_priority_from_env().unwrap_or(WgpuOptionsPriority::Functionality);
let priority = settings_priority_from_env().unwrap_or(WgpuSettingsPriority::Functionality);

let limits = if cfg!(feature = "webgl") || matches!(priority, WgpuOptionsPriority::WebGL2) {
let limits = if cfg!(feature = "webgl") || matches!(priority, WgpuSettingsPriority::WebGL2)
{
wgpu::Limits::downlevel_webgl2_defaults()
} else {
#[allow(unused_mut)]
Expand All @@ -65,17 +68,17 @@ impl Default for WgpuOptions {
}
}

/// Get a features/limits priority from the environment variable `WGPU_OPTIONS_PRIO`
pub fn options_priority_from_env() -> Option<WgpuOptionsPriority> {
/// Get a features/limits priority from the environment variable `WGPU_SETTINGS_PRIO`
pub fn settings_priority_from_env() -> Option<WgpuSettingsPriority> {
Some(
match std::env::var("WGPU_OPTIONS_PRIO")
match std::env::var("WGPU_SETTINGS_PRIO")
.as_deref()
.map(str::to_lowercase)
.as_deref()
{
Ok("compatibility") => WgpuOptionsPriority::Compatibility,
Ok("functionality") => WgpuOptionsPriority::Functionality,
Ok("webgl2") => WgpuOptionsPriority::WebGL2,
Ok("compatibility") => WgpuSettingsPriority::Compatibility,
Ok("functionality") => WgpuSettingsPriority::Functionality,
Ok("webgl2") => WgpuSettingsPriority::WebGL2,
_ => return None,
},
)
Expand Down
4 changes: 2 additions & 2 deletions examples/3d/wireframe.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use bevy::{
pbr::wireframe::{Wireframe, WireframeConfig, WireframePlugin},
prelude::*,
render::{options::WgpuOptions, render_resource::WgpuFeatures},
render::{render_resource::WgpuFeatures, settings::WgpuSettings},
};

fn main() {
App::new()
.insert_resource(Msaa { samples: 4 })
.insert_resource(WgpuOptions {
.insert_resource(WgpuSettings {
features: WgpuFeatures::POLYGON_MODE_LINE,
..Default::default()
})
Expand Down
4 changes: 2 additions & 2 deletions examples/app/headless_defaults.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use bevy::{prelude::*, render::options::WgpuOptions};
use bevy::{prelude::*, render::settings::WgpuSettings};

fn main() {
App::new()
.insert_resource(WgpuOptions {
.insert_resource(WgpuSettings {
backends: None,
..Default::default()
})
Expand Down