merge asset resources / support arbitrary asset handles / make them RwLocked

This commit is contained in:
Carter Anderson 2020-04-15 12:48:04 -07:00
parent bcbddf8719
commit 1f5f432e6c
10 changed files with 120 additions and 138 deletions

View File

@ -3,7 +3,7 @@ use legion::prelude::*;
use crate::{ use crate::{
draw_target::DrawTarget, draw_target::DrawTarget,
mesh::Mesh, mesh::{self, Mesh},
pass::RenderPass, pass::RenderPass,
pipeline::{PipelineAssignments, PipelineDescriptor}, pipeline::{PipelineAssignments, PipelineDescriptor},
render_resource::{ render_resource::{
@ -49,15 +49,15 @@ impl DrawTarget for AssignedMeshesDrawTarget {
continue; continue;
} }
let mesh = *world.get_component::<Handle<Mesh>>(*entity).unwrap(); let mesh_handle = *world.get_component::<Handle<Mesh>>(*entity).unwrap();
let render_context = render_pass.get_render_context(); let render_context = render_pass.get_render_context();
let render_resources = render_context.resources(); let render_resources = render_context.resources();
if current_mesh_handle != Some(mesh) { if current_mesh_handle != Some(mesh_handle) {
if let Some(vertex_buffer_resource) = if let Some(vertex_buffer_resource) =
render_resources.get_mesh_vertices_resource(mesh) render_resources.get_asset_resource(mesh_handle, mesh::VERTEX_BUFFER_ASSET_INDEX)
{ {
let index_buffer_resource = let index_buffer_resource =
render_resources.get_mesh_indices_resource(mesh).unwrap(); render_resources.get_asset_resource(mesh_handle, mesh::INDEX_BUFFER_ASSET_INDEX).unwrap();
render_resources.get_resource_info( render_resources.get_resource_info(
index_buffer_resource, index_buffer_resource,
&mut |resource_info| match resource_info { &mut |resource_info| match resource_info {
@ -71,7 +71,7 @@ impl DrawTarget for AssignedMeshesDrawTarget {
render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0); render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0);
} }
// TODO: Verify buffer format matches render pass // TODO: Verify buffer format matches render pass
current_mesh_handle = Some(mesh); current_mesh_handle = Some(mesh_handle);
} }
// TODO: validate bind group properties against shader uniform properties at least once // TODO: validate bind group properties against shader uniform properties at least once

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
draw_target::DrawTarget, draw_target::DrawTarget,
mesh::Mesh, mesh::{self, Mesh},
pass::RenderPass, pass::RenderPass,
pipeline::PipelineDescriptor, pipeline::PipelineDescriptor,
render_resource::{resource_name, ResourceInfo}, render_resource::{resource_name, ResourceInfo},
@ -24,19 +24,19 @@ impl DrawTarget for MeshesDrawTarget {
let mut current_mesh_handle = None; let mut current_mesh_handle = None;
let mut current_mesh_index_len = 0; let mut current_mesh_index_len = 0;
let mesh_query = <(Read<Handle<Mesh>>, Read<Renderable>)>::query(); let mesh_query = <(Read<Handle<Mesh>>, Read<Renderable>)>::query();
for (mesh, renderable) in mesh_query.iter(world) { for (mesh_handle, renderable) in mesh_query.iter(world) {
if !renderable.is_visible || renderable.is_instanced { if !renderable.is_visible || renderable.is_instanced {
continue; continue;
} }
let render_context = render_pass.get_render_context(); let render_context = render_pass.get_render_context();
let render_resources = render_context.resources(); let render_resources = render_context.resources();
if current_mesh_handle != Some(*mesh) { if current_mesh_handle != Some(*mesh_handle) {
if let Some(vertex_buffer_resource) = if let Some(vertex_buffer_resource) =
render_resources.get_mesh_vertices_resource(*mesh) render_resources.get_asset_resource(*mesh_handle, mesh::VERTEX_BUFFER_ASSET_INDEX)
{ {
let index_buffer_resource = let index_buffer_resource =
render_resources.get_mesh_indices_resource(*mesh).unwrap(); render_resources.get_asset_resource(*mesh_handle, mesh::INDEX_BUFFER_ASSET_INDEX).unwrap();
render_resources.get_resource_info(index_buffer_resource, &mut |resource_info| { render_resources.get_resource_info(index_buffer_resource, &mut |resource_info| {
match resource_info { match resource_info {
Some(ResourceInfo::Buffer(buffer_info)) => { Some(ResourceInfo::Buffer(buffer_info)) => {
@ -49,7 +49,7 @@ impl DrawTarget for MeshesDrawTarget {
render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0); render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0);
} }
// TODO: Verify buffer format matches render pass // TODO: Verify buffer format matches render pass
current_mesh_handle = Some(*mesh); current_mesh_handle = Some(*mesh_handle);
} }
// TODO: validate bind group properties against shader uniform properties at least once // TODO: validate bind group properties against shader uniform properties at least once

View File

@ -3,6 +3,9 @@ use bevy_asset::{Asset, Handle};
use glam::*; use glam::*;
use legion::prelude::*; use legion::prelude::*;
pub const VERTEX_BUFFER_ASSET_INDEX: usize = 0;
pub const INDEX_BUFFER_ASSET_INDEX: usize = 1;
pub enum MeshType { pub enum MeshType {
Cube, Cube,
Plane { size: f32 }, Plane { size: f32 },

View File

@ -1,6 +1,3 @@
use crate::{mesh::Mesh, texture::Texture};
use bevy_asset::Handle;
use std::collections::HashMap;
use uuid::Uuid; use uuid::Uuid;
// TODO: Rename to RenderResourceId // TODO: Rename to RenderResourceId
@ -12,51 +9,3 @@ impl RenderResource {
RenderResource(Uuid::new_v4()) RenderResource(Uuid::new_v4())
} }
} }
// TODO: consider scoping breaking these mappings up by type: Texture, Sampler, etc
// the overlap could cause accidents.
#[derive(Default, Clone)]
pub struct AssetResources {
texture_to_resource: HashMap<Handle<Texture>, RenderResource>,
texture_to_sampler_resource: HashMap<Handle<Texture>, RenderResource>,
mesh_to_vertices_resource: HashMap<Handle<Mesh>, RenderResource>,
mesh_to_indices_resource: HashMap<Handle<Mesh>, RenderResource>,
}
impl AssetResources {
pub fn set_texture_resource(&mut self, texture: Handle<Texture>, resource: RenderResource) {
self.texture_to_resource.insert(texture, resource);
}
pub fn get_texture_resource(&self, texture: Handle<Texture>) -> Option<RenderResource> {
self.texture_to_resource.get(&texture).cloned()
}
pub fn set_mesh_vertices_resource(&mut self, mesh: Handle<Mesh>, resource: RenderResource) {
self.mesh_to_vertices_resource.insert(mesh, resource);
}
pub fn get_mesh_vertices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource> {
self.mesh_to_vertices_resource.get(&mesh).cloned()
}
pub fn set_mesh_indices_resource(&mut self, mesh: Handle<Mesh>, resource: RenderResource) {
self.mesh_to_indices_resource.insert(mesh, resource);
}
pub fn get_mesh_indices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource> {
self.mesh_to_indices_resource.get(&mesh).cloned()
}
pub fn set_texture_sampler_resource(
&mut self,
texture: Handle<Texture>,
resource: RenderResource,
) {
self.texture_to_sampler_resource.insert(texture, resource);
}
pub fn get_texture_sampler_resource(&self, texture: Handle<Texture>) -> Option<RenderResource> {
self.texture_to_sampler_resource.get(&texture).cloned()
}
}

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
mesh::Mesh, mesh::{self, Mesh},
pipeline::VertexBufferDescriptors, pipeline::VertexBufferDescriptors,
render_resource::{ render_resource::{
AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments, ResourceProvider, AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments, ResourceProvider,
@ -24,10 +24,10 @@ impl MeshResourceProvider {
) { ) {
let render_resources = render_context.resources_mut(); let render_resources = render_context.resources_mut();
let (vertex_buffer, index_buffer) = let (vertex_buffer, index_buffer) =
if let Some(vertex_buffer) = render_resources.get_mesh_vertices_resource(handle) { if let Some(vertex_buffer) = render_resources.get_asset_resource(handle, mesh::VERTEX_BUFFER_ASSET_INDEX) {
( (
vertex_buffer, vertex_buffer,
render_resources.get_mesh_indices_resource(handle), render_resources.get_asset_resource(handle, mesh::INDEX_BUFFER_ASSET_INDEX),
) )
} else { } else {
let mesh_asset = mesh_storage.get(&handle).unwrap(); let mesh_asset = mesh_storage.get(&handle).unwrap();
@ -46,9 +46,8 @@ impl MeshResourceProvider {
mesh_asset.indices.as_bytes(), mesh_asset.indices.as_bytes(),
); );
let asset_resources = render_resources.asset_resources_mut(); render_resources.set_asset_resource(handle, vertex_buffer, mesh::VERTEX_BUFFER_ASSET_INDEX);
asset_resources.set_mesh_vertices_resource(handle, vertex_buffer); render_resources.set_asset_resource(handle, index_buffer, mesh::INDEX_BUFFER_ASSET_INDEX);
asset_resources.set_mesh_indices_resource(handle, index_buffer);
(vertex_buffer, Some(index_buffer)) (vertex_buffer, Some(index_buffer))
}; };

View File

@ -6,7 +6,7 @@ use crate::{
}, },
renderer_2::{RenderContext, RenderResourceContext}, renderer_2::{RenderContext, RenderResourceContext},
shader::{AsUniforms, FieldBindType}, shader::{AsUniforms, FieldBindType},
texture::{SamplerDescriptor, Texture, TextureDescriptor}, texture::{SamplerDescriptor, Texture, TextureDescriptor, self},
Renderable, Renderable,
}; };
use bevy_asset::{AssetStorage, Handle}; use bevy_asset::{AssetStorage, Handle};
@ -379,13 +379,13 @@ where
.unwrap(); .unwrap();
let (texture_resource, sampler_resource) = match render_context let (texture_resource, sampler_resource) = match render_context
.resources() .resources()
.get_texture_resource(texture_handle) .get_asset_resource(texture_handle, texture::TEXTURE_ASSET_INDEX)
{ {
Some(texture_resource) => ( Some(texture_resource) => (
texture_resource, texture_resource,
render_context render_context
.resources() .resources()
.get_texture_sampler_resource(texture_handle) .get_asset_resource(texture_handle, texture::SAMPLER_ASSET_INDEX)
.unwrap(), .unwrap(),
), ),
None => { None => {
@ -401,10 +401,9 @@ where
let sampler_resource = let sampler_resource =
render_resources.create_sampler(&sampler_descriptor); render_resources.create_sampler(&sampler_descriptor);
let asset_resources = render_resources.asset_resources_mut(); render_resources.set_asset_resource(texture_handle, texture_resource, 0);
asset_resources.set_texture_resource(texture_handle, texture_resource); render_resources
asset_resources .set_asset_resource(texture_handle, sampler_resource, 1);
.set_texture_sampler_resource(texture_handle, sampler_resource);
(texture_resource, sampler_resource) (texture_resource, sampler_resource)
} }
}; };

View File

@ -1,10 +1,9 @@
use crate::{ use crate::{
mesh::Mesh, render_resource::{BufferInfo, RenderResource, ResourceInfo},
render_resource::{AssetResources, BufferInfo, RenderResource, ResourceInfo},
shader::Shader, shader::Shader,
texture::{SamplerDescriptor, Texture, TextureDescriptor}, texture::{SamplerDescriptor, TextureDescriptor},
}; };
use bevy_asset::{AssetStorage, Handle}; use bevy_asset::{AssetStorage, Handle, HandleUntyped};
use bevy_window::{Window, WindowId}; use bevy_window::{Window, WindowId};
use std::any::Any; use std::any::Any;
@ -55,11 +54,39 @@ pub trait RenderResourceContext: Any {
fn remove_buffer(&mut self, resource: RenderResource); fn remove_buffer(&mut self, resource: RenderResource);
fn remove_texture(&mut self, resource: RenderResource); fn remove_texture(&mut self, resource: RenderResource);
fn remove_sampler(&mut self, resource: RenderResource); fn remove_sampler(&mut self, resource: RenderResource);
fn get_resource_info(&self, resource: RenderResource, handle_info: &mut dyn FnMut(Option<&ResourceInfo>)); fn get_resource_info(
fn asset_resources(&self) -> &AssetResources; &self,
fn asset_resources_mut(&mut self) -> &mut AssetResources; resource: RenderResource,
fn get_texture_resource(&self, texture: Handle<Texture>) -> Option<RenderResource>; handle_info: &mut dyn FnMut(Option<&ResourceInfo>),
fn get_texture_sampler_resource(&self, texture: Handle<Texture>) -> Option<RenderResource>; );
fn get_mesh_vertices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource>; fn set_asset_resource_untyped(
fn get_mesh_indices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource>; &mut self,
handle: HandleUntyped,
render_resource: RenderResource,
index: usize,
);
fn get_asset_resource_untyped(
&self,
handle: HandleUntyped,
index: usize,
) -> Option<RenderResource>;
}
impl dyn RenderResourceContext {
pub fn set_asset_resource<T>(
&mut self,
handle: Handle<T>,
render_resource: RenderResource,
index: usize,
) where
T: 'static,
{
self.set_asset_resource_untyped(handle.into(), render_resource, index);
}
pub fn get_asset_resource<T>(&self, handle: Handle<T>, index: usize) -> Option<RenderResource>
where
T: 'static,
{
self.get_asset_resource_untyped(handle.into(), index)
}
} }

View File

@ -2,6 +2,8 @@ use crate::shader::ShaderDefSuffixProvider;
use bevy_asset::{Asset, Handle}; use bevy_asset::{Asset, Handle};
use std::fs::File; use std::fs::File;
pub const TEXTURE_ASSET_INDEX: usize = 0;
pub const SAMPLER_ASSET_INDEX: usize = 1;
pub enum TextureType { pub enum TextureType {
Data(Vec<u8>, usize, usize), Data(Vec<u8>, usize, usize),
Png(String), // TODO: please rethink this Png(String), // TODO: please rethink this

View File

@ -1,17 +1,14 @@
use crate::WgpuResources; use crate::WgpuResources;
use bevy_asset::{AssetStorage, Handle}; use bevy_asset::{AssetStorage, Handle, HandleUntyped};
use bevy_render::{ use bevy_render::{
mesh::Mesh, render_resource::{BufferInfo, RenderResource, ResourceInfo},
render_resource::{
AssetResources, BufferInfo, RenderResource, ResourceInfo,
},
renderer_2::RenderResourceContext, renderer_2::RenderResourceContext,
shader::Shader, shader::Shader,
texture::{SamplerDescriptor, Texture, TextureDescriptor}, texture::{SamplerDescriptor, TextureDescriptor},
}; };
use bevy_window::{Window, WindowId};
use std::sync::Arc; use std::sync::Arc;
use bevy_window::{WindowId, Window};
#[derive(Clone)] #[derive(Clone)]
pub struct WgpuRenderResourceContext { pub struct WgpuRenderResourceContext {
@ -19,7 +16,6 @@ pub struct WgpuRenderResourceContext {
pub wgpu_resources: WgpuResources, pub wgpu_resources: WgpuResources,
} }
impl WgpuRenderResourceContext { impl WgpuRenderResourceContext {
pub fn new(device: Arc<wgpu::Device>) -> Self { pub fn new(device: Arc<wgpu::Device>) -> Self {
WgpuRenderResourceContext { WgpuRenderResourceContext {
@ -71,46 +67,27 @@ impl RenderResourceContext for WgpuRenderResourceContext {
self.wgpu_resources.remove_sampler(resource); self.wgpu_resources.remove_sampler(resource);
} }
fn get_texture_resource(&self, texture: Handle<Texture>) -> Option<RenderResource> { fn get_resource_info(
self.wgpu_resources &self,
.asset_resources resource: RenderResource,
.get_texture_resource(texture) handle_info: &mut dyn FnMut(Option<&ResourceInfo>),
} ) {
fn get_texture_sampler_resource(&self, texture: Handle<Texture>) -> Option<RenderResource> {
self.wgpu_resources
.asset_resources
.get_texture_sampler_resource(texture)
}
fn get_mesh_vertices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource> {
self.wgpu_resources
.asset_resources
.get_mesh_vertices_resource(mesh)
}
fn get_mesh_indices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource> {
self.wgpu_resources
.asset_resources
.get_mesh_indices_resource(mesh)
}
fn get_resource_info(&self, resource: RenderResource, handle_info: &mut dyn FnMut(Option<&ResourceInfo>)) {
self.wgpu_resources.get_resource_info(resource, handle_info); self.wgpu_resources.get_resource_info(resource, handle_info);
} }
fn asset_resources(&self) -> &AssetResources {
&self.wgpu_resources.asset_resources
}
fn asset_resources_mut(&mut self) -> &mut AssetResources {
&mut self.wgpu_resources.asset_resources
}
fn create_shader_module( fn create_shader_module(
&mut self, &mut self,
shader_handle: Handle<Shader>, shader_handle: Handle<Shader>,
shader_storage: &AssetStorage<Shader>, shader_storage: &AssetStorage<Shader>,
) { ) {
if self.wgpu_resources.shader_modules.read().unwrap().get(&shader_handle).is_some() { if self
.wgpu_resources
.shader_modules
.read()
.unwrap()
.get(&shader_handle)
.is_some()
{
return; return;
} }
@ -119,7 +96,8 @@ impl RenderResourceContext for WgpuRenderResourceContext {
.create_shader_module(&self.device, shader_handle, shader); .create_shader_module(&self.device, shader_handle, shader);
} }
fn create_swap_chain(&mut self, window: &Window) { fn create_swap_chain(&mut self, window: &Window) {
self.wgpu_resources.create_window_swap_chain(&self.device, window) self.wgpu_resources
.create_window_swap_chain(&self.device, window)
} }
fn next_swap_chain_texture(&mut self, window_id: bevy_window::WindowId) { fn next_swap_chain_texture(&mut self, window_id: bevy_window::WindowId) {
self.wgpu_resources.next_swap_chain_texture(window_id); self.wgpu_resources.next_swap_chain_texture(window_id);
@ -127,4 +105,21 @@ impl RenderResourceContext for WgpuRenderResourceContext {
fn drop_swap_chain_texture(&mut self, window_id: WindowId) { fn drop_swap_chain_texture(&mut self, window_id: WindowId) {
self.wgpu_resources.remove_swap_chain_texture(window_id); self.wgpu_resources.remove_swap_chain_texture(window_id);
} }
fn set_asset_resource_untyped(
&mut self,
handle: HandleUntyped,
render_resource: RenderResource,
index: usize,
) {
self.wgpu_resources
.set_asset_resource_untyped(handle, render_resource, index);
}
fn get_asset_resource_untyped(
&self,
handle: HandleUntyped,
index: usize,
) -> Option<RenderResource> {
self.wgpu_resources
.get_asset_resource_untyped(handle, index)
}
} }

View File

@ -1,9 +1,9 @@
use crate::{renderer_2::WgpuRenderResourceContext, wgpu_type_converter::WgpuInto}; use crate::{renderer_2::WgpuRenderResourceContext, wgpu_type_converter::WgpuInto};
use bevy_asset::Handle; use bevy_asset::{HandleUntyped, Handle};
use bevy_render::{ use bevy_render::{
pipeline::{BindGroupDescriptorId, PipelineDescriptor}, pipeline::{BindGroupDescriptorId, PipelineDescriptor},
render_resource::{ render_resource::{
AssetResources, BufferInfo, RenderResource, RenderResourceSetId, ResourceInfo, BufferInfo, RenderResource, RenderResourceSetId, ResourceInfo,
}, },
renderer_2::RenderResourceContext, renderer_2::RenderResourceContext,
shader::Shader, shader::Shader,
@ -74,7 +74,6 @@ pub struct WgpuResourceRefs<'a> {
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct WgpuResources { pub struct WgpuResources {
// TODO: remove this from WgpuResources. it doesn't need to be here // TODO: remove this from WgpuResources. it doesn't need to be here
pub asset_resources: AssetResources,
pub window_surfaces: Arc<RwLock<HashMap<WindowId, wgpu::Surface>>>, pub window_surfaces: Arc<RwLock<HashMap<WindowId, wgpu::Surface>>>,
pub window_swap_chains: Arc<RwLock<HashMap<WindowId, wgpu::SwapChain>>>, pub window_swap_chains: Arc<RwLock<HashMap<WindowId, wgpu::SwapChain>>>,
pub swap_chain_outputs: Arc<RwLock<HashMap<WindowId, wgpu::SwapChainOutput>>>, pub swap_chain_outputs: Arc<RwLock<HashMap<WindowId, wgpu::SwapChainOutput>>>,
@ -86,6 +85,7 @@ pub struct WgpuResources {
pub render_pipelines: Arc<RwLock<HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>>>, pub render_pipelines: Arc<RwLock<HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>>>,
pub bind_groups: Arc<RwLock<HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>>>, pub bind_groups: Arc<RwLock<HashMap<BindGroupDescriptorId, WgpuBindGroupInfo>>>,
pub bind_group_layouts: Arc<RwLock<HashMap<BindGroupDescriptorId, wgpu::BindGroupLayout>>>, pub bind_group_layouts: Arc<RwLock<HashMap<BindGroupDescriptorId, wgpu::BindGroupLayout>>>,
pub asset_resources: Arc<RwLock<HashMap<(HandleUntyped, usize), RenderResource>>>,
} }
impl WgpuResources { impl WgpuResources {
@ -362,12 +362,20 @@ impl WgpuResources {
self.resource_info.write().unwrap().remove(&resource); self.resource_info.write().unwrap().remove(&resource);
} }
pub fn get_render_resources(&self) -> &AssetResources { pub fn set_asset_resource<T>(&mut self, handle: Handle<T>, render_resource: RenderResource, index: usize) where T: 'static {
&self.asset_resources self.asset_resources.write().unwrap().insert((handle.into(), index), render_resource);
} }
pub fn get_render_resources_mut(&mut self) -> &mut AssetResources { pub fn get_asset_resource<T>(&mut self, handle: Handle<T>, index: usize) -> Option<RenderResource> where T: 'static {
&mut self.asset_resources self.asset_resources.write().unwrap().get(&(handle.into(), index)).cloned()
}
pub fn set_asset_resource_untyped(&mut self, handle: HandleUntyped, render_resource: RenderResource, index: usize) {
self.asset_resources.write().unwrap().insert((handle, index), render_resource);
}
pub fn get_asset_resource_untyped(&self, handle: HandleUntyped, index: usize) -> Option<RenderResource> {
self.asset_resources.write().unwrap().get(&(handle, index)).cloned()
} }
pub fn create_bind_group_layout( pub fn create_bind_group_layout(