finish new uniform resource provider staging buffer. dynamic uniforms work again. both dynamic and non-dynamic uniforms perform better than the previous implementation.

This commit is contained in:
Carter Anderson 2020-03-24 19:17:41 -07:00
parent c71b886165
commit 4d17763c85
15 changed files with 620 additions and 1094 deletions

View file

@ -199,8 +199,8 @@ impl AppBuilder {
.add_resource_provider(LightResourceProvider::new(10))
.add_resource_provider(UiResourceProvider::new())
.add_resource_provider(MeshResourceProvider::new())
.add_resource_provider(UniformResourceProviderNew::<StandardMaterial>::new(false))
.add_resource_provider(UniformResourceProviderNew::<LocalToWorld>::new(false))
.add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true))
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true))
.add_forward_pass()
.add_forward_pipeline()
.add_ui_pipeline();

View file

@ -4,21 +4,39 @@ use std::collections::HashMap;
#[derive(Default)]
pub struct BufferArrayInfo {
pub item_count: u64,
pub item_size: u64,
pub item_capacity: u64,
pub item_count: usize,
pub item_size: usize,
pub item_capacity: usize,
pub indices: HashMap<RenderResourceAssignmentsId, usize>,
pub current_index: usize,
}
#[derive(Default)]
pub struct BufferDynamicUniformInfo {
pub offsets: HashMap<RenderResourceAssignmentsId, u32>,
impl BufferArrayInfo {
pub fn get_index(&self, id: RenderResourceAssignmentsId) -> Option<usize> {
self.indices.get(&id).map(|offset| *offset)
}
pub fn get_or_assign_index(&mut self, id: RenderResourceAssignmentsId) -> usize {
if let Some(offset) = self.indices.get(&id) {
*offset
} else {
if self.current_index == self.item_capacity {
panic!("no empty slots available in array");
}
let index = self.current_index;
self.indices.insert(id, index);
self.current_index += 1;
index
}
}
}
pub struct BufferInfo {
pub size: u64,
pub size: usize,
pub buffer_usage: BufferUsage,
pub array_info: Option<BufferArrayInfo>,
pub dynamic_uniform_info: Option<BufferDynamicUniformInfo>,
pub is_dynamic: bool,
}
impl Default for BufferInfo {
@ -27,7 +45,7 @@ impl Default for BufferInfo {
size: 0,
buffer_usage: BufferUsage::NONE,
array_info: None,
dynamic_uniform_info: None,
is_dynamic: false,
}
}
}

View file

@ -20,7 +20,7 @@ impl ResourceProvider for Camera2dResourceProvider {
_resources: &Resources,
) {
let buffer = renderer.create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>() as u64,
size: std::mem::size_of::<[[f32; 4]; 4]>(),
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
@ -50,11 +50,11 @@ impl ResourceProvider for Camera2dResourceProvider {
self.tmp_buffer = Some(renderer.create_buffer_mapped(
BufferInfo {
size: matrix_size as u64,
size: matrix_size,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data| {
&mut |data, _renderer| {
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
},
));

View file

@ -21,7 +21,7 @@ impl ResourceProvider for CameraResourceProvider {
_resources: &Resources,
) {
let buffer = renderer.create_buffer(BufferInfo {
size: std::mem::size_of::<[[f32; 4]; 4]>() as u64,
size: std::mem::size_of::<[[f32; 4]; 4]>(),
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
@ -54,11 +54,11 @@ impl ResourceProvider for CameraResourceProvider {
self.tmp_buffer = Some(renderer.create_buffer_mapped(
BufferInfo {
size: matrix_size as u64,
size: matrix_size,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data| {
&mut |data, _renderer| {
data[0..matrix_size].copy_from_slice(camera_matrix.as_bytes());
},
));

View file

@ -40,9 +40,8 @@ impl ResourceProvider for LightResourceProvider {
_world: &mut World,
_resources: &Resources,
) {
let light_uniform_size = (std::mem::size_of::<LightCount>()
+ self.max_lights * std::mem::size_of::<LightRaw>())
as u64;
let light_uniform_size =
std::mem::size_of::<LightCount>() + self.max_lights * std::mem::size_of::<LightRaw>();
let buffer = renderer.create_buffer(BufferInfo {
size: light_uniform_size,
@ -79,11 +78,11 @@ impl ResourceProvider for LightResourceProvider {
self.tmp_light_buffer = Some(renderer.create_buffer_mapped(
BufferInfo {
size: total_size as u64,
size: total_size,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data| {
&mut |data, _renderer| {
for ((light, local_to_world, translation), slot) in
light_query.iter(world).zip(data.chunks_exact_mut(size))
{
@ -95,11 +94,11 @@ impl ResourceProvider for LightResourceProvider {
));
self.tmp_count_buffer = Some(renderer.create_buffer_mapped(
BufferInfo {
size: light_count_size as u64,
size: light_count_size,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |data| {
&mut |data, _renderer| {
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
},
));

View file

@ -5,7 +5,6 @@ mod light_resource_provider;
mod mesh_resource_provider;
mod ui_resource_provider;
mod uniform_resource_provider;
mod uniform_resource_provider_new;
pub use camera2d_resource_provider::*;
pub use camera_resource_provider::*;
@ -14,4 +13,3 @@ pub use light_resource_provider::*;
pub use mesh_resource_provider::*;
pub use ui_resource_provider::*;
pub use uniform_resource_provider::*;
pub use uniform_resource_provider_new::*;

View file

@ -77,8 +77,8 @@ impl UiResourceProvider {
return;
}
let size = std::mem::size_of::<Rect>() as u64;
let data_len = data.len() as u64;
let size = std::mem::size_of::<Rect>();
let data_len = data.len();
if let Some(old_instance_buffer) = self.instance_buffer {
renderer.remove_buffer(old_instance_buffer);
@ -92,6 +92,7 @@ impl UiResourceProvider {
item_capacity: data_len,
item_count: data_len,
item_size: size,
..Default::default()
}),
..Default::default()
},

View file

@ -1,589 +0,0 @@
use crate::{
asset::{AssetStorage, Handle},
render::{
render_graph::RenderGraph,
render_resource::{
AssetBatchers, BufferArrayInfo, BufferDynamicUniformInfo, BufferInfo, BufferUsage,
RenderResource, RenderResourceAssignments, RenderResourceAssignmentsProvider,
ResourceInfo, ResourceProvider,
},
renderer::Renderer,
shader::{AsUniforms, FieldBindType},
texture::{SamplerDescriptor, Texture, TextureDescriptor},
Renderable,
},
};
use legion::{filter::*, prelude::*};
use std::marker::PhantomData;
pub const BIND_BUFFER_ALIGNMENT: u64 = 256;
#[derive(Debug)]
struct BufferArrayStatus {
new_item_count: usize,
item_size: usize,
staging_buffer_offset: usize,
buffer: Option<RenderResource>,
}
pub struct UniformResourceProviderNew<T>
where
T: AsUniforms + Send + Sync + 'static,
{
_marker: PhantomData<T>,
use_dynamic_uniforms: bool,
is_instanceable: bool,
// PERF: somehow remove this HashSet
dynamic_uniform_buffer_status: Vec<Option<(String, BufferArrayStatus)>>,
instance_buffer_status: Option<BufferArrayStatus>,
query: Option<
Query<
(Read<T>, Write<Renderable>),
EntityFilterTuple<
And<(ComponentFilter<T>, ComponentFilter<Renderable>)>,
And<(Passthrough, Passthrough)>,
And<(Passthrough, Passthrough)>,
>,
>,
>,
query_finish: Option<
Query<
(Read<T>, Write<Renderable>),
EntityFilterTuple<
And<(ComponentFilter<T>, ComponentFilter<Renderable>)>,
And<(Passthrough, Passthrough)>,
And<(Passthrough, Passthrough)>,
>,
>,
>,
handle_query: Option<
Query<
(Read<Handle<T>>, Write<Renderable>),
EntityFilterTuple<
And<(ComponentFilter<Handle<T>>, ComponentFilter<Renderable>)>,
And<(Passthrough, Passthrough)>,
And<(Passthrough, Passthrough)>,
>,
>,
>,
handle_query_finish: Option<
Query<
(Read<Handle<T>>, Write<Renderable>),
EntityFilterTuple<
And<(ComponentFilter<Handle<T>>, ComponentFilter<Renderable>)>,
And<(Passthrough, Passthrough)>,
And<(Passthrough, Passthrough)>,
>,
>,
>,
}
impl<T> UniformResourceProviderNew<T>
where
T: AsUniforms + Send + Sync + 'static,
{
pub fn new(use_dynamic_uniforms: bool) -> Self {
let mut dynamic_uniform_buffer_status = Vec::new();
let field_infos = T::get_field_infos();
dynamic_uniform_buffer_status.resize_with(field_infos.len(), || None);
let is_instanceable = field_infos.iter().find(|f| f.is_instanceable).is_some();
UniformResourceProviderNew {
dynamic_uniform_buffer_status,
use_dynamic_uniforms,
instance_buffer_status: None,
is_instanceable,
query: Some(<(Read<T>, Write<Renderable>)>::query()),
query_finish: Some(<(Read<T>, Write<Renderable>)>::query()),
handle_query: Some(<(Read<Handle<T>>, Write<Renderable>)>::query()),
handle_query_finish: Some(<(Read<Handle<T>>, Write<Renderable>)>::query()),
_marker: PhantomData,
}
}
fn reset_buffer_array_status_counts(&mut self) {
for buffer_status in self.dynamic_uniform_buffer_status.iter_mut() {
if let Some((_name, buffer_status)) = buffer_status {
buffer_status.new_item_count = 0;
}
}
if let Some(ref mut buffer_status) = self.instance_buffer_status {
buffer_status.new_item_count = 0;
}
}
fn update_uniforms_info(&mut self, world: &mut World) {
if !self.use_dynamic_uniforms {
return;
}
let query = self.query.take().unwrap();
for (uniforms, mut renderable) in query.iter_mut(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
if self.is_instanceable {
self.increment_instance_count(|| Self::get_instance_size(&uniforms));
} else {
panic!(
"Cannot instance uniforms of type {}",
std::any::type_name::<T>()
);
}
} else if self.use_dynamic_uniforms {
self.increment_dynamic_uniform_counts(&uniforms);
}
Self::update_shader_defs(
&uniforms,
renderable.render_resource_assignments.as_mut().unwrap(),
);
}
self.query = Some(query);
}
fn update_handles_info(&mut self, world: &mut World, resources: &Resources) {
let handle_query = self.handle_query.take().unwrap();
let assets = resources.get::<AssetStorage<T>>();
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
if let Some(assets) = assets {
for (entity, (handle, mut renderable)) in handle_query.iter_entities_mut(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
if self.is_instanceable {
asset_batchers.set_entity_handle(entity, *handle);
self.increment_instance_count(|| {
let uniforms = assets.get(&handle).unwrap();
Self::get_instance_size(uniforms)
});
} else {
panic!(
"Cannot instance uniforms of type Handle<{}>",
std::any::type_name::<T>()
);
}
} else {
let uniforms = assets
.get(&handle)
.expect("Handle points to a non-existent resource");
Self::update_shader_defs(
uniforms,
renderable.render_resource_assignments.as_mut().unwrap(),
);
if self.use_dynamic_uniforms {
self.increment_dynamic_uniform_counts(&uniforms);
}
}
}
}
self.handle_query = Some(handle_query);
}
fn increment_instance_count(&mut self, f: impl Fn() -> usize) {
if let Some(ref mut buffer_array_status) = self.instance_buffer_status {
buffer_array_status.new_item_count += 1;
} else {
self.instance_buffer_status = Some(BufferArrayStatus {
new_item_count: 1,
item_size: f(),
staging_buffer_offset: 0,
buffer: None,
})
}
}
fn get_instance_size(uniforms: &T) -> usize {
let mut instance_buffer_size = 0;
for field_info in T::get_field_infos().iter() {
if field_info.is_instanceable {
if let Some(FieldBindType::Uniform { size }) =
uniforms.get_field_bind_type(field_info.name)
{
instance_buffer_size += size;
}
}
}
instance_buffer_size
}
fn increment_dynamic_uniform_counts(&mut self, uniforms: &T) {
for (i, field_info) in T::get_field_infos().iter().enumerate() {
if let Some(FieldBindType::Uniform { size }) =
uniforms.get_field_bind_type(&field_info.name)
{
if let Some((ref _name, ref mut buffer_array_status)) =
self.dynamic_uniform_buffer_status[i]
{
buffer_array_status.new_item_count += 1;
} else {
self.dynamic_uniform_buffer_status[i] = Some((
field_info.uniform_name.to_string(),
BufferArrayStatus {
new_item_count: 1,
item_size: size,
staging_buffer_offset: 0,
buffer: None,
},
))
}
}
}
}
fn update_shader_defs(
uniforms: &T,
render_resource_assignments: &mut RenderResourceAssignments,
) {
if let Some(shader_defs) = uniforms.get_shader_defs() {
for shader_def in shader_defs {
render_resource_assignments.shader_defs.insert(shader_def);
}
}
}
fn setup_uniform_resources(
&mut self,
uniforms: &T,
renderer: &mut dyn Renderer,
resources: &Resources,
render_resource_assignments: &mut RenderResourceAssignments,
) {
for field_info in T::get_field_infos() {
let bind_type = uniforms.get_field_bind_type(&field_info.name);
match bind_type {
Some(FieldBindType::Uniform { size }) => {
if self.use_dynamic_uniforms {
} else {
let buffer_resource = match render_resource_assignments
.get(field_info.uniform_name)
{
Some(render_resource) => render_resource,
None => {
let resource = renderer.create_buffer(BufferInfo {
size: size as u64,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
render_resource_assignments.set(&field_info.uniform_name, resource);
resource
}
};
let (tmp_buffer, tmp_buffer_size) = if let Some(uniform_bytes) =
uniforms.get_uniform_bytes_ref(&field_info.uniform_name)
{
if size != uniform_bytes.len() {
panic!("The number of bytes produced for {} do not match the expected count. Actual: {}. Expected: {}.", field_info.uniform_name, uniform_bytes.len(), size);
}
(
renderer.create_buffer_mapped(
BufferInfo {
size: uniform_bytes.len() as u64,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |mapped| {
mapped.copy_from_slice(uniform_bytes);
},
),
uniform_bytes.len(),
)
} else if let Some(uniform_bytes) =
uniforms.get_uniform_bytes(field_info.uniform_name)
{
if size != uniform_bytes.len() {
panic!("The number of bytes produced for {} do not match the expected count. Actual: {}. Expected: {}.", field_info.uniform_name, uniform_bytes.len(), size);
}
(
renderer.create_buffer_mapped(
BufferInfo {
size: uniform_bytes.len() as u64,
buffer_usage: BufferUsage::COPY_SRC,
..Default::default()
},
&mut |mapped| {
mapped.copy_from_slice(&uniform_bytes);
},
),
uniform_bytes.len(),
)
} else {
panic!(
"failed to get data from uniform: {}",
field_info.uniform_name
);
};
renderer.copy_buffer_to_buffer(
tmp_buffer,
0,
buffer_resource,
0,
tmp_buffer_size as u64,
);
renderer.remove_buffer(tmp_buffer);
}
}
Some(FieldBindType::Texture) => {
let texture_handle = uniforms
.get_uniform_texture(&field_info.texture_name)
.unwrap();
let (texture_resource, sampler_resource) = match renderer
.get_render_resources()
.get_texture_resource(texture_handle)
{
Some(texture_resource) => (
texture_resource,
renderer
.get_render_resources()
.get_texture_sampler_resource(texture_handle)
.unwrap(),
),
None => {
let storage = resources.get::<AssetStorage<Texture>>().unwrap();
let texture = storage.get(&texture_handle).unwrap();
let texture_descriptor: TextureDescriptor = texture.into();
let texture_resource =
renderer.create_texture(&texture_descriptor, Some(&texture.data));
let sampler_descriptor: SamplerDescriptor = texture.into();
let sampler_resource = renderer.create_sampler(&sampler_descriptor);
let render_resources = renderer.get_render_resources_mut();
render_resources.set_texture_resource(texture_handle, texture_resource);
render_resources
.set_texture_sampler_resource(texture_handle, sampler_resource);
(texture_resource, sampler_resource)
}
};
render_resource_assignments.set(field_info.texture_name, texture_resource);
render_resource_assignments.set(field_info.sampler_name, sampler_resource);
}
None => {}
}
}
}
fn setup_uniforms_resources(
&mut self,
world: &mut World,
resources: &Resources,
renderer: &mut dyn Renderer,
) {
let query_finish = self.query_finish.take().unwrap();
for (uniforms, mut renderable) in query_finish.iter_mut(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
panic!(
"Cannot instance uniforms of type {0}. Only Handle<{0}> can be instanced.",
std::any::type_name::<T>()
);
} else {
self.setup_uniform_resources(
&uniforms,
renderer,
resources,
renderable.render_resource_assignments.as_mut().unwrap(),
)
}
}
self.query_finish = Some(query_finish);
}
fn setup_handles_resources(
&mut self,
world: &mut World,
resources: &Resources,
renderer: &mut dyn Renderer,
) {
let assets = resources.get::<AssetStorage<T>>();
if let Some(assets) = assets {
let handle_query_finish = self.handle_query_finish.take().unwrap();
for (handle, mut renderable) in handle_query_finish.iter_mut(world) {
if !renderable.is_visible || renderable.is_instanced {
return;
}
let uniforms = assets
.get(&handle)
.expect("Handle points to a non-existent resource");
self.setup_uniform_resources(
&uniforms,
renderer,
resources,
renderable.render_resource_assignments.as_mut().unwrap(),
)
}
self.handle_query_finish = Some(handle_query_finish);
}
}
fn setup_batched_resources(
&mut self,
world: &mut World,
resources: &Resources,
renderer: &mut dyn Renderer,
) {
// update batch resources. this needs to run in "finish_update" because batches aren't finalized across
// all members of the batch until "UniformResourceProvider.update" has run for all members of the batch
if let Some(asset_storage) = resources.get::<AssetStorage<T>>() {
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
let mut render_resource_assignments_provider = resources
.get_mut::<RenderResourceAssignmentsProvider>()
.unwrap();
let handle_type = std::any::TypeId::of::<T>();
for batch in asset_batchers.get_handle_batches_mut::<T>().unwrap() {
let handle: Handle<T> = batch
.handles
.iter()
.find(|h| h.type_id == handle_type)
.map(|h| (*h).into())
.unwrap();
let render_resource_assignments = batch
.render_resource_assignments
.get_or_insert_with(|| render_resource_assignments_provider.next());
if let Some(uniforms) = asset_storage.get(&handle) {
self.setup_uniform_resources(
uniforms,
renderer,
resources,
render_resource_assignments,
);
Self::update_shader_defs(&uniforms, render_resource_assignments);
}
}
}
}
fn setup_buffer_arrays(&mut self, renderer: &mut dyn Renderer) {
for buffer_array_status in self.dynamic_uniform_buffer_status.iter_mut() {
if let Some((name, buffer_array_status)) = buffer_array_status {
println!("dynamic {} {:?}", name, buffer_array_status);
Self::setup_buffer_array(buffer_array_status, renderer);
}
}
if let Some(ref mut buffer_array_status) = self.instance_buffer_status {
println!("instance {}", std::any::type_name::<T>());
Self::setup_buffer_array(buffer_array_status, renderer);
}
}
fn setup_buffer_array(
buffer_array_status: &mut BufferArrayStatus,
renderer: &mut dyn Renderer,
) {
let new_capacity = if let Some(buffer) = buffer_array_status.buffer {
if let Some(ResourceInfo::Buffer(BufferInfo {
array_info: Some(array_info),
..
})) = renderer.get_resource_info_mut(buffer)
{
if array_info.item_capacity < buffer_array_status.new_item_count as u64 {
Some(
buffer_array_status.new_item_count + buffer_array_status.new_item_count / 2,
)
} else {
None
}
} else {
Some(buffer_array_status.new_item_count)
}
} else {
Some(buffer_array_status.new_item_count)
};
if let Some(new_capacity) = new_capacity {
println!("creating buffer {}", new_capacity);
let buffer = renderer.create_buffer(BufferInfo {
array_info: Some(BufferArrayInfo {
item_capacity: new_capacity as u64,
item_count: buffer_array_status.new_item_count as u64,
item_size: buffer_array_status.item_size as u64,
}),
size: (buffer_array_status.item_size * new_capacity) as u64,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
dynamic_uniform_info: Some(BufferDynamicUniformInfo::default()),
});
buffer_array_status.buffer = Some(buffer);
}
}
fn initialize_vertex_buffer_descriptor(&self, render_graph: &mut RenderGraph) {
let vertex_buffer_descriptor = T::get_vertex_buffer_descriptor();
if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor {
if let None = render_graph.get_vertex_buffer_descriptor(&vertex_buffer_descriptor.name)
{
render_graph.set_vertex_buffer_descriptor(vertex_buffer_descriptor.clone());
}
}
}
fn update_staging_buffer_offsets(&mut self) -> usize {
let mut size = 0;
for dynamic_buffer_array_status in self.dynamic_uniform_buffer_status.iter_mut() {
if let Some((_name, ref mut buffer_array_status)) = dynamic_buffer_array_status {
buffer_array_status.staging_buffer_offset = size;
size += buffer_array_status.item_size * buffer_array_status.new_item_count;
}
}
size
}
}
impl<T> ResourceProvider for UniformResourceProviderNew<T>
where
T: AsUniforms + Send + Sync + 'static,
{
fn initialize(
&mut self,
renderer: &mut dyn Renderer,
world: &mut World,
resources: &Resources,
) {
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
self.initialize_vertex_buffer_descriptor(&mut render_graph);
self.update(renderer, world, resources);
}
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) {
self.reset_buffer_array_status_counts();
self.update_uniforms_info(world);
self.update_handles_info(world, resources);
}
fn finish_update(
&mut self,
renderer: &mut dyn Renderer,
world: &mut World,
resources: &Resources,
) {
let staging_buffer_size = self.update_staging_buffer_offsets();
// TODO: when setting batch shader_defs, add INSTANCING
self.setup_buffer_arrays(renderer);
self.setup_uniforms_resources(world, resources, renderer);
self.setup_handles_resources(world, resources, renderer);
self.setup_batched_resources(world, resources, renderer);
}
}

View file

@ -24,7 +24,7 @@ pub trait Renderer {
fn create_buffer_mapped(
&mut self,
buffer_info: BufferInfo,
func: &mut dyn FnMut(&mut [u8]),
func: &mut dyn FnMut(&mut [u8], &mut dyn Renderer),
) -> RenderResource;
fn remove_buffer(&mut self, resource: RenderResource);
fn remove_texture(&mut self, resource: RenderResource);

View file

@ -58,6 +58,7 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
};
// setup dynamic uniform instances
// TODO: these indices could be stored in RenderResourceAssignments so they dont need to be collected on each draw
let mut dynamic_uniform_indices = Vec::new();
for binding in bind_group.bindings.iter() {
if let BindType::Uniform { dynamic, .. } = binding.bind_type {
@ -72,16 +73,17 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
.get_named_resource(&binding.name)
{
if let Some(ResourceInfo::Buffer(BufferInfo {
dynamic_uniform_info: Some(dynamic_uniform_info),
array_info: Some(array_info),
is_dynamic: true,
..
})) = self.wgpu_resources.resource_info.get(&resource)
{
let index = dynamic_uniform_info
.offsets
let index = array_info
.indices
.get(&render_resource_assignments.unwrap().get_id())
.unwrap();
dynamic_uniform_indices.push(*index);
dynamic_uniform_indices.push((*index * array_info.item_size) as u32);
}
}
}

View file

@ -19,10 +19,10 @@ use crate::{
update_shader_assignments,
},
};
use std::{collections::HashMap, ops::Deref};
use std::{cell::RefCell, collections::HashMap, ops::Deref, rc::Rc};
pub struct WgpuRenderer {
pub device: wgpu::Device,
pub device: Rc<RefCell<wgpu::Device>>,
pub queue: wgpu::Queue,
pub surface: Option<wgpu::Surface>,
pub encoder: Option<wgpu::CommandEncoder>,
@ -58,7 +58,7 @@ impl WgpuRenderer {
};
WgpuRenderer {
device,
device: Rc::new(RefCell::new(device)),
queue,
surface: None,
encoder: None,
@ -160,7 +160,7 @@ impl WgpuRenderer {
if let Some(ResourceInfo::Buffer(buffer_info)) =
wgpu_resources.resource_info.get(&resource)
{
*dynamic = buffer_info.dynamic_uniform_info.is_some();
*dynamic = buffer_info.is_dynamic;
}
}
}
@ -370,6 +370,7 @@ impl WgpuRenderer {
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
self.encoder = Some(
self.device
.borrow()
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
);
for resource_provider in render_graph.resource_providers.iter_mut() {
@ -417,12 +418,14 @@ impl Renderer for WgpuRenderer {
};
self.encoder = Some(
self.device
.borrow()
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
);
self.swap_chain_descriptor.width = window_size.width;
self.swap_chain_descriptor.height = window_size.height;
let swap_chain = self
.device
.borrow()
.create_swap_chain(self.surface.as_ref().unwrap(), &self.swap_chain_descriptor);
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues, so lets just store it in World.
@ -449,6 +452,7 @@ impl Renderer for WgpuRenderer {
// exposing the wgpu renderer internals to ResourceProvider traits. if this can be made cleaner that would be pretty cool.
self.encoder = Some(
self.device
.borrow()
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }),
);
@ -492,7 +496,7 @@ impl Renderer for WgpuRenderer {
let render_pipeline = WgpuRenderer::create_render_pipeline(
&mut self.wgpu_resources,
pipeline_descriptor,
&self.device,
&self.device.borrow(),
&render_graph,
vertex_shader,
fragment_shader,
@ -505,7 +509,7 @@ impl Renderer for WgpuRenderer {
let pipeline_layout = pipeline_descriptor.get_layout().unwrap();
for bind_group in pipeline_layout.bind_groups.iter() {
self.wgpu_resources
.setup_bind_group(&self.device, bind_group);
.setup_bind_group(&self.device.borrow(), bind_group);
}
}
@ -560,11 +564,12 @@ impl Renderer for WgpuRenderer {
fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource {
self.wgpu_resources
.create_buffer_with_data(&self.device, buffer_info, data)
.create_buffer_with_data(&self.device.borrow(), buffer_info, data)
}
fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource {
self.wgpu_resources.create_buffer(&self.device, buffer_info)
self.wgpu_resources
.create_buffer(&self.device.borrow(), buffer_info)
}
fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> {
@ -582,10 +587,10 @@ impl Renderer for WgpuRenderer {
fn create_buffer_mapped(
&mut self,
buffer_info: BufferInfo,
setup_data: &mut dyn FnMut(&mut [u8]),
setup_data: &mut dyn FnMut(&mut [u8], &mut dyn Renderer),
) -> RenderResource {
self.wgpu_resources
.create_buffer_mapped(&self.device, buffer_info, setup_data)
let buffer = WgpuResources::begin_create_buffer_mapped(&buffer_info, self, setup_data);
self.wgpu_resources.assign_buffer(buffer, buffer_info)
}
fn copy_buffer_to_buffer(
@ -608,7 +613,7 @@ impl Renderer for WgpuRenderer {
fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource {
self.wgpu_resources
.create_sampler(&self.device, sampler_descriptor)
.create_sampler(&self.device.borrow(), sampler_descriptor)
}
fn create_texture(
@ -617,7 +622,7 @@ impl Renderer for WgpuRenderer {
bytes: Option<&[u8]>,
) -> RenderResource {
self.wgpu_resources.create_texture(
&self.device,
&self.device.borrow(),
self.encoder.as_mut().unwrap(),
texture_descriptor,
bytes,
@ -655,7 +660,7 @@ impl Renderer for WgpuRenderer {
.get_assignments_bind_group(render_resource_assignments.get_id(), bind_group_id)
{
self.wgpu_resources.create_assignments_bind_group(
&self.device,
&self.device.borrow(),
bind_group,
render_resource_assignments,
);

View file

@ -1,9 +1,11 @@
use super::WgpuRenderer;
use crate::render::{
pipeline::{BindGroup, BindType},
render_resource::{
BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceAssignmentsId,
RenderResources, ResourceInfo,
},
renderer::Renderer,
texture::{SamplerDescriptor, TextureDescriptor},
};
use std::collections::HashMap;
@ -77,7 +79,7 @@ impl WgpuResources {
let buffer = self.buffers.get(&resource).unwrap();
wgpu::BindingResource::Buffer {
buffer,
range: 0..buffer_info.size,
range: 0..buffer_info.size as u64,
}
} else {
panic!("expected a Buffer resource");
@ -147,7 +149,7 @@ impl WgpuResources {
let buffer = self.buffers.get(&resource).unwrap();
wgpu::BindingResource::Buffer {
buffer,
range: 0..buffer_info.size,
range: 0..buffer_info.size as u64,
}
} else {
panic!("expected a Buffer resource");
@ -185,7 +187,7 @@ impl WgpuResources {
buffer_info: BufferInfo,
) -> RenderResource {
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
size: buffer_info.size,
size: buffer_info.size as u64,
usage: buffer_info.buffer_usage.into(),
});
@ -202,13 +204,9 @@ impl WgpuResources {
mut buffer_info: BufferInfo,
data: &[u8],
) -> RenderResource {
buffer_info.size = data.len() as u64;
let resource = self.render_resources.get_next_resource();
buffer_info.size = data.len();
let buffer = device.create_buffer_with_data(data, buffer_info.buffer_usage.into());
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info));
self.buffers.insert(resource, buffer);
resource
self.assign_buffer(buffer, buffer_info)
}
pub fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> {
@ -220,24 +218,31 @@ impl WgpuResources {
self.resource_info.remove(&resource);
}
pub fn create_buffer_mapped(
pub fn assign_buffer(
&mut self,
device: &wgpu::Device,
buffer: wgpu::Buffer,
buffer_info: BufferInfo,
setup_data: &mut dyn FnMut(&mut [u8]),
) -> RenderResource {
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_info));
self.buffers.insert(resource, buffer);
resource
}
pub fn begin_create_buffer_mapped(
buffer_info: &BufferInfo,
renderer: &mut WgpuRenderer,
setup_data: &mut dyn FnMut(&mut [u8], &mut dyn Renderer),
) -> wgpu::Buffer {
let device_rc = renderer.device.clone();
let device = device_rc.borrow();
let mut mapped =
device.create_buffer_mapped(buffer_info.size as usize, buffer_info.buffer_usage.into());
setup_data(&mut mapped.data, renderer);
mapped.finish()
}
pub fn copy_buffer_to_buffer(
&mut self,
encoder: &mut wgpu::CommandEncoder,

View file

@ -5,7 +5,7 @@ use crate::{
color::ColorSource,
pipeline::{BindType, VertexBufferDescriptor},
texture::{Texture, TextureViewDimension},
}, prelude::Color,
},
};
pub trait AsUniforms {
@ -79,7 +79,7 @@ where
let bind_type = self.uniforms.get_field_bind_type(field_info.name);
if let Some(bind_type) = bind_type {
Some(match bind_type {
FieldBindType::Uniform { .. }=> UniformInfo {
FieldBindType::Uniform { .. } => UniformInfo {
bind_type: BindType::Uniform {
dynamic: false,
properties: Vec::new(),
@ -147,7 +147,9 @@ where
{
// TODO: this breaks if get_bytes_ref() isn't supported for a datatype
default fn get_field_bind_type(&self) -> Option<FieldBindType> {
Some(FieldBindType::Uniform { size: self.get_bytes_ref().unwrap().len() })
Some(FieldBindType::Uniform {
size: self.get_bytes_ref().unwrap().len(),
})
}
}

View file

@ -5,7 +5,7 @@ use crate::{
pipeline::{
InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
},
shader::{AsUniforms, FieldBindType, FieldInfo, AsFieldBindType},
shader::{AsFieldBindType, AsUniforms, FieldBindType, FieldInfo},
texture::Texture,
},
};