Refactor / cleanup buffer metadata. Fix dynamic uniforms

This commit is contained in:
Carter Anderson 2020-03-20 19:32:59 -07:00
parent ae0d5abf45
commit a55053cf14
15 changed files with 372 additions and 467 deletions

View File

@ -49,8 +49,8 @@ impl DrawTarget for AssignedMeshesDrawTarget {
let index_buffer_resource =
render_resources.get_mesh_indices_resource(mesh).unwrap();
match renderer.get_resource_info(index_buffer_resource).unwrap() {
ResourceInfo::Buffer { size, .. } => {
current_mesh_index_len = (size / 2) as u32
ResourceInfo::Buffer(buffer_info) => {
current_mesh_index_len = (buffer_info.size / 2) as u32
}
_ => panic!("expected a buffer type"),
}

View File

@ -41,8 +41,8 @@ impl DrawTarget for MeshesDrawTarget {
let index_buffer_resource =
render_resources.get_mesh_indices_resource(*mesh).unwrap();
match renderer.get_resource_info(index_buffer_resource).unwrap() {
ResourceInfo::Buffer { size, .. } => {
current_mesh_index_len = (size / 2) as u32
ResourceInfo::Buffer(buffer_info) => {
current_mesh_index_len = (buffer_info.size / 2) as u32
}
_ => panic!("expected a buffer type"),
}

View File

@ -1,11 +1,13 @@
use crate::{
asset::{AssetStorage, Handle},
asset::{Asset, Handle},
legion::prelude::*,
math,
prelude::MeshType,
render::{
draw_target::DrawTarget,
mesh::Mesh,
pipeline::PipelineDescriptor,
render_resource::{resource_name, BufferUsage, RenderResource, ResourceInfo},
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResource, ResourceInfo},
renderer::{RenderPass, Renderer},
},
};
@ -17,6 +19,7 @@ pub struct UiDrawTarget {
pub mesh_vertex_buffer: Option<RenderResource>,
pub mesh_index_buffer: Option<RenderResource>,
pub mesh_index_length: usize,
pub mesh: Option<Handle<Mesh>>,
}
impl DrawTarget for UiDrawTarget {
@ -40,10 +43,12 @@ impl DrawTarget for UiDrawTarget {
let index_count = {
let renderer = render_pass.get_renderer();
if let Some(ResourceInfo::InstanceBuffer { count, .. }) =
renderer.get_resource_info(ui_instances_buffer)
if let Some(ResourceInfo::Buffer(BufferInfo {
array_info: Some(array_info),
..
})) = renderer.get_resource_info(ui_instances_buffer)
{
Some(*count)
Some(array_info.item_count)
} else {
None
}
@ -62,7 +67,7 @@ impl DrawTarget for UiDrawTarget {
fn setup(
&mut self,
_world: &World,
resources: &Resources,
_resources: &Resources,
renderer: &mut dyn Renderer,
_pipeline_handle: Handle<PipelineDescriptor>,
) {
@ -71,33 +76,27 @@ impl DrawTarget for UiDrawTarget {
return;
}
let ui_instances_buffer = {
match renderer
.get_render_resources()
.get_named_resource(resource_name::buffer::UI_INSTANCES)
{
Some(buffer) => buffer,
None => return,
}
};
if let ResourceInfo::InstanceBuffer { mesh_id, .. } =
renderer.get_resource_info(ui_instances_buffer).unwrap()
{
let mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
if let Some(mesh_asset) = mesh_storage.get_id(*mesh_id) {
self.mesh_vertex_buffer =
Some(renderer.create_buffer_with_data(
mesh_asset.vertices.as_bytes(),
BufferUsage::VERTEX,
));
self.mesh_index_buffer = Some(
renderer
.create_buffer_with_data(mesh_asset.indices.as_bytes(), BufferUsage::INDEX),
);
self.mesh_index_length = mesh_asset.indices.len();
};
}
let quad = Mesh::load(MeshType::Quad {
north_west: math::vec2(-0.5, 0.5),
north_east: math::vec2(0.5, 0.5),
south_west: math::vec2(-0.5, -0.5),
south_east: math::vec2(0.5, -0.5),
});
self.mesh_vertex_buffer = Some(renderer.create_buffer_with_data(
BufferInfo {
buffer_usage: BufferUsage::VERTEX,
..Default::default()
},
quad.vertices.as_bytes(),
));
self.mesh_index_buffer = Some(renderer.create_buffer_with_data(
BufferInfo {
buffer_usage: BufferUsage::INDEX,
..Default::default()
},
quad.indices.as_bytes(),
));
self.mesh_index_length = quad.indices.len();
}
fn get_name(&self) -> String {
resource_name::draw_target::UI.to_string()

View File

@ -1,16 +1,39 @@
use crate::render::render_resource::BufferUsage;
use super::RenderResourceAssignmentsId;
use std::collections::HashMap;
#[derive(Default)]
pub struct BufferArrayInfo {
pub item_count: u64,
pub item_size: u64,
pub item_capacity: u64,
}
#[derive(Default)]
pub struct BufferDynamicUniformInfo {
pub offsets: HashMap<RenderResourceAssignmentsId, u32>,
}
pub struct BufferInfo {
pub size: u64,
pub buffer_usage: BufferUsage,
pub array_info: Option<BufferArrayInfo>,
pub dynamic_uniform_info: Option<BufferDynamicUniformInfo>,
}
impl Default for BufferInfo {
fn default() -> Self {
BufferInfo {
size: 0,
buffer_usage: BufferUsage::NONE,
array_info: None,
dynamic_uniform_info: None,
}
}
}
pub enum ResourceInfo {
Buffer {
size: u64,
buffer_usage: BufferUsage,
},
InstanceBuffer {
size: usize,
count: usize,
buffer_usage: BufferUsage,
mesh_id: usize,
},
Buffer(BufferInfo),
Texture,
Sampler,
}

View File

@ -1,5 +1,5 @@
use crate::render::{
render_resource::{resource_name, BufferUsage, RenderResource, ResourceProvider},
render_resource::{resource_name, BufferUsage, RenderResource, ResourceProvider, BufferInfo},
renderer::Renderer,
ActiveCamera2d, Camera,
};
@ -20,8 +20,11 @@ impl ResourceProvider for Camera2dResourceProvider {
_resources: &Resources,
) {
let buffer = renderer.create_buffer(
std::mem::size_of::<[[f32; 4]; 4]>() as u64,
BufferUsage::COPY_DST | BufferUsage::UNIFORM,
BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>() as u64,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
}
);
renderer
@ -48,8 +51,11 @@ impl ResourceProvider for Camera2dResourceProvider {
}
self.tmp_buffer = Some(renderer.create_buffer_mapped(
matrix_size,
BufferUsage::COPY_SRC,
BufferInfo {
size: matrix_size as u64,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data| {
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
},

View File

@ -1,5 +1,5 @@
use crate::render::{
render_resource::{resource_name, BufferUsage, RenderResource, ResourceProvider},
render_resource::{resource_name, BufferUsage, RenderResource, ResourceProvider, BufferInfo},
renderer::Renderer,
ActiveCamera, Camera,
};
@ -21,8 +21,11 @@ impl ResourceProvider for CameraResourceProvider {
_resources: &Resources,
) {
let buffer = renderer.create_buffer(
std::mem::size_of::<[[f32; 4]; 4]>() as u64,
BufferUsage::COPY_DST | BufferUsage::UNIFORM,
BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>() as u64,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
}
);
renderer
@ -52,8 +55,11 @@ impl ResourceProvider for CameraResourceProvider {
}
self.tmp_buffer = Some(renderer.create_buffer_mapped(
matrix_size,
BufferUsage::COPY_SRC,
BufferInfo {
size: matrix_size as u64,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data| {
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
},

View File

@ -1,5 +1,5 @@
use crate::render::{
render_resource::{resource_name, BufferUsage, RenderResource, ResourceProvider},
render_resource::{resource_name, BufferUsage, RenderResource, ResourceProvider, BufferInfo},
renderer::Renderer,
Light, LightRaw,
};
@ -45,8 +45,11 @@ impl ResourceProvider for LightResourceProvider {
as u64;
let buffer = renderer.create_buffer(
light_uniform_size,
BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST,
BufferInfo {
size: light_uniform_size,
buffer_usage: BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST,
..Default::default()
}
);
renderer
.get_render_resources_mut()
@ -77,8 +80,11 @@ impl ResourceProvider for LightResourceProvider {
}
self.tmp_light_buffer = Some(renderer.create_buffer_mapped(
total_size,
BufferUsage::COPY_SRC,
BufferInfo {
size: total_size as u64,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data| {
for ((light, local_to_world, translation), slot) in
light_query.iter(world).zip(data.chunks_exact_mut(size))
@ -90,8 +96,11 @@ impl ResourceProvider for LightResourceProvider {
},
));
self.tmp_count_buffer = Some(renderer.create_buffer_mapped(
light_count_size,
BufferUsage::COPY_SRC,
BufferInfo {
size: light_count_size as u64,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data| {
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
},

View File

@ -3,7 +3,7 @@ use crate::{
prelude::Renderable,
render::{
mesh::Mesh,
render_resource::{AssetBatchers, BufferUsage, ResourceProvider},
render_resource::{AssetBatchers, BufferInfo, BufferUsage, ResourceProvider},
renderer::Renderer,
},
};
@ -49,10 +49,20 @@ impl ResourceProvider for MeshResourceProvider {
.get_mesh_vertices_resource(*mesh_handle)
{
let mesh_asset = mesh_storage.get(&mesh_handle).unwrap();
let vertex_buffer = renderer
.create_buffer_with_data(mesh_asset.vertices.as_bytes(), BufferUsage::VERTEX);
let index_buffer = renderer
.create_buffer_with_data(mesh_asset.indices.as_bytes(), BufferUsage::INDEX);
let vertex_buffer = renderer.create_buffer_with_data(
BufferInfo {
buffer_usage: BufferUsage::VERTEX,
..Default::default()
},
mesh_asset.vertices.as_bytes(),
);
let index_buffer = renderer.create_buffer_with_data(
BufferInfo {
buffer_usage: BufferUsage::INDEX,
..Default::default()
},
mesh_asset.indices.as_bytes(),
);
let render_resources = renderer.get_render_resources_mut();
render_resources.set_mesh_vertices_resource(*mesh_handle, vertex_buffer);

View File

@ -1,10 +1,8 @@
use crate::{
asset::{Asset, AssetStorage, Handle},
ecs, math,
ecs,
prelude::Node,
render::{
mesh::{Mesh, MeshType},
render_resource::{resource_name, BufferUsage, RenderResource, ResourceProvider},
render_resource::{resource_name, BufferUsage, RenderResource, ResourceProvider, BufferInfo, BufferArrayInfo},
renderer::Renderer,
},
};
@ -22,14 +20,12 @@ pub struct RectData {
}
pub struct UiResourceProvider {
pub quad: Option<Handle<Mesh>>,
pub instance_buffer: Option<RenderResource>,
}
impl UiResourceProvider {
pub fn new() -> Self {
UiResourceProvider {
quad: None,
instance_buffer: None,
}
}
@ -70,20 +66,26 @@ impl UiResourceProvider {
return;
}
let size = std::mem::size_of::<RectData>();
let size = std::mem::size_of::<RectData>() as u64;
let data_len = data.len() as u64;
let mesh_id = self.quad.as_ref().unwrap().id;
if let Some(old_instance_buffer) = self.instance_buffer {
renderer.remove_buffer(old_instance_buffer);
}
let buffer = renderer.create_instance_buffer_with_data(
mesh_id,
let buffer = renderer.create_buffer_with_data(
BufferInfo {
size,
buffer_usage: BufferUsage::COPY_SRC | BufferUsage::VERTEX,
array_info: Some(BufferArrayInfo {
item_capacity: data_len,
item_count: data_len,
item_size: size,
}),
..Default::default()
},
data.as_bytes(),
size,
data.len(),
BufferUsage::COPY_SRC | BufferUsage::VERTEX,
);
renderer
@ -98,17 +100,8 @@ impl ResourceProvider for UiResourceProvider {
&mut self,
_renderer: &mut dyn Renderer,
_world: &mut World,
resources: &Resources,
_resources: &Resources,
) {
// self.update(renderer, world);
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let quad = Mesh::load(MeshType::Quad {
north_west: math::vec2(-0.5, 0.5),
north_east: math::vec2(0.5, 0.5),
south_west: math::vec2(-0.5, -0.5),
south_east: math::vec2(0.5, -0.5),
});
self.quad = Some(mesh_storage.add(quad));
}
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, _resources: &Resources) {

View File

@ -2,9 +2,13 @@ use crate::{
asset::{AssetStorage, Handle},
render::{
pipeline::BindType,
render_resource::{AssetBatchers, BufferUsage, RenderResource, ResourceProvider, RenderResourceAssignments, EntityRenderResourceAssignments, RenderResourceAssignmentsProvider},
render_resource::{
AssetBatchers, BufferArrayInfo, BufferInfo, BufferUsage,
EntityRenderResourceAssignments, RenderResource, RenderResourceAssignments,
RenderResourceAssignmentsProvider, ResourceInfo, ResourceProvider, BufferDynamicUniformInfo,
},
renderer::Renderer,
shader::{AsUniforms, DynamicUniformBufferInfo, UniformInfoIter},
shader::{AsUniforms, UniformInfoIter},
texture::{SamplerDescriptor, Texture, TextureDescriptor},
Renderable,
},
@ -68,18 +72,25 @@ where
) {
let handle_query = self.handle_query.take().unwrap();
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
let mut entity_render_resource_assignments = resources.get_mut::<EntityRenderResourceAssignments>().unwrap();
let mut render_resource_assignments_provider = resources.get_mut::<RenderResourceAssignmentsProvider>().unwrap();
let mut entity_render_resource_assignments = resources
.get_mut::<EntityRenderResourceAssignments>()
.unwrap();
let mut render_resource_assignments_provider = resources
.get_mut::<RenderResourceAssignmentsProvider>()
.unwrap();
// TODO: only update handle values when Asset value has changed
if let Some(asset_storage) = resources.get::<AssetStorage<T>>() {
for (entity, (handle, renderable)) in handle_query.iter_entities(world) {
if renderable.is_instanced {
asset_batchers.set_entity_handle(entity, *handle);
} else {
let render_resource_assignments = if let Some(assignments) = entity_render_resource_assignments.get_mut(entity) {
let render_resource_assignments = if let Some(assignments) =
entity_render_resource_assignments.get_mut(entity)
{
assignments
} else {
entity_render_resource_assignments.set(entity, render_resource_assignments_provider.next());
entity_render_resource_assignments
.set(entity, render_resource_assignments_provider.next());
entity_render_resource_assignments.get_mut(entity).unwrap()
};
if let Some(uniforms) = asset_storage.get(&handle) {
@ -142,27 +153,28 @@ where
// let size = uniform_info.bind_type.get_uniform_size().unwrap();
// TODO: get actual size here
let size = BIND_BUFFER_ALIGNMENT;
let resource = renderer.create_buffer(
let resource = renderer.create_buffer(BufferInfo {
size,
BufferUsage::COPY_DST | BufferUsage::UNIFORM,
);
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
resources.insert(uniform_info.name.to_string(), resource);
resource
}
};
render_resource_assignments.set(
uniform_info.name,
render_resource,
);
render_resource_assignments.set(uniform_info.name, render_resource);
let (tmp_buffer, tmp_buffer_size) = if let Some(uniform_bytes) =
uniforms.get_uniform_bytes_ref(uniform_info.name)
{
(
renderer.create_buffer_mapped(
uniform_bytes.len(),
BufferUsage::COPY_SRC,
BufferInfo {
size: uniform_bytes.len() as u64,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |mapped| {
mapped.copy_from_slice(uniform_bytes);
},
@ -174,8 +186,11 @@ where
{
(
renderer.create_buffer_mapped(
uniform_bytes.len(),
BufferUsage::COPY_SRC,
BufferInfo {
size: uniform_bytes.len() as u64,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |mapped| {
mapped.copy_from_slice(&uniform_bytes);
},
@ -254,28 +269,38 @@ where
world: &World,
resources: &Resources,
) {
let entity_render_resource_assignments = resources.get::<EntityRenderResourceAssignments>().unwrap();
let entity_render_resource_assignments = resources
.get::<EntityRenderResourceAssignments>()
.unwrap();
// allocate uniform buffers
for (name, (resource, count, _entities)) in self.uniform_buffer_info_resources.iter_mut() {
let count = *count as u64;
if let Some(resource) = resource {
let mut info = renderer
.get_dynamic_uniform_buffer_info_mut(*resource)
.unwrap();
info.count = count;
continue;
if let Some(ResourceInfo::Buffer(BufferInfo {
array_info: Some(array_info),
..
})) = renderer.get_resource_info_mut(*resource)
{
array_info.item_count = count;
continue;
}
}
// allocate enough space for twice as many entities as there are currently;
let capacity = count * 2;
let size = BIND_BUFFER_ALIGNMENT * capacity;
let created_resource =
renderer.create_buffer(size, BufferUsage::COPY_DST | BufferUsage::UNIFORM);
let created_resource = renderer.create_buffer(BufferInfo {
size,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
array_info: Some(BufferArrayInfo {
item_capacity: capacity,
item_count: count,
item_size: BIND_BUFFER_ALIGNMENT,
}),
dynamic_uniform_info: Some(BufferDynamicUniformInfo::default()),
..Default::default()
});
let mut info = DynamicUniformBufferInfo::new();
info.count = count;
info.capacity = capacity;
renderer.add_dynamic_uniform_buffer_info(created_resource, info);
*resource = Some(created_resource);
renderer
.get_render_resources_mut()
@ -283,76 +308,64 @@ where
}
// copy entity uniform data to buffers
// PERF: consider iter_chunks here and calling get_bytes() on each chunk?
for (name, (resource, _count, entities)) in self.uniform_buffer_info_resources.iter() {
// PERF: consider iter_chunks here and calling get_bytes() on each chunk?
for (name, (resource, count, entities)) in self.uniform_buffer_info_resources.iter() {
let resource = resource.unwrap();
let size = {
// TODO: this lookup isn't needed anymore?
let info = renderer.get_dynamic_uniform_buffer_info(resource).unwrap();
BIND_BUFFER_ALIGNMENT * info.count
};
let alignment = BIND_BUFFER_ALIGNMENT as usize;
let mut offset = 0usize;
let info = renderer
.get_dynamic_uniform_buffer_info_mut(resource)
.unwrap();
// TODO: check if index has changed. if it has, then entity should be updated
// TODO: only mem-map entities if their data has changed
// PERF: These hashmap inserts are pretty expensive (10 fps for 10000 entities)
for (entity, (_, renderable)) in self.resource_query.iter_entities(world) {
if renderable.is_instanced || !entities.contains(&entity) {
continue;
}
info.offsets.insert(entity, offset as u32);
offset += alignment;
}
for (entity, (_, renderable)) in self.handle_query.as_ref().unwrap().iter_entities(world) {
if renderable.is_instanced {
continue;
}
info.offsets.insert(entity, offset as u32);
offset += alignment;
}
// TODO: check if index has changed. if it has, then entity should be updated
// TODO: only mem-map entities if their data has changed
let mapped_buffer_resource = renderer.create_buffer_mapped(
size as usize,
BufferUsage::COPY_SRC,
&mut |mapped| {
let alignment = BIND_BUFFER_ALIGNMENT as usize;
let mut offset = 0usize;
for (entity, (uniforms, renderable)) in
self.resource_query.iter_entities(world)
{
if renderable.is_instanced || !entities.contains(&entity) {
continue;
}
if let Some(uniform_bytes) = uniforms.get_uniform_bytes_ref(&name) {
mapped[offset..(offset + uniform_bytes.len())]
.copy_from_slice(uniform_bytes);
offset += alignment;
} else if let Some(uniform_bytes) = uniforms.get_uniform_bytes(&name) {
mapped[offset..(offset + uniform_bytes.len())]
.copy_from_slice(uniform_bytes.as_slice());
offset += alignment;
}
let resource_info = renderer.get_resource_info_mut(resource);
if let Some(ResourceInfo::Buffer(BufferInfo {
dynamic_uniform_info: Some(dynamic_uniform_info),
..
})) = resource_info
{
let size = BIND_BUFFER_ALIGNMENT * *count as u64;
let alignment = BIND_BUFFER_ALIGNMENT as usize;
let mut offset = 0usize;
// TODO: check if index has changed. if it has, then entity should be updated
// TODO: only mem-map entities if their data has changed
// PERF: These hashmap inserts are pretty expensive (10 fps for 10000 entities)
for (entity, (_, renderable)) in self.resource_query.iter_entities(world) {
if renderable.is_instanced || !entities.contains(&entity) {
continue;
}
if let Some(asset_storage) = resources.get::<AssetStorage<T>>() {
for (entity, (handle, renderable)) in
self.handle_query.as_ref().unwrap().iter_entities(world)
if let Some(render_resource) = entity_render_resource_assignments.get(entity) {
dynamic_uniform_info.offsets.insert(render_resource.get_id(), offset as u32);
}
offset += alignment;
}
for (entity, (_, renderable)) in
self.handle_query.as_ref().unwrap().iter_entities(world)
{
if renderable.is_instanced {
continue;
}
if let Some(render_resource) = entity_render_resource_assignments.get(entity) {
dynamic_uniform_info.offsets.insert(render_resource.get_id(), offset as u32);
}
offset += alignment;
}
// TODO: check if index has changed. if it has, then entity should be updated
// TODO: only mem-map entities if their data has changed
let mapped_buffer_resource = renderer.create_buffer_mapped(
BufferInfo {
size,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |mapped| {
let alignment = BIND_BUFFER_ALIGNMENT as usize;
let mut offset = 0usize;
for (entity, (uniforms, renderable)) in
self.resource_query.iter_entities(world)
{
if renderable.is_instanced ||!entities.contains(&entity) {
if renderable.is_instanced || !entities.contains(&entity) {
continue;
}
let uniforms = asset_storage.get(&handle).unwrap();
if let Some(uniform_bytes) = uniforms.get_uniform_bytes_ref(&name) {
mapped[offset..(offset + uniform_bytes.len())]
.copy_from_slice(uniform_bytes);
@ -363,12 +376,35 @@ where
offset += alignment;
}
}
}
},
);
renderer.copy_buffer_to_buffer(mapped_buffer_resource, 0, resource, 0, size);
renderer.remove_buffer(mapped_buffer_resource);
if let Some(asset_storage) = resources.get::<AssetStorage<T>>() {
for (entity, (handle, renderable)) in
self.handle_query.as_ref().unwrap().iter_entities(world)
{
if renderable.is_instanced || !entities.contains(&entity) {
continue;
}
let uniforms = asset_storage.get(&handle).unwrap();
if let Some(uniform_bytes) = uniforms.get_uniform_bytes_ref(&name) {
mapped[offset..(offset + uniform_bytes.len())]
.copy_from_slice(uniform_bytes);
offset += alignment;
} else if let Some(uniform_bytes) =
uniforms.get_uniform_bytes(&name)
{
mapped[offset..(offset + uniform_bytes.len())]
.copy_from_slice(uniform_bytes.as_slice());
offset += alignment;
}
}
}
},
);
renderer.copy_buffer_to_buffer(mapped_buffer_resource, 0, resource, 0, size);
renderer.remove_buffer(mapped_buffer_resource);
}
}
}
@ -405,29 +441,47 @@ where
// reset all uniform buffer info counts
let query = <(Read<T>, Read<Renderable>)>::query();
for (_name, (resource, count, _entities)) in self.uniform_buffer_info_resources.iter_mut() {
renderer
.get_dynamic_uniform_buffer_info_mut(resource.unwrap())
.unwrap()
.count = 0;
if let Some(ResourceInfo::Buffer(BufferInfo {
array_info: Some(array_info),
..
})) = renderer.get_resource_info_mut(resource.unwrap())
{
array_info.item_count = 0;
}
*count = 0;
}
self.update_asset_uniforms(renderer, world, resources);
let mut entity_render_resource_assignments = resources.get_mut::<EntityRenderResourceAssignments>().unwrap();
let mut render_resource_assignments_provider = resources.get_mut::<RenderResourceAssignmentsProvider>().unwrap();
let mut entity_render_resource_assignments = resources
.get_mut::<EntityRenderResourceAssignments>()
.unwrap();
let mut render_resource_assignments_provider = resources
.get_mut::<RenderResourceAssignmentsProvider>()
.unwrap();
for (entity, (uniforms, renderable)) in query.iter_entities(world) {
if renderable.is_instanced {
continue;
}
let render_resource_assignments = if let Some(assignments) = entity_render_resource_assignments.get_mut(entity) {
assignments
} else {
entity_render_resource_assignments.set(entity, render_resource_assignments_provider.next());
entity_render_resource_assignments.get_mut(entity).unwrap()
};
self.setup_entity_uniform_resources(entity, &uniforms, renderer, resources, render_resource_assignments, true, None);
let render_resource_assignments =
if let Some(assignments) = entity_render_resource_assignments.get_mut(entity) {
assignments
} else {
entity_render_resource_assignments
.set(entity, render_resource_assignments_provider.next());
entity_render_resource_assignments.get_mut(entity).unwrap()
};
self.setup_entity_uniform_resources(
entity,
&uniforms,
renderer,
resources,
render_resource_assignments,
true,
None,
);
}
self.setup_dynamic_uniform_buffers(renderer, world, resources);

View File

@ -3,8 +3,7 @@ use crate::{
render::{
pipeline::{PipelineDescriptor, VertexBufferDescriptor},
render_graph::RenderGraph,
render_resource::{BufferUsage, RenderResource, RenderResources, ResourceInfo, RenderResourceAssignments},
shader::DynamicUniformBufferInfo,
render_resource::{RenderResource, RenderResources, ResourceInfo, RenderResourceAssignments, BufferInfo},
texture::{SamplerDescriptor, TextureDescriptor},
},
};
@ -31,7 +30,7 @@ pub trait Renderer {
world: &mut World,
resources: &mut Resources,
);
fn create_buffer_with_data(&mut self, data: &[u8], buffer_usage: BufferUsage)
fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8])
-> RenderResource;
fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource;
fn create_texture(
@ -39,46 +38,17 @@ pub trait Renderer {
texture_descriptor: &TextureDescriptor,
bytes: Option<&[u8]>,
) -> RenderResource;
// TODO: remove this and replace it with ResourceInfo
fn get_dynamic_uniform_buffer_info(
&self,
resource: RenderResource,
) -> Option<&DynamicUniformBufferInfo>;
fn get_dynamic_uniform_buffer_info_mut(
&mut self,
resource: RenderResource,
) -> Option<&mut DynamicUniformBufferInfo>;
fn add_dynamic_uniform_buffer_info(
&mut self,
resource: RenderResource,
info: DynamicUniformBufferInfo,
);
fn create_buffer(&mut self, size: u64, buffer_usage: BufferUsage) -> RenderResource;
fn create_instance_buffer(
&mut self,
mesh_id: usize,
size: usize,
count: usize,
buffer_usage: BufferUsage,
) -> RenderResource;
fn create_instance_buffer_with_data(
&mut self,
mesh_id: usize,
data: &[u8],
size: usize,
count: usize,
buffer_usage: BufferUsage,
) -> RenderResource;
fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource;
fn create_buffer_mapped(
&mut self,
size: usize,
buffer_usage: BufferUsage,
buffer_info: BufferInfo,
func: &mut dyn FnMut(&mut [u8]),
) -> 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 get_resource_info_mut(&mut self, resource: RenderResource) -> Option<&mut ResourceInfo>;
fn copy_buffer_to_buffer(
&mut self,
source_buffer: RenderResource,

View File

@ -1,7 +1,7 @@
use super::{WgpuRenderer, WgpuResources};
use crate::render::{
pipeline::{BindType, PipelineDescriptor},
render_resource::{RenderResource, RenderResourceAssignments},
render_resource::{RenderResource, RenderResourceAssignments, ResourceInfo, BufferInfo},
renderer::{RenderPass, Renderer},
};
use std::ops::Range;
@ -65,23 +65,22 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
continue;
}
// PERF: This hashmap get is pretty expensive (10 fps for 10000 entities)
if let Some(resource) = self
.wgpu_resources
.render_resources
.get_named_resource(&binding.name)
{
// PERF: This hashmap get is pretty expensive (10 fps for 10000 entities)
if let Some(dynamic_uniform_buffer_info) = self
.wgpu_resources
.dynamic_uniform_buffer_info
.get(&resource)
{
// let index = dynamic_uniform_buffer_info
// .offsets
// .get(entity.unwrap())
// .unwrap();
if let Some(ResourceInfo::Buffer(BufferInfo {
dynamic_uniform_info: Some(dynamic_uniform_info),
..
})) = self.wgpu_resources.resource_info.get(&resource) {
let index = dynamic_uniform_info
.offsets
.get(&render_resource_assignments.unwrap().get_id())
.unwrap();
// dynamic_uniform_indices.push(*index);
dynamic_uniform_indices.push(*index);
}
}
}

View File

@ -13,10 +13,11 @@ use crate::{
},
render_graph::RenderGraph,
render_resource::{
resource_name, BufferUsage, RenderResource, RenderResources, ResourceInfo, RenderResourceAssignments,
resource_name, BufferInfo, RenderResource, RenderResourceAssignments,
RenderResources, ResourceInfo,
},
renderer::Renderer,
shader::{DynamicUniformBufferInfo, Shader},
shader::{Shader},
texture::{SamplerDescriptor, TextureDescriptor},
update_shader_assignments,
},
@ -72,10 +73,8 @@ impl WgpuRenderer {
}
pub fn create_render_pipeline(
render_resources: &RenderResources,
dynamic_uniform_buffer_info: &HashMap<RenderResource, DynamicUniformBufferInfo>,
wgpu_resources: &mut WgpuResources,
pipeline_descriptor: &mut PipelineDescriptor,
bind_group_layouts: &mut HashMap<u64, wgpu::BindGroupLayout>,
device: &wgpu::Device,
vertex_shader: &Shader,
fragment_shader: Option<&Shader>,
@ -109,11 +108,14 @@ impl WgpuRenderer {
ref mut dynamic, ..
} = binding.bind_type
{
if let Some(resource) =
render_resources.get_named_resource(&binding.name)
if let Some(resource) = wgpu_resources
.render_resources
.get_named_resource(&binding.name)
{
if dynamic_uniform_buffer_info.contains_key(&resource) {
*dynamic = true;
if let Some(ResourceInfo::Buffer(buffer_info)) =
wgpu_resources.resource_info.get(&resource)
{
*dynamic = buffer_info.dynamic_uniform_info.is_some();
}
}
}
@ -131,7 +133,7 @@ impl WgpuRenderer {
// setup new bind group layouts
for bind_group in layout.bind_groups.iter_mut() {
let bind_group_id = bind_group.get_or_update_hash();
if let None = bind_group_layouts.get(&bind_group_id) {
if let None = wgpu_resources.bind_group_layouts.get(&bind_group_id) {
let bind_group_layout_binding = bind_group
.bindings
.iter()
@ -146,7 +148,9 @@ impl WgpuRenderer {
bindings: bind_group_layout_binding.as_slice(),
});
bind_group_layouts.insert(bind_group_id, bind_group_layout);
wgpu_resources
.bind_group_layouts
.insert(bind_group_id, bind_group_layout);
}
}
@ -156,7 +160,10 @@ impl WgpuRenderer {
.iter()
.map(|bind_group| {
let bind_group_id = bind_group.get_hash().unwrap();
bind_group_layouts.get(&bind_group_id).unwrap()
wgpu_resources
.bind_group_layouts
.get(&bind_group_id)
.unwrap()
})
.collect::<Vec<&wgpu::BindGroupLayout>>();
@ -463,10 +470,8 @@ impl Renderer for WgpuRenderer {
.as_ref()
.map(|handle| &*shader_storage.get(&handle).unwrap());
let render_pipeline = WgpuRenderer::create_render_pipeline(
&self.wgpu_resources.render_resources,
&self.wgpu_resources.dynamic_uniform_buffer_info,
&mut self.wgpu_resources,
pipeline_descriptor,
&mut self.wgpu_resources.bind_group_layouts,
&self.device,
vertex_shader,
fragment_shader,
@ -530,74 +535,34 @@ impl Renderer for WgpuRenderer {
self.queue.submit(&[command_buffer]);
}
fn create_buffer_with_data(
&mut self,
data: &[u8],
buffer_usage: BufferUsage,
) -> RenderResource {
fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource {
self.wgpu_resources
.create_buffer_with_data(&self.device, data, buffer_usage.into())
.create_buffer_with_data(&self.device, buffer_info, data)
}
fn create_buffer(&mut self, size: u64, buffer_usage: BufferUsage) -> RenderResource {
self.wgpu_resources
.create_buffer(&self.device, size, buffer_usage.into())
}
fn create_instance_buffer(
&mut self,
mesh_id: usize,
size: usize,
count: usize,
buffer_usage: BufferUsage,
) -> RenderResource {
self.wgpu_resources.create_instance_buffer(
&self.device,
mesh_id,
size,
count,
buffer_usage.into(),
)
}
fn create_instance_buffer_with_data(
&mut self,
mesh_id: usize,
data: &[u8],
size: usize,
count: usize,
buffer_usage: BufferUsage,
) -> RenderResource {
self.wgpu_resources.create_instance_buffer_with_data(
&self.device,
mesh_id,
data,
size,
count,
buffer_usage.into(),
)
fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource {
self.wgpu_resources.create_buffer(&self.device, buffer_info)
}
fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> {
self.wgpu_resources.resource_info.get(&resource)
}
fn get_resource_info_mut(&mut self, resource: RenderResource) -> Option<&mut ResourceInfo> {
self.wgpu_resources.resource_info.get_mut(&resource)
}
fn remove_buffer(&mut self, resource: RenderResource) {
self.wgpu_resources.remove_buffer(resource);
}
fn create_buffer_mapped(
&mut self,
size: usize,
buffer_usage: BufferUsage,
buffer_info: BufferInfo,
setup_data: &mut dyn FnMut(&mut [u8]),
) -> RenderResource {
self.wgpu_resources.create_buffer_mapped(
&self.device,
size,
buffer_usage.into(),
setup_data,
)
self.wgpu_resources
.create_buffer_mapped(&self.device, buffer_info, setup_data)
}
fn copy_buffer_to_buffer(
@ -618,31 +583,6 @@ impl Renderer for WgpuRenderer {
);
}
fn get_dynamic_uniform_buffer_info(
&self,
resource: RenderResource,
) -> Option<&DynamicUniformBufferInfo> {
self.wgpu_resources
.get_dynamic_uniform_buffer_info(resource)
}
fn get_dynamic_uniform_buffer_info_mut(
&mut self,
resource: RenderResource,
) -> Option<&mut DynamicUniformBufferInfo> {
self.wgpu_resources
.get_dynamic_uniform_buffer_info_mut(resource)
}
fn add_dynamic_uniform_buffer_info(
&mut self,
resource: RenderResource,
info: DynamicUniformBufferInfo,
) {
self.wgpu_resources
.add_dynamic_uniform_buffer_info(resource, info);
}
fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource {
self.wgpu_resources
.create_sampler(&self.device, sampler_descriptor)
@ -691,8 +631,11 @@ impl Renderer for WgpuRenderer {
.wgpu_resources
.get_assignments_bind_group(render_resource_assignments.get_id(), bind_group_id)
{
self.wgpu_resources
.create_assignments_bind_group(&self.device, bind_group, render_resource_assignments);
self.wgpu_resources.create_assignments_bind_group(
&self.device,
bind_group,
render_resource_assignments,
);
}
}
}

View File

@ -2,9 +2,8 @@ use crate::{
render::{
pipeline::{BindGroup, BindType},
render_resource::{
BufferUsage, RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo, RenderResourceAssignmentsId,
RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo, RenderResourceAssignmentsId, BufferInfo,
},
shader::DynamicUniformBufferInfo,
texture::{SamplerDescriptor, TextureDescriptor},
},
};
@ -23,7 +22,6 @@ pub struct WgpuResources {
pub bind_groups: HashMap<u64, BindGroupInfo>,
pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>,
pub assignment_bind_groups: HashMap<(RenderResourceAssignmentsId, u64), BindGroupInfo>,
pub dynamic_uniform_buffer_info: HashMap<RenderResource, DynamicUniformBufferInfo>,
}
impl WgpuResources {
@ -35,7 +33,6 @@ impl WgpuResources {
resource_info: HashMap::new(),
bind_groups: HashMap::new(),
bind_group_layouts: HashMap::new(),
dynamic_uniform_buffer_info: HashMap::new(),
assignment_bind_groups: HashMap::new(),
render_resources: RenderResources::default(),
}
@ -77,15 +74,12 @@ impl WgpuResources {
dynamic: _,
properties: _,
} => {
if let ResourceInfo::Buffer {
size,
buffer_usage: _,
} = resource_info
if let ResourceInfo::Buffer(buffer_info) = resource_info
{
let buffer = self.buffers.get(&resource).unwrap();
wgpu::BindingResource::Buffer {
buffer,
range: 0..*size,
range: 0..buffer_info.size,
}
} else {
panic!("expected a Buffer resource");
@ -150,11 +144,11 @@ impl WgpuResources {
}
}
BindType::Uniform { .. } => {
if let ResourceInfo::Buffer { size, .. } = resource_info {
if let ResourceInfo::Buffer(buffer_info) = resource_info {
let buffer = self.buffers.get(&resource).unwrap();
wgpu::BindingResource::Buffer {
buffer,
range: 0..*size,
range: 0..buffer_info.size,
}
} else {
panic!("expected a Buffer resource");
@ -186,16 +180,15 @@ impl WgpuResources {
pub fn create_buffer(
&mut self,
device: &wgpu::Device,
size: u64,
buffer_usage: BufferUsage,
buffer_info: BufferInfo,
) -> RenderResource {
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
size,
usage: buffer_usage.into(),
size: buffer_info.size,
usage: buffer_info.buffer_usage.into(),
});
let resource = self.render_resources.get_next_resource();
self.add_resource_info(resource, ResourceInfo::Buffer { buffer_usage, size });
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info));
self.buffers.insert(resource, buffer);
resource
@ -204,71 +197,15 @@ impl WgpuResources {
pub fn create_buffer_with_data(
&mut self,
device: &wgpu::Device,
mut buffer_info: BufferInfo,
data: &[u8],
buffer_usage: BufferUsage,
) -> RenderResource {
buffer_info.size = data.len() as u64;
let resource = self.render_resources.get_next_resource();
let buffer = device.create_buffer_with_data(data, buffer_usage.into());
let buffer = device.create_buffer_with_data(data, buffer_info.buffer_usage.into());
self.add_resource_info(
resource,
ResourceInfo::Buffer {
buffer_usage,
size: data.len() as u64,
},
);
self.buffers.insert(resource, buffer);
resource
}
pub fn create_instance_buffer(
&mut self,
device: &wgpu::Device,
mesh_id: usize,
size: usize,
count: usize,
buffer_usage: BufferUsage,
) -> RenderResource {
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
size: (size * count) as u64,
usage: buffer_usage.into(),
});
let resource = self.render_resources.get_next_resource();
self.add_resource_info(
resource,
ResourceInfo::InstanceBuffer {
buffer_usage,
size,
count,
mesh_id,
},
);
self.buffers.insert(resource, buffer);
resource
}
pub fn create_instance_buffer_with_data(
&mut self,
device: &wgpu::Device,
mesh_id: usize,
data: &[u8],
size: usize,
count: usize,
buffer_usage: BufferUsage,
) -> RenderResource {
let buffer = device.create_buffer_with_data(data, buffer_usage.into());
let resource = self.render_resources.get_next_resource();
self.add_resource_info(
resource,
ResourceInfo::InstanceBuffer {
buffer_usage,
size,
count,
mesh_id,
},
ResourceInfo::Buffer(buffer_info),
);
self.buffers.insert(resource, buffer);
@ -287,21 +224,17 @@ impl WgpuResources {
pub fn create_buffer_mapped(
&mut self,
device: &wgpu::Device,
size: usize,
buffer_usage: BufferUsage,
buffer_info: BufferInfo,
setup_data: &mut dyn FnMut(&mut [u8]),
) -> RenderResource {
let mut mapped = device.create_buffer_mapped(size, buffer_usage.into());
let mut mapped = device.create_buffer_mapped(buffer_info.size as usize, buffer_info.buffer_usage.into());
setup_data(&mut mapped.data);
let buffer = mapped.finish();
let resource = self.render_resources.get_next_resource();
self.add_resource_info(
resource,
ResourceInfo::Buffer {
buffer_usage,
size: size as u64,
},
ResourceInfo::Buffer(buffer_info),
);
self.buffers.insert(resource, buffer);
@ -322,28 +255,6 @@ impl WgpuResources {
encoder.copy_buffer_to_buffer(source, source_offset, destination, destination_offset, size);
}
pub fn get_dynamic_uniform_buffer_info(
&self,
resource: RenderResource,
) -> Option<&DynamicUniformBufferInfo> {
self.dynamic_uniform_buffer_info.get(&resource)
}
pub fn get_dynamic_uniform_buffer_info_mut(
&mut self,
resource: RenderResource,
) -> Option<&mut DynamicUniformBufferInfo> {
self.dynamic_uniform_buffer_info.get_mut(&resource)
}
pub fn add_dynamic_uniform_buffer_info(
&mut self,
resource: RenderResource,
info: DynamicUniformBufferInfo,
) {
self.dynamic_uniform_buffer_info.insert(resource, info);
}
pub fn create_sampler(
&mut self,
device: &wgpu::Device,

View File

@ -7,8 +7,6 @@ use crate::{
texture::{Texture, TextureViewDimension},
},
};
use legion::prelude::Entity;
use std::collections::HashMap;
pub trait AsUniforms {
fn get_field_infos(&self) -> &[FieldInfo];
@ -191,20 +189,4 @@ impl GetTexture for ColorSource {
pub struct UniformInfo<'a> {
pub name: &'a str,
pub bind_type: BindType,
}
pub struct DynamicUniformBufferInfo {
pub offsets: HashMap<Entity, u32>,
pub capacity: u64,
pub count: u64,
}
impl DynamicUniformBufferInfo {
pub fn new() -> Self {
DynamicUniformBufferInfo {
capacity: 0,
count: 0,
offsets: HashMap::new(),
}
}
}
}