From 81136c0989b50a204501079326e87c24bb7ed88a Mon Sep 17 00:00:00 2001 From: Elabajaba Date: Sun, 29 Jan 2023 20:27:30 +0000 Subject: [PATCH] Wgpu 0.15 (#7356) # Objective Update Bevy to wgpu 0.15. ## Changelog - Update to wgpu 0.15, wgpu-hal 0.15.1, and naga 0.11 - Users can now use the [DirectX Shader Compiler](https://github.com/microsoft/DirectXShaderCompiler) (DXC) on Windows with DX12 for faster shader compilation and ShaderModel 6.0+ support (requires `dxcompiler.dll` and `dxil.dll`, which are included in DXC downloads from [here](https://github.com/microsoft/DirectXShaderCompiler/releases/latest)) ## Migration Guide ### WGSL Top-Level `let` is now `const` All top level constants are now declared with `const`, catching up with the wgsl spec. `let` is no longer allowed at the global scope, only within functions. ```diff -let SOME_CONSTANT = 12.0; +const SOME_CONSTANT = 12.0; ``` #### `TextureDescriptor` and `SurfaceConfiguration` now requires a `view_formats` field The new `view_formats` field in the `TextureDescriptor` is used to specify a list of formats the texture can be re-interpreted to in a texture view. Currently only changing srgb-ness is allowed (ex. `Rgba8Unorm` <=> `Rgba8UnormSrgb`). You should set `view_formats` to `&[]` (empty) unless you have a specific reason not to. #### The DirectX Shader Compiler (DXC) is now supported on DX12 DXC is now the default shader compiler when using the DX12 backend. DXC is Microsoft's replacement for their legacy FXC compiler, and is faster, less buggy, and allows for modern shader features to be used (ShaderModel 6.0+). DXC requires `dxcompiler.dll` and `dxil.dll` to be available, otherwise it will log a warning and fall back to FXC. You can get `dxcompiler.dll` and `dxil.dll` by downloading the latest release from [Microsoft's DirectXShaderCompiler github repo](https://github.com/microsoft/DirectXShaderCompiler/releases/latest) and copying them into your project's root directory. These must be included when you distribute your Bevy game/app/etc if you plan on supporting the DX12 backend and are using DXC. `WgpuSettings` now has a `dx12_shader_compiler` field which can be used to choose between either FXC or DXC (if you pass None for the paths for DXC, it will check for the .dlls in the working directory). --- .gitignore | 2 + crates/bevy_core_pipeline/src/bloom/mod.rs | 1 + crates/bevy_core_pipeline/src/core_3d/mod.rs | 1 + crates/bevy_core_pipeline/src/fxaa/fxaa.wgsl | 24 ++++----- crates/bevy_pbr/src/prepass/mod.rs | 2 + .../src/render/clustered_forward.wgsl | 2 +- crates/bevy_pbr/src/render/light.rs | 2 + crates/bevy_pbr/src/render/mesh_types.wgsl | 4 +- .../bevy_pbr/src/render/mesh_view_types.wgsl | 16 +++--- crates/bevy_pbr/src/render/pbr_types.wgsl | 32 ++++++------ crates/bevy_pbr/src/render/utils.wgsl | 2 +- crates/bevy_render/Cargo.toml | 6 +-- crates/bevy_render/src/lib.rs | 9 +++- crates/bevy_render/src/renderer/mod.rs | 3 ++ crates/bevy_render/src/settings.rs | 13 ++++- crates/bevy_render/src/texture/image.rs | 1 + crates/bevy_render/src/view/mod.rs | 3 ++ crates/bevy_render/src/view/window.rs | 52 +++++++++++++++---- .../src/mesh2d/color_material.wgsl | 2 +- examples/3d/render_to_texture.rs | 1 + examples/shader/post_processing.rs | 1 + 21 files changed, 123 insertions(+), 56 deletions(-) diff --git a/.gitignore b/.gitignore index d1e9822c5bb7f4..0dc1de0df93cff 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ Cargo.lock /.idea /.vscode /benches/target +dxcompiler.dll +dxil.dll # Generated by "examples/scene/scene.rs" assets/scenes/load_scene_example-new.scn.ron diff --git a/crates/bevy_core_pipeline/src/bloom/mod.rs b/crates/bevy_core_pipeline/src/bloom/mod.rs index ad438b2a25dcf3..93d7090846f7f6 100644 --- a/crates/bevy_core_pipeline/src/bloom/mod.rs +++ b/crates/bevy_core_pipeline/src/bloom/mod.rs @@ -580,6 +580,7 @@ fn prepare_bloom_textures( dimension: TextureDimension::D2, format: ViewTarget::TEXTURE_FORMAT_HDR, usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING, + view_formats: &[], }; texture_descriptor.label = Some("bloom_texture_a"); diff --git a/crates/bevy_core_pipeline/src/core_3d/mod.rs b/crates/bevy_core_pipeline/src/core_3d/mod.rs index 1da08fc83193c3..78bf4b758a0f95 100644 --- a/crates/bevy_core_pipeline/src/core_3d/mod.rs +++ b/crates/bevy_core_pipeline/src/core_3d/mod.rs @@ -308,6 +308,7 @@ pub fn prepare_core_3d_depth_textures( // PERF: vulkan docs recommend using 24 bit depth for better performance format: TextureFormat::Depth32Float, usage, + view_formats: &[], }; texture_cache.get(&render_device, descriptor) diff --git a/crates/bevy_core_pipeline/src/fxaa/fxaa.wgsl b/crates/bevy_core_pipeline/src/fxaa/fxaa.wgsl index 1c24af6d80c328..13f409466264d9 100644 --- a/crates/bevy_core_pipeline/src/fxaa/fxaa.wgsl +++ b/crates/bevy_core_pipeline/src/fxaa/fxaa.wgsl @@ -15,48 +15,48 @@ var samp: sampler; // Trims the algorithm from processing darks. #ifdef EDGE_THRESH_MIN_LOW - let EDGE_THRESHOLD_MIN: f32 = 0.0833; + const EDGE_THRESHOLD_MIN: f32 = 0.0833; #endif #ifdef EDGE_THRESH_MIN_MEDIUM - let EDGE_THRESHOLD_MIN: f32 = 0.0625; + const EDGE_THRESHOLD_MIN: f32 = 0.0625; #endif #ifdef EDGE_THRESH_MIN_HIGH - let EDGE_THRESHOLD_MIN: f32 = 0.0312; + const EDGE_THRESHOLD_MIN: f32 = 0.0312; #endif #ifdef EDGE_THRESH_MIN_ULTRA - let EDGE_THRESHOLD_MIN: f32 = 0.0156; + const EDGE_THRESHOLD_MIN: f32 = 0.0156; #endif #ifdef EDGE_THRESH_MIN_EXTREME - let EDGE_THRESHOLD_MIN: f32 = 0.0078; + const EDGE_THRESHOLD_MIN: f32 = 0.0078; #endif // The minimum amount of local contrast required to apply algorithm. #ifdef EDGE_THRESH_LOW - let EDGE_THRESHOLD_MAX: f32 = 0.250; + const EDGE_THRESHOLD_MAX: f32 = 0.250; #endif #ifdef EDGE_THRESH_MEDIUM - let EDGE_THRESHOLD_MAX: f32 = 0.166; + const EDGE_THRESHOLD_MAX: f32 = 0.166; #endif #ifdef EDGE_THRESH_HIGH - let EDGE_THRESHOLD_MAX: f32 = 0.125; + const EDGE_THRESHOLD_MAX: f32 = 0.125; #endif #ifdef EDGE_THRESH_ULTRA - let EDGE_THRESHOLD_MAX: f32 = 0.063; + const EDGE_THRESHOLD_MAX: f32 = 0.063; #endif #ifdef EDGE_THRESH_EXTREME - let EDGE_THRESHOLD_MAX: f32 = 0.031; + const EDGE_THRESHOLD_MAX: f32 = 0.031; #endif -let ITERATIONS: i32 = 12; //default is 12 -let SUBPIXEL_QUALITY: f32 = 0.75; +const ITERATIONS: i32 = 12; //default is 12 +const SUBPIXEL_QUALITY: f32 = 0.75; // #define QUALITY(q) ((q) < 5 ? 1.0 : ((q) > 5 ? ((q) < 10 ? 2.0 : ((q) < 11 ? 4.0 : 8.0)) : 1.5)) fn QUALITY(q: i32) -> f32 { switch (q) { diff --git a/crates/bevy_pbr/src/prepass/mod.rs b/crates/bevy_pbr/src/prepass/mod.rs index f2492ed94c321b..3d31258a425e5e 100644 --- a/crates/bevy_pbr/src/prepass/mod.rs +++ b/crates/bevy_pbr/src/prepass/mod.rs @@ -411,6 +411,7 @@ pub fn prepare_prepass_textures( usage: TextureUsages::COPY_DST | TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING, + view_formats: &[], }; texture_cache.get(&render_device, descriptor) }) @@ -432,6 +433,7 @@ pub fn prepare_prepass_textures( format: NORMAL_PREPASS_FORMAT, usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING, + view_formats: &[], }, ) }) diff --git a/crates/bevy_pbr/src/render/clustered_forward.wgsl b/crates/bevy_pbr/src/render/clustered_forward.wgsl index 5939b7d31b2e73..9a467e3ad09446 100644 --- a/crates/bevy_pbr/src/render/clustered_forward.wgsl +++ b/crates/bevy_pbr/src/render/clustered_forward.wgsl @@ -27,7 +27,7 @@ fn fragment_cluster_index(frag_coord: vec2, view_z: f32, is_orthographic: b } // this must match CLUSTER_COUNT_SIZE in light.rs -let CLUSTER_COUNT_SIZE = 9u; +const CLUSTER_COUNT_SIZE = 9u; fn unpack_offset_and_counts(cluster_index: u32) -> vec3 { #if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3 return cluster_offsets_and_counts.data[cluster_index].xyz; diff --git a/crates/bevy_pbr/src/render/light.rs b/crates/bevy_pbr/src/render/light.rs index e08b8b14aac86c..05f8d30bd3ec8d 100644 --- a/crates/bevy_pbr/src/render/light.rs +++ b/crates/bevy_pbr/src/render/light.rs @@ -1043,6 +1043,7 @@ pub fn prepare_lights( format: SHADOW_FORMAT, label: Some("point_light_shadow_map_texture"), usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING, + view_formats: &[], }, ); let directional_light_depth_texture = texture_cache.get( @@ -1063,6 +1064,7 @@ pub fn prepare_lights( format: SHADOW_FORMAT, label: Some("directional_light_shadow_map_texture"), usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING, + view_formats: &[], }, ); let mut view_lights = Vec::new(); diff --git a/crates/bevy_pbr/src/render/mesh_types.wgsl b/crates/bevy_pbr/src/render/mesh_types.wgsl index d44adbc2bb13f8..9caebc73d01830 100644 --- a/crates/bevy_pbr/src/render/mesh_types.wgsl +++ b/crates/bevy_pbr/src/render/mesh_types.wgsl @@ -13,6 +13,6 @@ struct SkinnedMesh { }; #endif -let MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u; +const MESH_FLAGS_SHADOW_RECEIVER_BIT: u32 = 1u; // 2^31 - if the flag is set, the sign is positive, else it is negative -let MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT: u32 = 2147483648u; +const MESH_FLAGS_SIGN_DETERMINANT_MODEL_3X3_BIT: u32 = 2147483648u; diff --git a/crates/bevy_pbr/src/render/mesh_view_types.wgsl b/crates/bevy_pbr/src/render/mesh_view_types.wgsl index 3e797596fefa8f..c732cabc9453c4 100644 --- a/crates/bevy_pbr/src/render/mesh_view_types.wgsl +++ b/crates/bevy_pbr/src/render/mesh_view_types.wgsl @@ -25,8 +25,8 @@ struct PointLight { spot_light_tan_angle: f32, }; -let POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u; -let POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE: u32 = 2u; +const POINT_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u; +const POINT_LIGHT_FLAGS_SPOT_LIGHT_Y_NEGATIVE: u32 = 2u; struct DirectionalCascade { view_projection: mat4x4, @@ -47,7 +47,7 @@ struct DirectionalLight { depth_texture_base_index: u32, }; -let DIRECTIONAL_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u; +const DIRECTIONAL_LIGHT_FLAGS_SHADOWS_ENABLED_BIT: u32 = 1u; struct Lights { // NOTE: this array size must be kept in sync with the constants defined in bevy_pbr/src/render/light.rs @@ -89,11 +89,11 @@ struct Fog { } // Important: These must be kept in sync with `fog.rs` -let FOG_MODE_OFF: u32 = 0u; -let FOG_MODE_LINEAR: u32 = 1u; -let FOG_MODE_EXPONENTIAL: u32 = 2u; -let FOG_MODE_EXPONENTIAL_SQUARED: u32 = 3u; -let FOG_MODE_ATMOSPHERIC: u32 = 4u; +const FOG_MODE_OFF: u32 = 0u; +const FOG_MODE_LINEAR: u32 = 1u; +const FOG_MODE_EXPONENTIAL: u32 = 2u; +const FOG_MODE_EXPONENTIAL_SQUARED: u32 = 3u; +const FOG_MODE_ATMOSPHERIC: u32 = 4u; #if AVAILABLE_STORAGE_BUFFER_BINDINGS >= 3 struct PointLights { diff --git a/crates/bevy_pbr/src/render/pbr_types.wgsl b/crates/bevy_pbr/src/render/pbr_types.wgsl index c84ea79275c260..722f9b8411c21f 100644 --- a/crates/bevy_pbr/src/render/pbr_types.wgsl +++ b/crates/bevy_pbr/src/render/pbr_types.wgsl @@ -11,22 +11,22 @@ struct StandardMaterial { alpha_cutoff: f32, }; -let STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT: u32 = 1u; -let STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT: u32 = 2u; -let STANDARD_MATERIAL_FLAGS_METALLIC_ROUGHNESS_TEXTURE_BIT: u32 = 4u; -let STANDARD_MATERIAL_FLAGS_OCCLUSION_TEXTURE_BIT: u32 = 8u; -let STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT: u32 = 16u; -let STANDARD_MATERIAL_FLAGS_UNLIT_BIT: u32 = 32u; -let STANDARD_MATERIAL_FLAGS_TWO_COMPONENT_NORMAL_MAP: u32 = 64u; -let STANDARD_MATERIAL_FLAGS_FLIP_NORMAL_MAP_Y: u32 = 128u; -let STANDARD_MATERIAL_FLAGS_FOG_ENABLED_BIT: u32 = 256u; -let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS: u32 = 3758096384u; // (0b111u32 << 29) -let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE: u32 = 0u; // (0u32 << 29) -let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK: u32 = 536870912u; // (1u32 << 29) -let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_BLEND: u32 = 1073741824u; // (2u32 << 29) -let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_PREMULTIPLIED: u32 = 1610612736u; // (3u32 << 29) -let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_ADD: u32 = 2147483648u; // (4u32 << 29) -let STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MULTIPLY: u32 = 2684354560u; // (5u32 << 29) +const STANDARD_MATERIAL_FLAGS_BASE_COLOR_TEXTURE_BIT: u32 = 1u; +const STANDARD_MATERIAL_FLAGS_EMISSIVE_TEXTURE_BIT: u32 = 2u; +const STANDARD_MATERIAL_FLAGS_METALLIC_ROUGHNESS_TEXTURE_BIT: u32 = 4u; +const STANDARD_MATERIAL_FLAGS_OCCLUSION_TEXTURE_BIT: u32 = 8u; +const STANDARD_MATERIAL_FLAGS_DOUBLE_SIDED_BIT: u32 = 16u; +const STANDARD_MATERIAL_FLAGS_UNLIT_BIT: u32 = 32u; +const STANDARD_MATERIAL_FLAGS_TWO_COMPONENT_NORMAL_MAP: u32 = 64u; +const STANDARD_MATERIAL_FLAGS_FLIP_NORMAL_MAP_Y: u32 = 128u; +const STANDARD_MATERIAL_FLAGS_FOG_ENABLED_BIT: u32 = 256u; +const STANDARD_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS: u32 = 3758096384u; // (0b111u32 << 29) +const STANDARD_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE: u32 = 0u; // (0u32 << 29) +const STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MASK: u32 = 536870912u; // (1u32 << 29) +const STANDARD_MATERIAL_FLAGS_ALPHA_MODE_BLEND: u32 = 1073741824u; // (2u32 << 29) +const STANDARD_MATERIAL_FLAGS_ALPHA_MODE_PREMULTIPLIED: u32 = 1610612736u; // (3u32 << 29) +const STANDARD_MATERIAL_FLAGS_ALPHA_MODE_ADD: u32 = 2147483648u; // (4u32 << 29) +const STANDARD_MATERIAL_FLAGS_ALPHA_MODE_MULTIPLY: u32 = 2684354560u; // (5u32 << 29) // ↑ To calculate/verify the values above, use the following playground: // https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=7792f8dd6fc6a8d4d0b6b1776898a7f4 diff --git a/crates/bevy_pbr/src/render/utils.wgsl b/crates/bevy_pbr/src/render/utils.wgsl index d1da8611f13c5f..379c87e5e40bc7 100644 --- a/crates/bevy_pbr/src/render/utils.wgsl +++ b/crates/bevy_pbr/src/render/utils.wgsl @@ -1,6 +1,6 @@ #define_import_path bevy_pbr::utils -let PI: f32 = 3.141592653589793; +const PI: f32 = 3.141592653589793; fn hsv2rgb(hue: f32, saturation: f32, value: f32) -> vec3 { let rgb = clamp( diff --git a/crates/bevy_render/Cargo.toml b/crates/bevy_render/Cargo.toml index b47461e7693644..bff7571e26d65e 100644 --- a/crates/bevy_render/Cargo.toml +++ b/crates/bevy_render/Cargo.toml @@ -50,10 +50,10 @@ bevy_tasks = { path = "../bevy_tasks", version = "0.9.0" } image = { version = "0.24", default-features = false } # misc -wgpu = { version = "0.14.0", features = ["spirv"] } -wgpu-hal = "0.14.1" +wgpu = { version = "0.15.0", features = ["spirv"] } +wgpu-hal = "0.15.1" codespan-reporting = "0.11.0" -naga = { version = "0.10.0", features = ["glsl-in", "spv-in", "spv-out", "wgsl-in", "wgsl-out"] } +naga = { version = "0.11.0", features = ["glsl-in", "spv-in", "spv-out", "wgsl-in", "wgsl-out"] } serde = { version = "1", features = ["derive"] } bitflags = "1.2.1" smallvec = { version = "1.6", features = ["union", "const_generics"] } diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index 20bb6c61685156..5c2f42b0c7de05 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -148,11 +148,16 @@ impl Plugin for RenderPlugin { let primary_window = system_state.get(&app.world); if let Some(backends) = self.wgpu_settings.backends { - let instance = wgpu::Instance::new(backends); + let instance = wgpu::Instance::new(wgpu::InstanceDescriptor { + backends, + dx12_shader_compiler: self.wgpu_settings.dx12_shader_compiler.clone(), + }); let surface = primary_window.get_single().ok().map(|wrapper| unsafe { // SAFETY: Plugins should be set up on the main thread. let handle = wrapper.get_handle(); - instance.create_surface(&handle) + instance + .create_surface(&handle) + .expect("Failed to create wgpu surface") }); let request_adapter_options = wgpu::RequestAdapterOptions { diff --git a/crates/bevy_render/src/renderer/mod.rs b/crates/bevy_render/src/renderer/mod.rs index 5885003bfb76ee..b47f73b85e1b1d 100644 --- a/crates/bevy_render/src/renderer/mod.rs +++ b/crates/bevy_render/src/renderer/mod.rs @@ -251,6 +251,9 @@ pub async fn initialize_renderer( max_buffer_size: limits .max_buffer_size .min(constrained_limits.max_buffer_size), + max_bindings_per_bind_group: limits + .max_bindings_per_bind_group + .min(constrained_limits.max_bindings_per_bind_group), }; } diff --git a/crates/bevy_render/src/settings.rs b/crates/bevy_render/src/settings.rs index 62bdc7be43ba25..423038a263d728 100644 --- a/crates/bevy_render/src/settings.rs +++ b/crates/bevy_render/src/settings.rs @@ -1,6 +1,8 @@ use std::borrow::Cow; -pub use wgpu::{Backends, Features as WgpuFeatures, Limits as WgpuLimits, PowerPreference}; +pub use wgpu::{ + Backends, Dx12Compiler, Features as WgpuFeatures, Limits as WgpuLimits, PowerPreference, +}; /// Configures the priority used when automatically configuring the features/limits of `wgpu`. #[derive(Clone)] @@ -37,6 +39,8 @@ pub struct WgpuSettings { pub limits: WgpuLimits, /// The constraints on limits allowed regardless of what the adapter/backend supports pub constrained_limits: Option, + /// The shader compiler to use for the DX12 backend. + pub dx12_shader_compiler: Dx12Compiler, } impl Default for WgpuSettings { @@ -65,6 +69,12 @@ impl Default for WgpuSettings { limits }; + let dx12_compiler = + wgpu::util::dx12_shader_compiler_from_env().unwrap_or(Dx12Compiler::Dxc { + dxil_path: None, + dxc_path: None, + }); + Self { device_label: Default::default(), backends, @@ -74,6 +84,7 @@ impl Default for WgpuSettings { disabled_features: None, limits, constrained_limits: None, + dx12_shader_compiler: dx12_compiler, } } } diff --git a/crates/bevy_render/src/texture/image.rs b/crates/bevy_render/src/texture/image.rs index d2cfa72c80d263..0f37e78208cc9b 100644 --- a/crates/bevy_render/src/texture/image.rs +++ b/crates/bevy_render/src/texture/image.rs @@ -184,6 +184,7 @@ impl Default for Image { mip_level_count: 1, sample_count: 1, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, + view_formats: &[], }, sampler_descriptor: ImageSampler::Default, texture_view_descriptor: None, diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index b62222efc8f7e6..b0cae8eb296ea5 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -338,6 +338,8 @@ fn prepare_view_targets( format: main_texture_format, usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING, + // TODO: Consider changing this if main_texture_format is not sRGB + view_formats: &[], }; MainTargetTextures { a: texture_cache @@ -370,6 +372,7 @@ fn prepare_view_targets( dimension: TextureDimension::D2, format: main_texture_format, usage: TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], }, ) .default_view diff --git a/crates/bevy_render/src/view/window.rs b/crates/bevy_render/src/view/window.rs index 957455747f1ff3..4d3a507559694d 100644 --- a/crates/bevy_render/src/view/window.rs +++ b/crates/bevy_render/src/view/window.rs @@ -12,6 +12,8 @@ use bevy_window::{ use std::ops::{Deref, DerefMut}; use wgpu::TextureFormat; +use super::Msaa; + /// Token to ensure a system runs on the main thread. #[derive(Resource, Default)] pub struct NonSendMarker; @@ -176,6 +178,7 @@ pub fn prepare_windows( render_device: Res, render_instance: Res, render_adapter: Res, + mut msaa: ResMut, ) { for window in windows.windows.values_mut() { let window_surfaces = window_surfaces.deref_mut(); @@ -184,15 +187,26 @@ pub fn prepare_windows( .entry(window.entity) .or_insert_with(|| unsafe { // NOTE: On some OSes this MUST be called from the main thread. - let surface = render_instance.create_surface(&window.handle.get_handle()); - let format = *surface - .get_supported_formats(&render_adapter) - .get(0) - .unwrap_or_else(|| { - panic!( - "No supported formats found for surface {surface:?} on adapter {render_adapter:?}" - ) - }); + // As of wgpu 0.15, only failable if the given window is a HTML canvas and obtaining a WebGPU or WebGL2 context fails. + let surface = render_instance + .create_surface(&window.handle.get_handle()) + .expect("Failed to create wgpu surface"); + let caps = surface.get_capabilities(&render_adapter); + let formats = caps.formats; + // For future HDR output support, we'll need to request a format that supports HDR, + // but as of wgpu 0.15 that is not yet supported. + // Prefer sRGB formats for surfaces, but fall back to first available format if no sRGB formats are available. + let mut format = *formats.get(0).expect("No supported formats for surface"); + for available_format in formats { + // Rgba8UnormSrgb and Bgra8UnormSrgb and the only sRGB formats wgpu exposes that we can use for surfaces. + if available_format == TextureFormat::Rgba8UnormSrgb + || available_format == TextureFormat::Bgra8UnormSrgb + { + format = available_format; + break; + } + } + SurfaceData { surface, format } }); @@ -215,8 +229,28 @@ pub fn prepare_windows( CompositeAlphaMode::PostMultiplied => wgpu::CompositeAlphaMode::PostMultiplied, CompositeAlphaMode::Inherit => wgpu::CompositeAlphaMode::Inherit, }, + // TODO: Use an sRGB view format here on platforms that don't support sRGB surfaces. (afaik only WebGPU) + view_formats: vec![], }; + // This is an ugly hack to work around drivers that don't support MSAA. + // This should be removed once https://github.com/bevyengine/bevy/issues/7194 lands and we're doing proper + // feature detection for MSAA. + let sample_flags = render_adapter + .get_texture_format_features(surface_configuration.format) + .flags; + match *msaa { + Msaa::Off => (), + Msaa::Sample4 => { + if !sample_flags.contains(wgpu::TextureFormatFeatureFlags::MULTISAMPLE_X4) { + bevy_log::warn!( + "MSAA 4x is not supported on this device. Falling back to disabling MSAA." + ); + *msaa = Msaa::Off; + } + } + } + // A recurring issue is hitting `wgpu::SurfaceError::Timeout` on certain Linux // mesa driver implementations. This seems to be a quirk of some drivers. // We'd rather keep panicking when not on Linux mesa, because in those case, diff --git a/crates/bevy_sprite/src/mesh2d/color_material.wgsl b/crates/bevy_sprite/src/mesh2d/color_material.wgsl index 0e83d1487dcf22..a78eedbbb96d5b 100644 --- a/crates/bevy_sprite/src/mesh2d/color_material.wgsl +++ b/crates/bevy_sprite/src/mesh2d/color_material.wgsl @@ -6,7 +6,7 @@ struct ColorMaterial { // 'flags' is a bit field indicating various options. u32 is 32 bits so we have up to 32 options. flags: u32, }; -let COLOR_MATERIAL_FLAGS_TEXTURE_BIT: u32 = 1u; +const COLOR_MATERIAL_FLAGS_TEXTURE_BIT: u32 = 1u; @group(1) @binding(0) var material: ColorMaterial; diff --git a/examples/3d/render_to_texture.rs b/examples/3d/render_to_texture.rs index 043d43065756fb..77321460978314 100644 --- a/examples/3d/render_to_texture.rs +++ b/examples/3d/render_to_texture.rs @@ -55,6 +55,7 @@ fn setup( usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST | TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], }, ..default() }; diff --git a/examples/shader/post_processing.rs b/examples/shader/post_processing.rs index ea306fd97069f5..71eb37851c1792 100644 --- a/examples/shader/post_processing.rs +++ b/examples/shader/post_processing.rs @@ -61,6 +61,7 @@ fn setup( usage: TextureUsages::TEXTURE_BINDING | TextureUsages::COPY_DST | TextureUsages::RENDER_ATTACHMENT, + view_formats: &[], }, ..default() };