From f47315afa3d9ca09d6f2fcf294e1642cd9b54518 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Fri, 24 Apr 2020 12:48:12 -0700 Subject: [PATCH] RenderGraph2: fix uniform node textures --- bevy_render/src/render_graph_2/command.rs | 68 +++++++++++++++++-- .../src/render_graph_2/nodes/uniform_node.rs | 18 +++++ bevy_render/src/renderer_2/render_context.rs | 13 +++- bevy_render/src/texture/texture_dimension.rs | 1 + .../src/renderer_2/wgpu_render_context.rs | 27 +++++++- bevy_wgpu/src/wgpu_resources.rs | 58 ++++++++++++++-- 6 files changed, 171 insertions(+), 14 deletions(-) diff --git a/bevy_render/src/render_graph_2/command.rs b/bevy_render/src/render_graph_2/command.rs index 67671c1aa0..7246d1a94d 100644 --- a/bevy_render/src/render_graph_2/command.rs +++ b/bevy_render/src/render_graph_2/command.rs @@ -1,5 +1,5 @@ -use crate::{renderer_2::RenderContext, render_resource::RenderResource}; -use std::{sync::{Arc, Mutex}, collections::VecDeque}; +use crate::{render_resource::RenderResource, renderer_2::RenderContext, texture::Extent3d}; +use std::sync::{Arc, Mutex}; pub enum Command { CopyBufferToBuffer { @@ -9,17 +9,28 @@ pub enum Command { destination_offset: u64, size: u64, }, + CopyBufferToTexture { + source_buffer: RenderResource, + source_offset: u64, + source_bytes_per_row: u32, + destination_texture: RenderResource, + destination_origin: [u32; 3], + destination_mip_level: u32, + destination_array_layer: u32, + size: Extent3d, + }, + FreeBuffer(RenderResource), } #[derive(Default, Clone)] pub struct CommandQueue { // TODO: this shouldn't really need a mutex. its just needs to be shared on whatever thread its scheduled on - queue: Arc>>, + queue: Arc>>, } impl CommandQueue { fn push(&mut self, command: Command) { - self.queue.lock().unwrap().push_front(command); + self.queue.lock().unwrap().push(command); } pub fn copy_buffer_to_buffer( @@ -39,6 +50,33 @@ impl CommandQueue { }); } + pub fn copy_buffer_to_texture( + &mut self, + source_buffer: RenderResource, + source_offset: u64, + source_bytes_per_row: u32, + destination_texture: RenderResource, + destination_origin: [u32; 3], + destination_mip_level: u32, + destination_array_layer: u32, + size: Extent3d, + ) { + self.push(Command::CopyBufferToTexture { + source_buffer, + source_offset, + source_bytes_per_row, + destination_texture, + destination_origin, + destination_mip_level, + destination_array_layer, + size, + }); + } + + pub fn free_buffer(&mut self, buffer: RenderResource) { + self.push(Command::FreeBuffer(buffer)); + } + pub fn execute(&mut self, render_context: &mut dyn RenderContext) { for command in self.queue.lock().unwrap().drain(..) { match command { @@ -55,7 +93,27 @@ impl CommandQueue { destination_offset, size, ), + Command::CopyBufferToTexture { + source_buffer, + source_offset, + source_bytes_per_row, + destination_texture, + destination_origin, + destination_mip_level, + destination_array_layer, + size, + } => render_context.copy_buffer_to_texture( + source_buffer, + source_offset, + source_bytes_per_row, + destination_texture, + destination_origin, + destination_mip_level, + destination_array_layer, + size, + ), + Command::FreeBuffer(buffer) => render_context.resources().remove_buffer(buffer), } } } -} \ No newline at end of file +} diff --git a/bevy_render/src/render_graph_2/nodes/uniform_node.rs b/bevy_render/src/render_graph_2/nodes/uniform_node.rs index e06f2de2a3..ac36072097 100644 --- a/bevy_render/src/render_graph_2/nodes/uniform_node.rs +++ b/bevy_render/src/render_graph_2/nodes/uniform_node.rs @@ -367,6 +367,7 @@ where fn setup_uniform_texture_resources( uniforms: &T, + command_queue: &mut CommandQueue, texture_storage: &AssetStorage, render_resource_context: &dyn RenderResourceContext, render_resource_assignments: &mut RenderResourceAssignments, @@ -395,6 +396,21 @@ where render_resource_context.create_texture(&texture_descriptor); // TODO: queue texture copy // .create_texture_with_data(&texture_descriptor, &texture.data); + let texture_buffer = render_resource_context.create_buffer_with_data(BufferInfo { + buffer_usage: BufferUsage::COPY_SRC, + ..Default::default() + }, &texture.data); + command_queue.copy_buffer_to_texture( + texture_buffer, + 0, + (4 * texture.width) as u32, + texture_resource, + [0, 0, 0], + 0, + 0, + texture_descriptor.size.clone(), + ); + command_queue.free_buffer(texture_buffer); let sampler_descriptor: SamplerDescriptor = texture.into(); let sampler_resource = @@ -521,6 +537,7 @@ where } else { Self::setup_uniform_texture_resources( &uniforms, + &mut command_queue, textures, render_resource_context, &mut renderable.render_resource_assignments, @@ -541,6 +558,7 @@ where .expect("Handle points to a non-existent resource"); Self::setup_uniform_texture_resources( &uniforms, + &mut command_queue, textures, render_resource_context, &mut renderable.render_resource_assignments, diff --git a/bevy_render/src/renderer_2/render_context.rs b/bevy_render/src/renderer_2/render_context.rs index a6055b62e4..a7ef2e7150 100644 --- a/bevy_render/src/renderer_2/render_context.rs +++ b/bevy_render/src/renderer_2/render_context.rs @@ -4,7 +4,7 @@ use crate::{ pipeline::{BindGroupDescriptor, PipelineDescriptor}, render_resource::{RenderResource, RenderResourceAssignments, RenderResourceSetId}, shader::Shader, - texture::TextureDescriptor, + texture::{Extent3d, TextureDescriptor}, }; use bevy_asset::{AssetStorage, Handle}; @@ -25,6 +25,17 @@ pub trait RenderContext { destination_offset: u64, size: u64, ); + fn copy_buffer_to_texture( + &mut self, + source_buffer: RenderResource, + source_offset: u64, + source_bytes_per_row: u32, + destination_texture: RenderResource, + destination_origin: [u32; 3], + destination_mip_level: u32, + destination_array_layer: u32, + size: Extent3d, + ); fn create_bind_group( &mut self, bind_group_descriptor: &BindGroupDescriptor, diff --git a/bevy_render/src/texture/texture_dimension.rs b/bevy_render/src/texture/texture_dimension.rs index 1f90173992..c3c1537ad4 100644 --- a/bevy_render/src/texture/texture_dimension.rs +++ b/bevy_render/src/texture/texture_dimension.rs @@ -17,6 +17,7 @@ pub enum TextureDimension { D3, } +// TODO: use math type here #[derive(Clone, Copy, Debug)] pub struct Extent3d { pub width: u32, diff --git a/bevy_wgpu/src/renderer_2/wgpu_render_context.rs b/bevy_wgpu/src/renderer_2/wgpu_render_context.rs index 8a30d53a09..9010859f14 100644 --- a/bevy_wgpu/src/renderer_2/wgpu_render_context.rs +++ b/bevy_wgpu/src/renderer_2/wgpu_render_context.rs @@ -15,7 +15,7 @@ use bevy_render::{ }, renderer_2::{RenderContext, RenderResourceContext}, shader::Shader, - texture::TextureDescriptor, + texture::{Extent3d, TextureDescriptor}, }; use bevy_window::WindowId; use std::{collections::HashMap, sync::Arc}; @@ -140,7 +140,7 @@ impl RenderContext for WgpuRenderContext { let textures = self .render_resources .wgpu_resources - .textures + .texture_views .read() .unwrap(); let samplers = self @@ -443,6 +443,29 @@ impl RenderContext for WgpuRenderContext { self.command_encoder.set(encoder); } + fn copy_buffer_to_texture( + &mut self, + source_buffer: RenderResource, + source_offset: u64, + source_bytes_per_row: u32, + destination_texture: RenderResource, + destination_origin: [u32; 3], + destination_mip_level: u32, + destination_array_layer: u32, + size: Extent3d, + ) { + self.render_resources.wgpu_resources.copy_buffer_to_texture( + self.command_encoder.get_or_create(&self.device), + source_buffer, + source_offset, + source_bytes_per_row, + destination_texture, + destination_origin, + destination_mip_level, + destination_array_layer, + size, + ) + } } pub fn create_render_pass<'a, 'b>( diff --git a/bevy_wgpu/src/wgpu_resources.rs b/bevy_wgpu/src/wgpu_resources.rs index 3d1e3aa686..0b65560050 100644 --- a/bevy_wgpu/src/wgpu_resources.rs +++ b/bevy_wgpu/src/wgpu_resources.rs @@ -5,7 +5,7 @@ use bevy_render::{ render_resource::{BufferInfo, RenderResource, RenderResourceSetId, ResourceInfo}, renderer_2::RenderResourceContext, shader::Shader, - texture::{SamplerDescriptor, TextureDescriptor}, + texture::{Extent3d, SamplerDescriptor, TextureDescriptor}, }; use bevy_window::{Window, WindowId}; use std::{ @@ -77,7 +77,8 @@ pub struct WgpuResources { pub window_swap_chains: Arc>>, pub swap_chain_outputs: Arc>>, pub buffers: Arc>>, - pub textures: Arc>>, + pub texture_views: Arc>>, + pub textures: Arc>>, pub samplers: Arc>>, pub resource_info: Arc>>, pub shader_modules: Arc, wgpu::ShaderModule>>>, @@ -91,7 +92,7 @@ impl WgpuResources { pub fn read(&self) -> WgpuResourcesReadLock { WgpuResourcesReadLock { buffers: self.buffers.read().unwrap(), - textures: self.textures.read().unwrap(), + textures: self.texture_views.read().unwrap(), swap_chain_outputs: self.swap_chain_outputs.read().unwrap(), render_pipelines: self.render_pipelines.read().unwrap(), bind_groups: self.bind_groups.read().unwrap(), @@ -119,7 +120,10 @@ impl WgpuResources { } pub fn remove_swap_chain_texture(&self, render_resource: RenderResource) { - self.swap_chain_outputs.write().unwrap().remove(&render_resource); + self.swap_chain_outputs + .write() + .unwrap() + .remove(&render_resource); } pub fn remove_all_swap_chain_textures(&self) { @@ -274,6 +278,43 @@ impl WgpuResources { encoder.copy_buffer_to_buffer(source, source_offset, destination, destination_offset, size); } + pub fn copy_buffer_to_texture( + &self, + encoder: &mut wgpu::CommandEncoder, + source_buffer: RenderResource, + source_offset: u64, + source_bytes_per_row: u32, + 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.buffers.read().unwrap(); + let textures = self.textures.read().unwrap(); + let source = buffers.get(&source_buffer).unwrap(); + let destination = textures.get(&destination_texture).unwrap(); + 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? + }, + 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], + z: destination_origin[2], + }, + }, + size.wgpu_into(), + ); + } + pub fn create_shader_module( &self, device: &wgpu::Device, @@ -310,10 +351,14 @@ impl WgpuResources { let texture_view = texture.create_default_view(); let resource = RenderResource::new(); self.add_resource_info(resource, ResourceInfo::Texture); - self.textures + self.texture_views .write() .unwrap() .insert(resource, texture_view); + self.textures + .write() + .unwrap() + .insert(resource, texture); resource } @@ -346,7 +391,7 @@ impl WgpuResources { let resource = RenderResource::new(); self.add_resource_info(resource, ResourceInfo::Texture); - self.textures + self.texture_views .write() .unwrap() .insert(resource, texture_view); @@ -354,6 +399,7 @@ impl WgpuResources { } pub fn remove_texture(&self, resource: RenderResource) { + self.texture_views.write().unwrap().remove(&resource); self.textures.write().unwrap().remove(&resource); self.resource_info.write().unwrap().remove(&resource); }