diff --git a/crates/bevy_render/src/base_render_graph/mod.rs b/crates/bevy_render/src/base_render_graph/mod.rs index 83fb3e0ba8..72576f8b08 100644 --- a/crates/bevy_render/src/base_render_graph/mod.rs +++ b/crates/bevy_render/src/base_render_graph/mod.rs @@ -109,6 +109,8 @@ impl BaseRenderGraphBuilder for RenderGraph { depth_store_op: StoreOp::Store, stencil_load_op: LoadOp::Clear, stencil_store_op: StoreOp::Store, + stencil_read_only: false, + depth_read_only: false, clear_depth: 1.0, clear_stencil: 0, }), diff --git a/crates/bevy_render/src/pass/pass.rs b/crates/bevy_render/src/pass/pass.rs index 4756b6a592..2807c732f4 100644 --- a/crates/bevy_render/src/pass/pass.rs +++ b/crates/bevy_render/src/pass/pass.rs @@ -44,6 +44,8 @@ pub struct RenderPassDepthStencilAttachmentDescriptor { pub clear_depth: f32, pub stencil_load_op: LoadOp, pub stencil_store_op: StoreOp, + pub depth_read_only: bool, + pub stencil_read_only: bool, pub clear_stencil: u32, } diff --git a/crates/bevy_render/src/render_graph/command.rs b/crates/bevy_render/src/render_graph/command.rs index 5619d55201..e318bd4229 100644 --- a/crates/bevy_render/src/render_graph/command.rs +++ b/crates/bevy_render/src/render_graph/command.rs @@ -17,7 +17,6 @@ pub enum Command { destination_texture: RenderResource, destination_origin: [u32; 3], destination_mip_level: u32, - destination_array_layer: u32, size: Extent3d, }, // TODO: Frees probably don't need to be queued? @@ -60,7 +59,6 @@ impl CommandQueue { destination_texture: RenderResource, destination_origin: [u32; 3], destination_mip_level: u32, - destination_array_layer: u32, size: Extent3d, ) { self.push(Command::CopyBufferToTexture { @@ -70,7 +68,6 @@ impl CommandQueue { destination_texture, destination_origin, destination_mip_level, - destination_array_layer, size, }); } @@ -102,7 +99,6 @@ impl CommandQueue { destination_texture, destination_origin, destination_mip_level, - destination_array_layer, size, } => render_context.copy_buffer_to_texture( source_buffer, @@ -111,7 +107,6 @@ impl CommandQueue { destination_texture, destination_origin, destination_mip_level, - destination_array_layer, size, ), Command::FreeBuffer(buffer) => render_context.resources().remove_buffer(buffer), diff --git a/crates/bevy_render/src/render_graph/nodes/texture_copy_node.rs b/crates/bevy_render/src/render_graph/nodes/texture_copy_node.rs index c10c61581e..853dd29aca 100644 --- a/crates/bevy_render/src/render_graph/nodes/texture_copy_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/texture_copy_node.rs @@ -14,6 +14,11 @@ pub struct TextureCopyNode { pub texture_event_reader: EventReader>, } +pub const ALIGNMENT: usize = 256; +fn get_aligned(data_size: f32) -> usize { + ALIGNMENT * ((data_size / ALIGNMENT as f32).ceil() as usize) +} + impl Node for TextureCopyNode { fn update( &mut self, @@ -30,12 +35,20 @@ impl Node for TextureCopyNode { AssetEvent::Created { handle } | AssetEvent::Modified { handle } => { if let Some(texture) = textures.get(&handle) { let texture_descriptor: TextureDescriptor = texture.into(); + let width = texture.size.x() as usize; + let aligned_width = get_aligned(texture.size.x()); + let format_size = 4; // TODO: this will be incorrect for some formats + let mut aligned_data = vec![0; format_size * aligned_width * texture.size.y() as usize]; + texture.data.chunks_exact(format_size * width).enumerate().for_each(|(index, row)| { + let offset = index * aligned_width * format_size; + aligned_data[offset..(offset + width * format_size)].copy_from_slice(row); + }); let texture_buffer = render_context.resources().create_buffer_with_data( BufferInfo { buffer_usage: BufferUsage::COPY_SRC, ..Default::default() }, - &texture.data, + &aligned_data, ); let texture_resource = render_context @@ -43,15 +56,13 @@ impl Node for TextureCopyNode { .get_asset_resource(*handle, TEXTURE_ASSET_INDEX) .unwrap(); - // TODO: bytes_per_row could be incorrect for some texture formats render_context.copy_buffer_to_texture( texture_buffer, 0, - 4 * texture.size.x() as u32, + (format_size * aligned_width) as u32, texture_resource, [0, 0, 0], 0, - 0, texture_descriptor.size.clone(), ); render_context.resources().remove_buffer(texture_buffer); diff --git a/crates/bevy_render/src/renderer/render_context.rs b/crates/bevy_render/src/renderer/render_context.rs index d85a78d278..09db8129f7 100644 --- a/crates/bevy_render/src/renderer/render_context.rs +++ b/crates/bevy_render/src/renderer/render_context.rs @@ -2,18 +2,12 @@ use super::RenderResourceContext; use crate::{ pass::{PassDescriptor, RenderPass}, render_resource::{RenderResource, RenderResourceAssignments}, - texture::{Extent3d, TextureDescriptor}, + texture::{Extent3d}, }; pub trait RenderContext { fn resources(&self) -> &dyn RenderResourceContext; fn resources_mut(&mut self) -> &mut dyn RenderResourceContext; - - fn create_texture_with_data( - &mut self, - texture_descriptor: TextureDescriptor, - bytes: &[u8], - ) -> RenderResource; fn copy_buffer_to_buffer( &mut self, source_buffer: RenderResource, @@ -30,7 +24,6 @@ pub trait RenderContext { destination_texture: RenderResource, destination_origin: [u32; 3], destination_mip_level: u32, - destination_array_layer: u32, size: Extent3d, ); fn begin_pass( diff --git a/crates/bevy_render/src/texture/sampler_descriptor.rs b/crates/bevy_render/src/texture/sampler_descriptor.rs index 9e56c0060d..9af43585a0 100644 --- a/crates/bevy_render/src/texture/sampler_descriptor.rs +++ b/crates/bevy_render/src/texture/sampler_descriptor.rs @@ -11,7 +11,8 @@ pub struct SamplerDescriptor { pub mipmap_filter: FilterMode, pub lod_min_clamp: f32, pub lod_max_clamp: f32, - pub compare_function: CompareFunction, + pub compare_function: Option, + pub anisotropy_clamp: Option, } impl Default for SamplerDescriptor { @@ -25,7 +26,8 @@ impl Default for SamplerDescriptor { mipmap_filter: FilterMode::Nearest, lod_min_clamp: -100.0, lod_max_clamp: 100.0, - compare_function: CompareFunction::Always, + compare_function: Some(CompareFunction::Always), + anisotropy_clamp: None, } } } @@ -41,7 +43,8 @@ impl From<&Texture> for SamplerDescriptor { mipmap_filter: FilterMode::Nearest, lod_min_clamp: -100.0, lod_max_clamp: 100.0, - compare_function: CompareFunction::Always, + compare_function: Some(CompareFunction::Always), + anisotropy_clamp: None, } } } diff --git a/crates/bevy_wgpu/Cargo.toml b/crates/bevy_wgpu/Cargo.toml index fd764a9d2d..1ebe5a48dc 100644 --- a/crates/bevy_wgpu/Cargo.toml +++ b/crates/bevy_wgpu/Cargo.toml @@ -19,10 +19,10 @@ bevy_winit = { path = "../bevy_winit", optional = true } legion = { path = "../bevy_legion" } # render -wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "89ee5bffd3c37279f733b76b05e5d030aba035db" } +wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "ff41d31200a5c5f0d7ddcd9a87b370c566936257" } # wgpu = { version = "0.5.0" } -futures = "0.3" +pollster = "0.2.0" log = { version = "0.4", features = ["release_max_level_info"] } crossbeam-channel = "0.4.2" crossbeam-utils = "0.7.2" \ No newline at end of file diff --git a/crates/bevy_wgpu/src/diagnostic/wgpu_resource_diagnostics_plugin.rs b/crates/bevy_wgpu/src/diagnostic/wgpu_resource_diagnostics_plugin.rs index 9349348c2d..9ed9c62050 100644 --- a/crates/bevy_wgpu/src/diagnostic/wgpu_resource_diagnostics_plugin.rs +++ b/crates/bevy_wgpu/src/diagnostic/wgpu_resource_diagnostics_plugin.rs @@ -125,7 +125,7 @@ impl WgpuResourceDiagnosticsPlugin { Self::SWAP_CHAIN_OUTPUTS, render_resource_context .resources - .swap_chain_outputs + .swap_chain_frames .read() .unwrap() .len() as f64, diff --git a/crates/bevy_wgpu/src/lib.rs b/crates/bevy_wgpu/src/lib.rs index 43b7dbcd85..150ab5d8fa 100644 --- a/crates/bevy_wgpu/src/lib.rs +++ b/crates/bevy_wgpu/src/lib.rs @@ -29,7 +29,7 @@ pub fn wgpu_render_system(resources: &mut Resources) -> impl FnMut(&mut World, & let mut wgpu_renderer = { let window_resized_event = resources.get::>().unwrap(); let window_created_event = resources.get::>().unwrap(); - futures::executor::block_on(WgpuRenderer::new( + pollster::block_on(WgpuRenderer::new( window_resized_event.get_reader(), window_created_event.get_reader(), )) diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs index 0527de4d48..b003c1761b 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs @@ -8,7 +8,7 @@ use bevy_render::{ }, render_resource::{RenderResource, RenderResourceAssignment, RenderResourceAssignments}, renderer::{RenderContext, RenderResourceContext}, - texture::{Extent3d, TextureDescriptor}, + texture::Extent3d, }; use std::{collections::HashMap, sync::Arc}; @@ -71,17 +71,6 @@ impl WgpuRenderContext { } impl RenderContext for WgpuRenderContext { - fn create_texture_with_data( - &mut self, - texture_descriptor: TextureDescriptor, - bytes: &[u8], - ) -> RenderResource { - self.render_resources.create_texture_with_data( - self.command_encoder.get_or_create(&self.device), - texture_descriptor, - bytes, - ) - } fn copy_buffer_to_buffer( &mut self, source_buffer: RenderResource, @@ -108,7 +97,6 @@ impl RenderContext for WgpuRenderContext { destination_texture: RenderResource, destination_origin: [u32; 3], destination_mip_level: u32, - destination_array_layer: u32, size: Extent3d, ) { self.render_resources.copy_buffer_to_texture( @@ -119,7 +107,6 @@ impl RenderContext for WgpuRenderContext { destination_texture, destination_origin, destination_mip_level, - destination_array_layer, size, ) } @@ -200,7 +187,7 @@ fn get_texture_view<'a>( panic!("Color attachment {} does not exist", name); } }, - TextureAttachment::RenderResource(render_resource) => refs.textures.get(&render_resource).unwrap_or_else(|| &refs.swap_chain_outputs.get(&render_resource).unwrap().view), + TextureAttachment::RenderResource(render_resource) => refs.textures.get(&render_resource).unwrap_or_else(|| &refs.swap_chain_frames.get(&render_resource).unwrap().output.view), TextureAttachment::Input(_) => panic!("Encountered unset TextureAttachment::Input. The RenderGraph executor should always set TextureAttachment::Inputs to TextureAttachment::RenderResource before running. This is a bug"), } } @@ -257,5 +244,7 @@ fn create_wgpu_depth_stencil_attachment_descriptor<'a>( stencil_store_op: depth_stencil_attachment_descriptor .stencil_store_op .wgpu_into(), + depth_read_only: depth_stencil_attachment_descriptor.depth_read_only, + stencil_read_only: depth_stencil_attachment_descriptor.stencil_read_only, } } diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index cd94e99a2f..1ebcba0750 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -36,46 +36,6 @@ impl WgpuRenderResourceContext { window_surfaces.insert(window_id, surface); } - pub fn create_texture_with_data( - &mut self, - command_encoder: &mut wgpu::CommandEncoder, - texture_descriptor: TextureDescriptor, - bytes: &[u8], - ) -> RenderResource { - let mut resource_info = self.resources.resource_info.write().unwrap(); - let mut texture_views = self.resources.texture_views.write().unwrap(); - let mut textures = self.resources.textures.write().unwrap(); - - let descriptor: wgpu::TextureDescriptor = (&texture_descriptor).wgpu_into(); - let texture = self.device.create_texture(&descriptor); - let texture_view = texture.create_default_view(); - let temp_buf = self - .device - .create_buffer_with_data(bytes, wgpu::BufferUsage::COPY_SRC); - command_encoder.copy_buffer_to_texture( - wgpu::BufferCopyView { - buffer: &temp_buf, - offset: 0, - bytes_per_row: 4 * descriptor.size.width, - rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height? - }, - wgpu::TextureCopyView { - texture: &texture, - mip_level: 0, - array_layer: 0, - origin: wgpu::Origin3d { x: 0, y: 0, z: 0 }, - }, - descriptor.size, - ); - - let resource = RenderResource::new(); - resource_info.insert(resource, ResourceInfo::Texture(texture_descriptor)); - texture_views.insert(resource, texture_view); - textures.insert(resource, texture); - - resource - } - pub fn copy_buffer_to_buffer( &self, command_encoder: &mut wgpu::CommandEncoder, @@ -107,7 +67,6 @@ impl WgpuRenderResourceContext { destination_texture: RenderResource, destination_origin: [u32; 3], // TODO: replace with math type destination_mip_level: u32, - destination_array_layer: u32, size: Extent3d, ) { let buffers = self.resources.buffers.read().unwrap(); @@ -118,14 +77,15 @@ impl WgpuRenderResourceContext { command_encoder.copy_buffer_to_texture( wgpu::BufferCopyView { buffer: source, - offset: source_offset, - bytes_per_row: source_bytes_per_row, - rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height? + layout: wgpu::TextureDataLayout { + offset: source_offset, + bytes_per_row: source_bytes_per_row, + rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height? + }, }, wgpu::TextureCopyView { texture: destination, mip_level: destination_mip_level, - array_layer: destination_array_layer, origin: wgpu::Origin3d { x: destination_origin[0], y: destination_origin[1], @@ -207,6 +167,7 @@ impl RenderResourceContext for WgpuRenderResourceContext { label: None, size: buffer_info.size as u64, usage: buffer_info.buffer_usage.wgpu_into(), + mapped_at_creation: false, }); let resource = RenderResource::new(); @@ -220,14 +181,24 @@ impl RenderResourceContext for WgpuRenderResourceContext { buffer_info: BufferInfo, setup_data: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext), ) -> RenderResource { - let mut mapped = self.device.create_buffer_mapped(&wgpu::BufferDescriptor { + let usage: wgpu::BufferUsage = buffer_info.buffer_usage.wgpu_into(); + let buffer = self.device.create_buffer(&wgpu::BufferDescriptor { size: buffer_info.size as u64, - usage: buffer_info.buffer_usage.wgpu_into(), + usage: usage | wgpu::BufferUsage::MAP_WRITE, label: None, + mapped_at_creation: false, }); - setup_data(&mut mapped.data(), self); - let buffer = mapped.finish(); + let data = buffer.map_async(wgpu::MapMode::Write, 0, wgpu::BufferSize::WHOLE); + self.device.poll(wgpu::Maintain::Wait); + if let Ok(()) = pollster::block_on(data) { + let data = buffer.get_mapped_range_mut(0, wgpu::BufferSize::WHOLE); + setup_data(data, self); + } else { + panic!("failed to map buffer to host"); + } + + buffer.unmap(); let resource = RenderResource::new(); let mut resource_info = self.resources.resource_info.write().unwrap(); let mut buffers = self.resources.buffers.write().unwrap(); @@ -326,10 +297,10 @@ impl RenderResourceContext for WgpuRenderResourceContext { fn next_swap_chain_texture(&self, window_id: bevy_window::WindowId) -> RenderResource { let mut window_swap_chains = self.resources.window_swap_chains.write().unwrap(); - let mut swap_chain_outputs = self.resources.swap_chain_outputs.write().unwrap(); + let mut swap_chain_outputs = self.resources.swap_chain_frames.write().unwrap(); let window_swap_chain = window_swap_chains.get_mut(&window_id).unwrap(); - let next_texture = window_swap_chain.get_next_texture().unwrap(); + let next_texture = window_swap_chain.get_next_frame().unwrap(); // TODO: Add ResourceInfo let render_resource = RenderResource::new(); @@ -338,12 +309,12 @@ impl RenderResourceContext for WgpuRenderResourceContext { } fn drop_swap_chain_texture(&self, render_resource: RenderResource) { - let mut swap_chain_outputs = self.resources.swap_chain_outputs.write().unwrap(); + let mut swap_chain_outputs = self.resources.swap_chain_frames.write().unwrap(); swap_chain_outputs.remove(&render_resource); } fn drop_all_swap_chain_textures(&self) { - let mut swap_chain_outputs = self.resources.swap_chain_outputs.write().unwrap(); + let mut swap_chain_outputs = self.resources.swap_chain_frames.write().unwrap(); swap_chain_outputs.clear(); } @@ -521,10 +492,7 @@ impl RenderResourceContext for WgpuRenderResourceContext { } RenderResourceAssignment::Buffer { resource, range , .. } => { let buffer = buffers.get(&resource).unwrap(); - wgpu::BindingResource::Buffer { - buffer, - range: range.clone(), - } + wgpu::BindingResource::Buffer(buffer.slice(range.clone())) } }; wgpu::Binding { diff --git a/crates/bevy_wgpu/src/wgpu_render_pass.rs b/crates/bevy_wgpu/src/wgpu_render_pass.rs index 9e0502c499..cd9b8aa2d4 100644 --- a/crates/bevy_wgpu/src/wgpu_render_pass.rs +++ b/crates/bevy_wgpu/src/wgpu_render_pass.rs @@ -25,7 +25,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> { fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64) { let buffer = self.render_resources.buffers.get(&resource).unwrap(); self.render_pass - .set_vertex_buffer(start_slot, &buffer, offset, 0); + .set_vertex_buffer(start_slot, buffer.slice(offset..)); } fn set_viewport(&mut self, x: f32, y: f32, w: f32, h: f32, min_depth: f32, max_depth: f32) { @@ -39,7 +39,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> { fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) { let buffer = self.render_resources.buffers.get(&resource).unwrap(); - self.render_pass.set_index_buffer(&buffer, offset, 0); + self.render_pass.set_index_buffer(buffer.slice(offset..)); } fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range) { diff --git a/crates/bevy_wgpu/src/wgpu_renderer.rs b/crates/bevy_wgpu/src/wgpu_renderer.rs index 8227f02cb8..7ecf72bf56 100644 --- a/crates/bevy_wgpu/src/wgpu_renderer.rs +++ b/crates/bevy_wgpu/src/wgpu_renderer.rs @@ -39,9 +39,7 @@ impl WgpuRenderer { let (device, queue) = adapter .request_device( &wgpu::DeviceDescriptor { - extensions: wgpu::Extensions { - anisotropic_filtering: false, - }, + extensions: wgpu::Extensions::empty(), limits: wgpu::Limits::default(), }, None, diff --git a/crates/bevy_wgpu/src/wgpu_resources.rs b/crates/bevy_wgpu/src/wgpu_resources.rs index 36823494af..8c8e22ffea 100644 --- a/crates/bevy_wgpu/src/wgpu_resources.rs +++ b/crates/bevy_wgpu/src/wgpu_resources.rs @@ -40,7 +40,7 @@ pub struct WgpuBindGroupInfo { pub struct WgpuResourcesReadLock<'a> { pub buffers: RwLockReadGuard<'a, HashMap>, pub textures: RwLockReadGuard<'a, HashMap>, - pub swap_chain_outputs: RwLockReadGuard<'a, HashMap>, + pub swap_chain_frames: RwLockReadGuard<'a, HashMap>, pub render_pipelines: RwLockReadGuard<'a, HashMap, wgpu::RenderPipeline>>, pub bind_groups: RwLockReadGuard<'a, HashMap>, @@ -51,7 +51,7 @@ impl<'a> WgpuResourcesReadLock<'a> { WgpuResourceRefs { buffers: &self.buffers, textures: &self.textures, - swap_chain_outputs: &self.swap_chain_outputs, + swap_chain_frames: &self.swap_chain_frames, render_pipelines: &self.render_pipelines, bind_groups: &self.bind_groups, } @@ -62,7 +62,7 @@ impl<'a> WgpuResourcesReadLock<'a> { pub struct WgpuResourceRefs<'a> { pub buffers: &'a HashMap, pub textures: &'a HashMap, - pub swap_chain_outputs: &'a HashMap, + pub swap_chain_frames: &'a HashMap, pub render_pipelines: &'a HashMap, wgpu::RenderPipeline>, pub bind_groups: &'a HashMap, } @@ -72,7 +72,7 @@ pub struct WgpuResources { pub resource_info: Arc>>, pub window_surfaces: Arc>>, pub window_swap_chains: Arc>>, - pub swap_chain_outputs: Arc>>, + pub swap_chain_frames: Arc>>, pub buffers: Arc>>, pub texture_views: Arc>>, pub textures: Arc>>, @@ -89,7 +89,7 @@ impl WgpuResources { WgpuResourcesReadLock { buffers: self.buffers.read().unwrap(), textures: self.texture_views.read().unwrap(), - swap_chain_outputs: self.swap_chain_outputs.read().unwrap(), + swap_chain_frames: self.swap_chain_frames.read().unwrap(), render_pipelines: self.render_pipelines.read().unwrap(), bind_groups: self.bind_groups.read().unwrap(), } diff --git a/crates/bevy_wgpu/src/wgpu_type_converter.rs b/crates/bevy_wgpu/src/wgpu_type_converter.rs index 1288775aef..f99eec1f6a 100644 --- a/crates/bevy_wgpu/src/wgpu_type_converter.rs +++ b/crates/bevy_wgpu/src/wgpu_type_converter.rs @@ -506,7 +506,8 @@ impl WgpuFrom for wgpu::SamplerDescriptor<'_> { mipmap_filter: sampler_descriptor.mipmap_filter.wgpu_into(), lod_min_clamp: sampler_descriptor.lod_min_clamp, lod_max_clamp: sampler_descriptor.lod_max_clamp, - compare: sampler_descriptor.compare_function.wgpu_into(), + compare: sampler_descriptor.compare_function.map(|c| c.wgpu_into()), + anisotropy_clamp: sampler_descriptor.anisotropy_clamp.clone(), } } }