diff --git a/crates/bevy_pbr/src/render/mesh.rs b/crates/bevy_pbr/src/render/mesh.rs index 0bb456bcaa5fa0..7b5c0aa8ccd5ad 100644 --- a/crates/bevy_pbr/src/render/mesh.rs +++ b/crates/bevy_pbr/src/render/mesh.rs @@ -20,10 +20,8 @@ use bevy_render::{ render_asset::RenderAssets, render_phase::{EntityRenderCommand, RenderCommandResult, TrackedRenderPass}, render_resource::*, - renderer::{RenderDevice, RenderQueue}, - texture::{ - BevyDefault, DefaultImageSampler, GpuImage, Image, ImageSampler, TextureFormatPixelInfo, - }, + renderer::{AvailableTextureFormats, RenderDevice, RenderQueue}, + texture::{DefaultImageSampler, GpuImage, Image, ImageSampler, TextureFormatPixelInfo}, view::{ComputedVisibility, ViewUniform, ViewUniformOffset, ViewUniforms}, Extract, RenderApp, RenderStage, }; @@ -263,8 +261,10 @@ impl FromWorld for MeshPipeline { Res, Res, Res, + Res, )> = SystemState::new(world); - let (render_device, default_sampler, render_queue) = system_state.get_mut(world); + let (render_device, default_sampler, render_queue, available_texture_formats) = + system_state.get_mut(world); let clustered_forward_buffer_binding_type = render_device .get_supported_read_only_binding_type(CLUSTERED_FORWARD_STORAGE_BUFFER_COUNT); @@ -421,7 +421,7 @@ impl FromWorld for MeshPipeline { Extent3d::default(), TextureDimension::D2, &[255u8; 4], - TextureFormat::bevy_default(), + available_texture_formats[0], ); let texture = render_device.create_texture(&image.texture_descriptor); let sampler = match image.sampler_descriptor { @@ -610,7 +610,7 @@ impl SpecializedMeshPipeline for MeshPipeline { shader_defs, entry_point: "fragment".into(), targets: vec![Some(ColorTargetState { - format: TextureFormat::bevy_default(), + format: self.dummy_white_gpu_image.texture_format, blend, write_mask: ColorWrites::ALL, })], diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index bebf80dde2fcdd..bed1314e495b17 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -148,14 +148,19 @@ impl Plugin for RenderPlugin { compatible_surface: surface.as_ref(), ..Default::default() }; - let (device, queue, adapter_info) = futures_lite::future::block_on( - renderer::initialize_renderer(&instance, &options, &request_adapter_options), - ); + let (device, queue, adapter_info, render_adapter, available_texture_formats) = + 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(adapter_info.clone()) + .insert_resource(render_adapter.clone()) + .insert_resource(available_texture_formats.clone()) .init_resource::() .register_type::() .register_type::(); @@ -197,6 +202,8 @@ impl Plugin for RenderPlugin { .insert_resource(instance) .insert_resource(device) .insert_resource(queue) + .insert_resource(render_adapter) + .insert_resource(available_texture_formats) .insert_resource(adapter_info) .insert_resource(pipeline_cache) .insert_resource(asset_server) diff --git a/crates/bevy_render/src/renderer/mod.rs b/crates/bevy_render/src/renderer/mod.rs index bc95217dabcaf3..6ea6dea072285c 100644 --- a/crates/bevy_render/src/renderer/mod.rs +++ b/crates/bevy_render/src/renderer/mod.rs @@ -14,7 +14,7 @@ use bevy_ecs::prelude::*; use bevy_time::TimeSender; use bevy_utils::Instant; use std::sync::Arc; -use wgpu::{AdapterInfo, CommandEncoder, Instance, Queue, RequestAdapterOptions}; +use wgpu::{Adapter, 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) { @@ -86,17 +86,28 @@ pub fn render_system(world: &mut World) { /// This queue is used to enqueue tasks for the GPU to execute asynchronously. pub type RenderQueue = Arc; +/// This is the adapter that the GPU is using to render. +pub type RenderAdapter = Arc; + /// The GPU instance is used to initialize the [`RenderQueue`] and [`RenderDevice`], /// aswell as to create [`WindowSurfaces`](crate::view::window::WindowSurfaces). pub type RenderInstance = Instance; +pub type AvailableTextureFormats = Arc>; + /// Initializes the renderer by retrieving and preparing the GPU instance, device and queue /// for the specified backend. pub async fn initialize_renderer( instance: &Instance, options: &WgpuSettings, request_adapter_options: &RequestAdapterOptions<'_>, -) -> (RenderDevice, RenderQueue, AdapterInfo) { +) -> ( + RenderDevice, + RenderQueue, + AdapterInfo, + RenderAdapter, + AvailableTextureFormats, +) { let adapter = instance .request_adapter(request_adapter_options) .await @@ -243,9 +254,22 @@ pub async fn initialize_renderer( ) .await .unwrap(); + let device = Arc::new(device); let queue = Arc::new(queue); - (RenderDevice::from(device), queue, adapter_info) + let adapter = Arc::new(adapter); + let mut available_texture_formats = Vec::new(); + if let Some(s) = request_adapter_options.compatible_surface { + available_texture_formats = s.get_supported_formats(&adapter); + }; + let available_texture_formats = Arc::new(available_texture_formats); + ( + RenderDevice::from(device), + queue, + adapter_info, + adapter, + available_texture_formats, + ) } /// The context with all information required to interact with the GPU. diff --git a/crates/bevy_render/src/view/mod.rs b/crates/bevy_render/src/view/mod.rs index 71e3597e3127be..9d2ece01ffcc18 100644 --- a/crates/bevy_render/src/view/mod.rs +++ b/crates/bevy_render/src/view/mod.rs @@ -15,7 +15,7 @@ use crate::{ rangefinder::ViewRangefinder3d, render_asset::RenderAssets, render_resource::{DynamicUniformBuffer, ShaderType, Texture, TextureView}, - renderer::{RenderDevice, RenderQueue}, + renderer::{AvailableTextureFormats, RenderDevice, RenderQueue}, texture::{BevyDefault, TextureCache}, RenderApp, RenderStage, }; @@ -183,6 +183,7 @@ fn prepare_view_targets( images: Res>, msaa: Res, render_device: Res, + available_texture_formats: Res, mut texture_cache: ResMut, cameras: Query<(Entity, &ExtractedCamera)>, ) { @@ -206,7 +207,7 @@ fn prepare_view_targets( mip_level_count: 1, sample_count: msaa.samples, dimension: TextureDimension::D2, - format: TextureFormat::bevy_default(), + format: available_texture_formats[0], usage: TextureUsages::RENDER_ATTACHMENT, }, ) diff --git a/crates/bevy_render/src/view/window.rs b/crates/bevy_render/src/view/window.rs index 4699cef2020068..f8649336b6a376 100644 --- a/crates/bevy_render/src/view/window.rs +++ b/crates/bevy_render/src/view/window.rs @@ -1,7 +1,6 @@ use crate::{ render_resource::TextureView, - renderer::{RenderDevice, RenderInstance}, - texture::BevyDefault, + renderer::{RenderAdapter, RenderDevice, RenderInstance}, Extract, RenderApp, RenderStage, }; use bevy_app::{App, Plugin}; @@ -9,7 +8,6 @@ use bevy_ecs::prelude::*; use bevy_utils::{tracing::debug, HashMap, HashSet}; use bevy_window::{PresentMode, RawWindowHandleWrapper, WindowClosed, WindowId, Windows}; use std::ops::{Deref, DerefMut}; -use wgpu::TextureFormat; /// Token to ensure a system runs on the main thread. #[derive(Default)] @@ -149,6 +147,7 @@ pub fn prepare_windows( mut window_surfaces: ResMut, render_device: Res, render_instance: Res, + render_adapter: Res, ) { let window_surfaces = window_surfaces.deref_mut(); for window in windows.windows.values_mut() { @@ -161,7 +160,7 @@ pub fn prepare_windows( }); let swap_chain_descriptor = wgpu::SurfaceConfiguration { - format: TextureFormat::bevy_default(), + format: surface.get_supported_formats(&render_adapter)[0], width: window.physical_width, height: window.physical_height, usage: wgpu::TextureUsages::RENDER_ATTACHMENT, @@ -173,7 +172,6 @@ pub fn prepare_windows( PresentMode::AutoNoVsync => wgpu::PresentMode::AutoNoVsync, }, }; - // Do the initial surface configuration if it hasn't been configured yet if window_surfaces.configured_windows.insert(window.id) || window.size_changed { render_device.configure_surface(surface, &swap_chain_descriptor); diff --git a/crates/bevy_sprite/src/mesh2d/mesh.rs b/crates/bevy_sprite/src/mesh2d/mesh.rs index 41188cd48679fd..13641bd3419449 100644 --- a/crates/bevy_sprite/src/mesh2d/mesh.rs +++ b/crates/bevy_sprite/src/mesh2d/mesh.rs @@ -197,7 +197,7 @@ impl FromWorld for Mesh2dPipeline { Extent3d::default(), TextureDimension::D2, &[255u8; 4], - TextureFormat::bevy_default(), + TextureFormat::Bgra8Unorm, ); let texture = render_device.create_texture(&image.texture_descriptor); let sampler = match image.sampler_descriptor { @@ -353,7 +353,7 @@ impl SpecializedMeshPipeline for Mesh2dPipeline { shader_defs, entry_point: "fragment".into(), targets: vec![Some(ColorTargetState { - format: TextureFormat::bevy_default(), + format: TextureFormat::Bgra8Unorm, blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], diff --git a/crates/bevy_sprite/src/render/mod.rs b/crates/bevy_sprite/src/render/mod.rs index fb07f730694475..b68f7144964c42 100644 --- a/crates/bevy_sprite/src/render/mod.rs +++ b/crates/bevy_sprite/src/render/mod.rs @@ -147,7 +147,7 @@ impl SpecializedRenderPipeline for SpritePipeline { shader_defs, entry_point: "fragment".into(), targets: vec![Some(ColorTargetState { - format: TextureFormat::bevy_default(), + format: TextureFormat::Bgra8Unorm, blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })], diff --git a/crates/bevy_ui/src/render/pipeline.rs b/crates/bevy_ui/src/render/pipeline.rs index 4404429afffe78..f4b3215ff5f136 100644 --- a/crates/bevy_ui/src/render/pipeline.rs +++ b/crates/bevy_ui/src/render/pipeline.rs @@ -1,16 +1,28 @@ -use bevy_ecs::prelude::*; +use bevy_ecs::{prelude::*, system::SystemState}; +use bevy_math::Vec2; use bevy_render::{ - render_resource::*, renderer::RenderDevice, texture::BevyDefault, view::ViewUniform, + render_resource::*, + renderer::{AvailableTextureFormats, RenderDevice, RenderQueue}, + texture::{DefaultImageSampler, GpuImage, Image, ImageSampler, TextureFormatPixelInfo}, + view::ViewUniform, }; pub struct UiPipeline { pub view_layout: BindGroupLayout, pub image_layout: BindGroupLayout, + pub dummy_white_gpu_image: GpuImage, } impl FromWorld for UiPipeline { fn from_world(world: &mut World) -> Self { - let render_device = world.resource::(); + let mut system_state: SystemState<( + Res, + Res, + Res, + Res, + )> = SystemState::new(world); + let (render_device, default_sampler, render_queue, available_texture_formats) = + system_state.get_mut(world); let view_layout = render_device.create_bind_group_layout(&BindGroupLayoutDescriptor { entries: &[BindGroupLayoutEntry { @@ -47,10 +59,57 @@ impl FromWorld for UiPipeline { ], label: Some("ui_image_layout"), }); + let dummy_white_gpu_image = { + let image = Image::new_fill( + Extent3d::default(), + TextureDimension::D2, + &[255u8; 4], + available_texture_formats[0], + ); + let texture = render_device.create_texture(&image.texture_descriptor); + let sampler = match image.sampler_descriptor { + ImageSampler::Default => (**default_sampler).clone(), + ImageSampler::Descriptor(descriptor) => render_device.create_sampler(&descriptor), + }; + + let format_size = image.texture_descriptor.format.pixel_size(); + render_queue.write_texture( + ImageCopyTexture { + texture: &texture, + mip_level: 0, + origin: Origin3d::ZERO, + aspect: TextureAspect::All, + }, + &image.data, + ImageDataLayout { + offset: 0, + bytes_per_row: Some( + std::num::NonZeroU32::new( + image.texture_descriptor.size.width * format_size as u32, + ) + .unwrap(), + ), + rows_per_image: None, + }, + image.texture_descriptor.size, + ); + let texture_view = texture.create_view(&TextureViewDescriptor::default()); + GpuImage { + texture, + texture_view, + texture_format: image.texture_descriptor.format, + sampler, + size: Vec2::new( + image.texture_descriptor.size.width as f32, + image.texture_descriptor.size.height as f32, + ), + } + }; UiPipeline { view_layout, image_layout, + dummy_white_gpu_image, } } } @@ -87,7 +146,7 @@ impl SpecializedRenderPipeline for UiPipeline { shader_defs, entry_point: "fragment".into(), targets: vec![Some(ColorTargetState { - format: TextureFormat::bevy_default(), + format: self.dummy_white_gpu_image.texture_format, blend: Some(BlendState::ALPHA_BLENDING), write_mask: ColorWrites::ALL, })],