mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
more texture work
This commit is contained in:
parent
79c900bc2d
commit
1a4bd98434
10 changed files with 171 additions and 42 deletions
|
@ -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 a new issue