more texture work
This commit is contained in:
		
							parent
							
								
									79c900bc2d
								
							
						
					
					
						commit
						1a4bd98434
					
				| @ -119,13 +119,20 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream { | ||||
|     }).collect::<Vec<String>>(); | ||||
| 
 | ||||
|     let mut uniform_name_strings = Vec::new(); | ||||
|     let field_uniform_names = active_uniform_field_name_strings.iter().map(|f| { | ||||
|         let uniform = format!("{}_{}", struct_name, f); | ||||
|     let mut texture_and_sampler_name_strings = Vec::new(); | ||||
|     let mut texture_and_sampler_name_idents = Vec::new(); | ||||
|     let field_uniform_names = active_uniform_fields.iter().map(|f| { | ||||
|         let field_name = f.ident.as_ref().unwrap().to_string(); | ||||
|         let uniform = format!("{}_{}", struct_name, field_name); | ||||
|         let texture = format!("{}_texture", uniform); | ||||
|         let sampler = format!("{}_sampler", uniform); | ||||
|         uniform_name_strings.push(uniform.clone()); | ||||
|         texture_and_sampler_name_strings.push(texture.clone()); | ||||
|         texture_and_sampler_name_strings.push(sampler.clone()); | ||||
|         texture_and_sampler_name_idents.push(f.ident.clone()); | ||||
|         texture_and_sampler_name_idents.push(f.ident.clone()); | ||||
|         quote!(bevy::render::render_graph::FieldUniformName { | ||||
|             field: #f, | ||||
|             field: #field_name, | ||||
|             uniform: #uniform, | ||||
|             texture: #texture, | ||||
|             sampler: #sampler,     
 | ||||
| @ -160,6 +167,14 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream { | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             fn get_uniform_texture(&self, name: &str) -> Option<bevy::asset::Handle<bevy::asset::Texture>> { | ||||
|                 use bevy::render::render_graph::GetTexture; | ||||
|                 match name { | ||||
|                     #(#texture_and_sampler_name_strings => self.#texture_and_sampler_name_idents.get_texture(),)* | ||||
|                     _ => None, | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // TODO: this will be very allocation heavy. find a way to either make this allocation free
 | ||||
|             // or alternatively only run it when the shader_defs have changed
 | ||||
|             fn get_shader_defs(&self) -> Option<Vec<String>> { | ||||
|  | ||||
| @ -12,7 +12,7 @@ fn setup(world: &mut World) { | ||||
| 
 | ||||
|     let texture_handle = { | ||||
|         let mut texture_storage = world.resources.get_mut::<AssetStorage<Texture>>().unwrap(); | ||||
|         let texture = Texture::load(TextureType::Data(asset::create_texels(256))); | ||||
|         let texture = Texture::load(TextureType::Data(asset::create_texels(256), 256, 256)); | ||||
|         texture_storage.add(texture) | ||||
|     }; | ||||
| 
 | ||||
|  | ||||
| @ -1,23 +1,44 @@ | ||||
| use crate::asset::Asset; | ||||
| use crate::{render::render_graph::{TextureDimension, TextureDescriptor}, asset::Asset}; | ||||
| 
 | ||||
| pub enum TextureType { | ||||
|     Data(Vec<u8>), | ||||
|     Data(Vec<u8>, usize, usize), | ||||
| } | ||||
| 
 | ||||
| pub struct Texture { | ||||
|     pub data: Vec<u8>, | ||||
|     pub width: usize, | ||||
|     pub height: usize, | ||||
| } | ||||
| 
 | ||||
| impl Asset<TextureType> for Texture { | ||||
|     fn load(descriptor: TextureType) -> Self { | ||||
|         let data = match descriptor { | ||||
|             TextureType::Data(data) => data.clone(), | ||||
|         let (data, width, height) = match descriptor { | ||||
|             TextureType::Data(data, width, height) => (data.clone(), width, height), | ||||
|         }; | ||||
| 
 | ||||
|         Texture { data } | ||||
|         Texture { data, width, height } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl From<&Texture> for TextureDescriptor { | ||||
|     fn from(texture: &Texture) -> Self { | ||||
|        TextureDescriptor { | ||||
|             size: wgpu::Extent3d { | ||||
|                 height: texture.height as u32, | ||||
|                 width: texture.width as u32, | ||||
|                 depth: 1, | ||||
|             }, | ||||
|             array_layer_count: 1, | ||||
|             mip_level_count: 1, | ||||
|             sample_count: 1, | ||||
|             dimension: TextureDimension::D2, | ||||
|             format: wgpu::TextureFormat::Rgba8UnormSrgb, | ||||
|             usage: wgpu::TextureUsage::SAMPLED | wgpu::TextureUsage::COPY_DST, | ||||
|        } 
 | ||||
|     } | ||||
|     
 | ||||
| } | ||||
| 
 | ||||
| pub fn create_texels(size: usize) -> Vec<u8> { | ||||
|     use std::iter; | ||||
| 
 | ||||
|  | ||||
| @ -241,3 +241,32 @@ impl From<TextureDescriptor> for wgpu::TextureDescriptor { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Copy, Clone)] | ||||
| pub struct SamplerDescriptor { | ||||
|     pub address_mode_u: wgpu::AddressMode, | ||||
|     pub address_mode_v: wgpu::AddressMode, | ||||
|     pub address_mode_w: wgpu::AddressMode, | ||||
|     pub mag_filter: wgpu::FilterMode, | ||||
|     pub min_filter: wgpu::FilterMode, | ||||
|     pub mipmap_filter: wgpu::FilterMode, | ||||
|     pub lod_min_clamp: f32, | ||||
|     pub lod_max_clamp: f32, | ||||
|     pub compare_function: wgpu::CompareFunction, | ||||
| } | ||||
| 
 | ||||
| impl From<SamplerDescriptor> for wgpu::SamplerDescriptor { | ||||
|     fn from(sampler_descriptor: SamplerDescriptor) -> Self { | ||||
|         wgpu::SamplerDescriptor { | ||||
|             address_mode_u: sampler_descriptor.address_mode_u, | ||||
|             address_mode_v: sampler_descriptor.address_mode_v, | ||||
|             address_mode_w: sampler_descriptor.address_mode_w, | ||||
|             mag_filter: sampler_descriptor.mag_filter, | ||||
|             min_filter: sampler_descriptor.min_filter, | ||||
|             mipmap_filter: sampler_descriptor.mipmap_filter, | ||||
|             lod_min_clamp: sampler_descriptor.lod_min_clamp, | ||||
|             lod_max_clamp: sampler_descriptor.lod_max_clamp, | ||||
|             compare_function: sampler_descriptor.compare_function, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -2,8 +2,8 @@ use crate::{ | ||||
|     legion::prelude::*, | ||||
|     render::render_graph::{ | ||||
|         render_resource::RenderResource, DynamicUniformBufferInfo, PipelineDescriptor, RenderGraph, | ||||
|         ResourceInfo, TextureDescriptor, | ||||
|     }, | ||||
|         ResourceInfo, TextureDescriptor, SamplerDescriptor | ||||
|     }, asset::{Handle, Texture}, | ||||
| }; | ||||
| use std::ops::Range; | ||||
| 
 | ||||
| @ -23,8 +23,8 @@ pub trait Renderer { | ||||
|         data: &[u8], | ||||
|         buffer_usage: wgpu::BufferUsage, | ||||
|     ) -> RenderResource; | ||||
|     fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource; | ||||
|     fn create_texture_with_data( | ||||
|     fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource; | ||||
|     fn create_texture( | ||||
|         &mut self, | ||||
|         texture_descriptor: &TextureDescriptor, | ||||
|         bytes: Option<&[u8]>, | ||||
| @ -67,6 +67,7 @@ pub trait Renderer { | ||||
|     ) -> RenderResource; | ||||
|     fn remove_buffer(&mut self, resource: RenderResource); | ||||
|     fn remove_texture(&mut self, resource: RenderResource); | ||||
|     fn remove_sampler(&mut self, resource: RenderResource); | ||||
|     fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo>; | ||||
|     fn copy_buffer_to_buffer( | ||||
|         &mut self, | ||||
| @ -78,6 +79,8 @@ pub trait Renderer { | ||||
|     ); | ||||
|     fn get_named_resource(&self, name: &str) -> Option<RenderResource>; | ||||
|     fn set_named_resource(&mut self, name: &str, resource: RenderResource); | ||||
|     fn get_texture_resource(&self, texture: Handle<Texture>) -> Option<RenderResource>; | ||||
|     fn set_texture_resource(&mut self, texture: Handle<Texture>, resource: RenderResource); | ||||
| } | ||||
| 
 | ||||
| pub trait RenderPass { | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| use crate::{ | ||||
|     asset::{AssetStorage, Handle}, | ||||
|     asset::{AssetStorage, Handle, Texture}, | ||||
|     legion::prelude::*, | ||||
|     render::{ | ||||
|         render_graph::{ | ||||
| @ -7,7 +7,7 @@ use crate::{ | ||||
|             DynamicUniformBufferInfo, PassDescriptor, PipelineDescriptor, PipelineLayout, | ||||
|             PipelineLayoutType, RenderGraph, RenderPass, RenderPassColorAttachmentDescriptor, | ||||
|             RenderPassDepthStencilAttachmentDescriptor, RenderResource, RenderResources, Renderer, | ||||
|             ResourceInfo, TextureDescriptor, | ||||
|             ResourceInfo, SamplerDescriptor, TextureDescriptor, | ||||
|         }, | ||||
|         Shader, | ||||
|     }, | ||||
| @ -23,6 +23,7 @@ pub struct WgpuRenderer { | ||||
|     pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>, | ||||
|     pub buffers: HashMap<RenderResource, wgpu::Buffer>, | ||||
|     pub textures: HashMap<RenderResource, wgpu::TextureView>, | ||||
|     pub samplers: HashMap<RenderResource, wgpu::Sampler>, | ||||
|     pub resource_info: HashMap<RenderResource, ResourceInfo>, | ||||
|     pub bind_groups: HashMap<u64, BindGroupInfo>, | ||||
|     pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>, | ||||
| @ -64,6 +65,7 @@ impl WgpuRenderer { | ||||
|             render_pipelines: HashMap::new(), | ||||
|             buffers: HashMap::new(), | ||||
|             textures: HashMap::new(), | ||||
|             samplers: HashMap::new(), | ||||
|             resource_info: HashMap::new(), | ||||
|             bind_groups: HashMap::new(), | ||||
|             bind_group_layouts: HashMap::new(), | ||||
| @ -304,11 +306,11 @@ impl WgpuRenderer { | ||||
|         if let None = self.bind_groups.get(&bind_group_id) { | ||||
|             let mut unset_uniforms = Vec::new(); | ||||
| 
 | ||||
|             let mut binding_resources = Vec::with_capacity(bind_group.bindings.len()); | ||||
|             let mut binding_resources = Vec::new(); | ||||
|             // if a uniform resource buffer doesn't exist, create a new empty one
 | ||||
|             for binding in bind_group.bindings.iter() { | ||||
|                 let resource = match self.render_resources.get_named_resource(&binding.name) { | ||||
|                     Some(resource) => resource, | ||||
|                     resource @ Some(_) => resource, | ||||
|                     None => { | ||||
|                         println!( | ||||
|                             "Warning: creating new empty buffer for binding {} {:?}", | ||||
| @ -325,14 +327,20 @@ impl WgpuRenderer { | ||||
| 
 | ||||
|                                 self.render_resources | ||||
|                                     .set_named_resource(&binding.name, resource); | ||||
|                                 resource | ||||
|                             } | ||||
|                                 Some(resource) | ||||
|                             }, | ||||
|                             BindType::Sampler | BindType::SampledTexture { .. } => { | ||||
|                                 // textures and samplers are handled per-entity
 | ||||
|                                 None | ||||
|                             }, | ||||
|                             _ => panic!("unsupported bind type: {:?}", binding), | ||||
|                         } | ||||
|                     } | ||||
|                 }; | ||||
| 
 | ||||
|                 binding_resources.push(resource); | ||||
|                 if let Some(resource) = resource { | ||||
|                     binding_resources.push(resource); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // create wgpu Bindings
 | ||||
| @ -474,7 +482,7 @@ impl Renderer for WgpuRenderer { | ||||
|         update_shader_assignments(world, render_graph); | ||||
| 
 | ||||
|         for (name, texture_descriptor) in render_graph.queued_textures.drain(..) { | ||||
|             let resource = self.create_texture(&texture_descriptor); | ||||
|             let resource = self.create_texture(&texture_descriptor, None); | ||||
|             self.render_resources.set_named_resource(&name, resource); | ||||
|         } | ||||
| 
 | ||||
| @ -709,16 +717,17 @@ impl Renderer for WgpuRenderer { | ||||
|         self.dynamic_uniform_buffer_info.insert(resource, info); | ||||
|     } | ||||
| 
 | ||||
|     fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource { | ||||
|         let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).into(); | ||||
|         let texture = self.device.create_texture(&descriptor); | ||||
|     fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource { | ||||
|         let descriptor: wgpu::SamplerDescriptor = (*sampler_descriptor).into(); | ||||
|         let sampler = self.device.create_sampler(&descriptor); | ||||
|         let resource = self.render_resources.get_next_resource(); | ||||
|         self.textures | ||||
|             .insert(resource, texture.create_default_view()); | ||||
|         self.samplers.insert(resource, sampler); | ||||
|         self.add_resource_info(resource, ResourceInfo::Texture); | ||||
|         resource | ||||
|     } | ||||
| 
 | ||||
|     fn create_texture_with_data( | ||||
| 
 | ||||
|     fn create_texture( | ||||
|         &mut self, | ||||
|         texture_descriptor: &TextureDescriptor, | ||||
|         bytes: Option<&[u8]>, | ||||
| @ -749,6 +758,7 @@ impl Renderer for WgpuRenderer { | ||||
| 
 | ||||
|         let resource = self.render_resources.get_next_resource(); | ||||
|         self.add_resource_info(resource, ResourceInfo::Texture); | ||||
|         self.textures.insert(resource, texture_view); | ||||
|         resource | ||||
|     } | ||||
| 
 | ||||
| @ -764,6 +774,19 @@ impl Renderer for WgpuRenderer { | ||||
|         self.textures.remove(&resource); | ||||
|         self.resource_info.remove(&resource); | ||||
|     } | ||||
| 
 | ||||
|     fn remove_sampler(&mut self, resource: RenderResource) { | ||||
|         self.samplers.remove(&resource); | ||||
|         self.resource_info.remove(&resource); | ||||
|     } | ||||
| 
 | ||||
|     fn get_texture_resource(&self, texture: Handle<Texture>) -> Option<RenderResource> { | ||||
|         self.render_resources.get_texture_resource(texture) | ||||
|     } | ||||
| 
 | ||||
|     fn set_texture_resource(&mut self, texture: Handle<Texture>, resource: RenderResource) { | ||||
|         self.render_resources.set_texture_resource(texture, resource); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub struct WgpuRenderPass<'a, 'b, 'c, 'd> { | ||||
|  | ||||
| @ -26,7 +26,7 @@ impl FrameTextureResourceProvider { | ||||
|             renderer.remove_texture(old_resource); | ||||
|         } | ||||
| 
 | ||||
|         let texture_resource = renderer.create_texture(&self.descriptor); | ||||
|         let texture_resource = renderer.create_texture(&self.descriptor, None); | ||||
|         renderer.set_named_resource(&self.name, texture_resource); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,6 +1,9 @@ | ||||
| use crate::render::render_graph::{ | ||||
|     render_resource::RenderResource, AsUniforms, BindType, DynamicUniformBufferInfo, Renderable, | ||||
|     Renderer, ResourceProvider, UniformInfoIter, | ||||
| use crate::{ | ||||
|     asset::{AssetStorage, Texture}, | ||||
|     render::render_graph::{ | ||||
|         render_resource::RenderResource, AsUniforms, BindType, DynamicUniformBufferInfo, | ||||
|         Renderable, Renderer, ResourceProvider, TextureDescriptor, UniformInfoIter, | ||||
|     }, | ||||
| }; | ||||
| use legion::prelude::*; | ||||
| use std::{marker::PhantomData, ops::Deref}; | ||||
| @ -68,11 +71,18 @@ where | ||||
|                         uniform_index += 1; | ||||
|                     } | ||||
|                     BindType::SampledTexture { .. } => { | ||||
|                         // TODO: look up Handle and load
 | ||||
|                     } | ||||
|                     BindType::Sampler { .. } => { | ||||
|                         // TODO: look up Handle and load
 | ||||
|                         let texture_handle = | ||||
|                             uniforms.get_uniform_texture(&uniform_info.name).unwrap(); | ||||
|                         let storage = world.resources.get::<AssetStorage<Texture>>().unwrap(); | ||||
|                         let texture = storage.get(&texture_handle).unwrap(); | ||||
|                         if let None = renderer.get_texture_resource(texture_handle.clone()) { | ||||
|                             let descriptor: TextureDescriptor = texture.into(); | ||||
|                             let resource = | ||||
|                                 renderer.create_texture(&descriptor, Some(&texture.data)); | ||||
|                             renderer.set_texture_resource(texture_handle, resource); | ||||
|                         } | ||||
|                     } | ||||
|                     BindType::Sampler { .. } => {} | ||||
|                     _ => panic!( | ||||
|                         "encountered unsupported bind_type {:?}", | ||||
|                         uniform_info.bind_type | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| use crate::{ | ||||
|     asset::{Handle, Texture}, | ||||
|     core::GetBytes, | ||||
|     math::Vec4, | ||||
|     render::{ | ||||
|         color::ColorSource, | ||||
|         render_graph::{BindType, TextureViewDimension}, | ||||
| @ -13,6 +13,7 @@ use std::collections::HashMap; | ||||
| pub trait AsUniforms { | ||||
|     fn get_field_uniform_names(&self) -> &[FieldUniformName]; | ||||
|     fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>; | ||||
|     fn get_uniform_texture(&self, name: &str) -> Option<Handle<Texture>>; | ||||
|     fn get_shader_defs(&self) -> Option<Vec<String>>; | ||||
|     fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType>; | ||||
|     // TODO: support zero-copy uniforms
 | ||||
| @ -125,18 +126,42 @@ impl AsFieldBindType for ColorSource { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| default impl<T> AsFieldBindType for T | ||||
| impl<T> AsFieldBindType for T | ||||
| where | ||||
|     T: GetBytes, | ||||
| { | ||||
|     fn get_field_bind_type(&self) -> FieldBindType { | ||||
|     default fn get_field_bind_type(&self) -> FieldBindType { | ||||
|         FieldBindType::Uniform | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AsFieldBindType for Vec4 { | ||||
|     fn get_field_bind_type(&self) -> FieldBindType { | ||||
|         FieldBindType::Uniform | ||||
| pub trait GetTexture { | ||||
|     fn get_texture(&self) -> Option<Handle<Texture>> { | ||||
|         None | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<T> GetTexture for T | ||||
| where | ||||
|     T: GetBytes, | ||||
| { | ||||
|     default fn get_texture(&self) -> Option<Handle<Texture>> { | ||||
|         None | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl GetTexture for Handle<Texture> { | ||||
|     fn get_texture(&self) -> Option<Handle<Texture>> { | ||||
|         Some(self.clone()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl GetTexture for ColorSource { | ||||
|     fn get_texture(&self) -> Option<Handle<Texture>> { | ||||
|         match self { | ||||
|             ColorSource::Color(_) => None, | ||||
|             ColorSource::Texture(texture) => Some(texture.clone()), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| use crate::render::render_graph::{uniform::AsUniforms, FieldBindType, FieldUniformName}; | ||||
| use crate::{asset::{Handle, Texture}, render::render_graph::{uniform::AsUniforms, FieldBindType, FieldUniformName}}; | ||||
| 
 | ||||
| use zerocopy::AsBytes; | ||||
| 
 | ||||
| @ -30,4 +30,7 @@ impl AsUniforms for bevy_transform::prelude::LocalToWorld { | ||||
|             _ => None, | ||||
|         } | ||||
|     } | ||||
|     fn get_uniform_texture(&self, _name: &str) -> Option<Handle<Texture>> { | ||||
|         None | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson