mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
Continue moving uniform buffers to ResourceProviders
This commit is contained in:
parent
45dbe90d85
commit
c4b10ea4f7
7 changed files with 168 additions and 18 deletions
|
@ -141,7 +141,7 @@ fn setup(world: &mut World) {
|
|||
builder = builder.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.0, 1.0, 0.0, 1.0),
|
||||
albedo: math::vec4(rng.gen_range(0.0, 1.0), rng.gen_range(0.0, 1.0), rng.gen_range(0.0, 1.0), 1.0),
|
||||
},
|
||||
shader_uniforms: ShaderUniforms {
|
||||
uniform_selectors: vec![
|
||||
|
|
|
@ -4,13 +4,13 @@ use crate::{
|
|||
core::Time,
|
||||
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
|
||||
render::render_graph_2,
|
||||
render::render_graph_2::{pipelines::*, wgpu_renderer::WgpuRenderer, resource_provider::CameraResourceProvider},
|
||||
render::render_graph_2::{pipelines::*, wgpu_renderer::WgpuRenderer, resource_provider::CameraResourceProvider, UniformResourceProvider, StandardMaterial},
|
||||
render::{passes::*, *},
|
||||
plugin::load_plugin,
|
||||
ui,
|
||||
};
|
||||
|
||||
use bevy_transform::transform_system_bundle;
|
||||
use bevy_transform::{transform_system_bundle, prelude::LocalToWorld};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct AppBuilder {
|
||||
|
@ -175,6 +175,8 @@ impl AppBuilder {
|
|||
self.render_graph_builder = self
|
||||
.render_graph_builder
|
||||
.add_resource_provider(Box::new(CameraResourceProvider))
|
||||
.add_resource_provider(Box::new(UniformResourceProvider::<StandardMaterial>::new()))
|
||||
.add_resource_provider(Box::new(UniformResourceProvider::<LocalToWorld>::new()))
|
||||
.add_forward_pass()
|
||||
.add_forward_pipeline();
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ pub enum UniformPropertyType {
|
|||
}
|
||||
|
||||
impl UniformPropertyType {
|
||||
fn get_size(&self) -> u64 {
|
||||
pub fn get_size(&self) -> u64 {
|
||||
match self {
|
||||
UniformPropertyType::Int => 4,
|
||||
UniformPropertyType::Float => 4,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{legion::prelude::*, render::render_graph_2::{RenderGraph, ResourceInfo, PipelineDescriptor}};
|
||||
use crate::{legion::prelude::*, render::render_graph_2::{RenderGraph, ResourceInfo, PipelineDescriptor, wgpu_renderer::DynamicUniformBufferInfo}};
|
||||
use std::ops::Range;
|
||||
|
||||
pub trait Renderer {
|
||||
|
@ -7,9 +7,14 @@ pub trait Renderer {
|
|||
fn process_render_graph(&mut self, render_graph: &mut RenderGraph, world: &mut World);
|
||||
// TODO: swap out wgpu::BufferUsage for non-wgpu type
|
||||
fn create_buffer_with_data(&mut self, name: &str, data: &[u8], buffer_usage: wgpu::BufferUsage);
|
||||
fn get_dynamic_uniform_buffer_info(&self, name: &str) -> Option<&DynamicUniformBufferInfo>;
|
||||
fn get_dynamic_uniform_buffer_info_mut(&mut self, name: &str) -> Option<&mut DynamicUniformBufferInfo>;
|
||||
fn add_dynamic_uniform_buffer_info(&mut self, name: &str, info: DynamicUniformBufferInfo);
|
||||
fn create_buffer(&mut self, name: &str, size: u64, buffer_usage: wgpu::BufferUsage);
|
||||
fn create_buffer_mapped(&mut self, name: &str, size: usize, buffer_usage: wgpu::BufferUsage, func: &mut dyn FnMut(&mut [u8]));
|
||||
fn remove_buffer(&mut self, name: &str);
|
||||
fn get_resource_info(&self, name: &str) -> Option<&ResourceInfo>;
|
||||
fn copy_buffer_to_buffer(&mut self, source_buffer: &str, source_offset: u64, destination_buffer: &str, destination_offset: u64, size: u64);
|
||||
}
|
||||
|
||||
pub trait RenderPass {
|
||||
|
|
|
@ -7,20 +7,20 @@ use legion::prelude::*;
|
|||
use zerocopy::AsBytes;
|
||||
|
||||
pub trait ResourceProvider {
|
||||
fn initialize(&self, renderer: &mut dyn Renderer, world: &mut World);
|
||||
fn update(&self, renderer: &mut dyn Renderer, world: &mut World);
|
||||
fn resize(&self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32);
|
||||
fn initialize(&mut self, renderer: &mut dyn Renderer, world: &mut World);
|
||||
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World);
|
||||
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32);
|
||||
}
|
||||
|
||||
pub struct CameraResourceProvider;
|
||||
|
||||
impl ResourceProvider for CameraResourceProvider {
|
||||
fn initialize(&self, _renderer: &mut dyn Renderer, _world: &mut World) {
|
||||
fn initialize(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {
|
||||
// TODO: create real buffer here
|
||||
}
|
||||
|
||||
fn update(&self, _renderer: &mut dyn Renderer, _world: &mut World) {}
|
||||
fn resize(&self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {
|
||||
fn update(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {}
|
||||
fn resize(&mut self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {
|
||||
for (mut camera, local_to_world, _) in
|
||||
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
|
||||
{
|
||||
|
|
|
@ -4,9 +4,13 @@ use crate::{
|
|||
prelude::{Entity, World},
|
||||
},
|
||||
math::Vec4,
|
||||
render::render_graph_2::{BindType, UniformPropertyType},
|
||||
render::render_graph_2::{
|
||||
wgpu_renderer::DynamicUniformBufferInfo, BindType, ResourceProvider, UniformPropertyType,
|
||||
},
|
||||
};
|
||||
use legion::storage::Component;
|
||||
use legion::{prelude::*, storage::Component};
|
||||
use std::collections::HashSet;
|
||||
use std::marker::PhantomData;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub type ShaderUniformSelector = fn(Entity, &World) -> Option<RefMap<&dyn AsUniforms>>;
|
||||
|
@ -145,7 +149,7 @@ const STANDARD_MATERIAL_UNIFORM_INFO: &[UniformInfo] = &[UniformInfo {
|
|||
// these are separate from BindType::Uniform{properties} because they need to be const
|
||||
const STANDARD_MATERIAL_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]];
|
||||
|
||||
// const ST
|
||||
// const
|
||||
impl AsUniforms for StandardMaterial {
|
||||
fn get_uniform_infos(&self) -> &[UniformInfo] {
|
||||
STANDARD_MATERIAL_UNIFORM_INFO
|
||||
|
@ -187,7 +191,7 @@ const LOCAL_TO_WORLD_UNIFORM_INFO: &[UniformInfo] = &[UniformInfo {
|
|||
name: "Object",
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
// TODO: fill this in with properties
|
||||
// TODO: maybe fill this in with properties (vec.push cant be const though)
|
||||
properties: Vec::new(),
|
||||
},
|
||||
}];
|
||||
|
@ -230,3 +234,107 @@ impl AsUniforms for bevy_transform::prelude::LocalToWorld {
|
|||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
pub struct UniformResourceProvider<T>
|
||||
where
|
||||
T: AsUniforms + Send + Sync,
|
||||
{
|
||||
_marker: PhantomData<T>,
|
||||
uniform_buffer_info_names: HashSet<String>,
|
||||
// dynamic_uniform_buffer_infos: HashMap<String, DynamicUniformBufferInfo>,
|
||||
}
|
||||
|
||||
impl<T> UniformResourceProvider<T>
|
||||
where
|
||||
T: AsUniforms + Send + Sync,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
UniformResourceProvider {
|
||||
// dynamic_uniform_buffer_infos: HashMap::new(),
|
||||
uniform_buffer_info_names: HashSet::new(),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ResourceProvider for UniformResourceProvider<T>
|
||||
where
|
||||
T: AsUniforms + Send + Sync + 'static,
|
||||
{
|
||||
fn initialize(&mut self, renderer: &mut dyn super::Renderer, world: &mut World) {
|
||||
}
|
||||
|
||||
fn update(&mut self, renderer: &mut dyn super::Renderer, world: &mut World) {
|
||||
let query = <Read<T>>::query();
|
||||
// retrieve all uniforms buffers that aren't aleady set. these are "dynamic" uniforms, which are set by the user in ShaderUniforms
|
||||
// TODO: this breaks down in multiple ways:
|
||||
// (1) resource_info will be set after the first run so this won't update.
|
||||
// (2) if we create new buffers, the old bind groups will be invalid
|
||||
for uniforms in query.iter(world) {
|
||||
let uniform_layouts = uniforms.get_uniform_layouts();
|
||||
for (i, uniform_info) in uniforms.get_uniform_infos().iter().enumerate() {
|
||||
if let None = renderer.get_dynamic_uniform_buffer_info(uniform_info.name) {
|
||||
let uniform_layout = uniform_layouts[i];
|
||||
let mut info = DynamicUniformBufferInfo::new();
|
||||
info.size = uniform_layout.iter().map(|u| u.get_size()).fold(0, |total, current| total + current);
|
||||
self.uniform_buffer_info_names.insert(uniform_info.name.to_string());
|
||||
renderer.add_dynamic_uniform_buffer_info(uniform_info.name, info);
|
||||
}
|
||||
|
||||
let mut info = renderer.get_dynamic_uniform_buffer_info_mut(uniform_info.name)
|
||||
.unwrap();
|
||||
info.count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate uniform buffers
|
||||
// for (name, info) in self.dynamic_uniform_buffer_infos.iter_mut() {
|
||||
// if let Some(_) = renderer.get_resource_info(name) {
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// // allocate enough space for twice as many entities as there are currently;
|
||||
// info.capacity = info.count * 2;
|
||||
// let size = wgpu::BIND_BUFFER_ALIGNMENT * info.capacity;
|
||||
// renderer.create_buffer(name, size, wgpu::BufferUsage::COPY_DST | wgpu::BufferUsage::UNIFORM)
|
||||
// }
|
||||
|
||||
// copy entity uniform data to buffers
|
||||
for name in self.uniform_buffer_info_names.iter() {
|
||||
let info = renderer.get_dynamic_uniform_buffer_info_mut(name).unwrap();
|
||||
info.capacity = info.count;
|
||||
let size = wgpu::BIND_BUFFER_ALIGNMENT * info.count;
|
||||
let mut data = vec![Default::default(); size as usize];
|
||||
// renderer
|
||||
// .create_buffer_mapped("tmp_uniform_mapped", size as usize, wgpu::BufferUsage::COPY_SRC, &mut |mapped| {
|
||||
|
||||
let alignment = wgpu::BIND_BUFFER_ALIGNMENT as usize;
|
||||
let mut offset = 0usize;
|
||||
for (i, (entity, uniforms)) in query.iter_entities(world).enumerate() {
|
||||
// TODO: check if index has changed. if it has, then entity should be updated
|
||||
// TODO: only mem-map entities if their data has changed
|
||||
info.offsets.insert(entity, offset as u64);
|
||||
info.indices.insert(i, entity);
|
||||
// TODO: try getting ref first
|
||||
if let Some(uniform_bytes) = uniforms.get_uniform_bytes(name) {
|
||||
data[offset..(offset + uniform_bytes.len())].copy_from_slice(uniform_bytes.as_slice());
|
||||
offset += alignment;
|
||||
}
|
||||
}
|
||||
// });
|
||||
|
||||
// TODO: port me
|
||||
// let uniform_buffer = self.buffers.get(name);
|
||||
renderer.create_buffer_with_data(name, &data, wgpu::BufferUsage::UNIFORM);
|
||||
}
|
||||
}
|
||||
|
||||
fn resize(
|
||||
&mut self,
|
||||
renderer: &mut dyn super::Renderer,
|
||||
world: &mut World,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,18 @@ pub struct DynamicUniformBufferInfo {
|
|||
pub size: u64,
|
||||
}
|
||||
|
||||
impl DynamicUniformBufferInfo {
|
||||
pub fn new() -> Self {
|
||||
DynamicUniformBufferInfo {
|
||||
capacity: 0,
|
||||
count: 0,
|
||||
indices: HashMap::new(),
|
||||
offsets: HashMap::new(),
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WgpuRenderer {
|
||||
pub device: wgpu::Device,
|
||||
pub queue: wgpu::Queue,
|
||||
|
@ -466,7 +478,7 @@ impl Renderer for WgpuRenderer {
|
|||
.device
|
||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||
|
||||
self.setup_dynamic_entity_shader_uniforms(world, render_graph, &mut encoder);
|
||||
// self.setup_dynamic_entity_shader_uniforms(world, render_graph, &mut encoder);
|
||||
|
||||
// setup, pipelines, bind groups, and resources
|
||||
for (pipeline_name, pipeline_descriptor) in render_graph.pipeline_descriptors.iter_mut() {
|
||||
|
@ -558,6 +570,28 @@ impl Renderer for WgpuRenderer {
|
|||
fn remove_buffer(&mut self, name: &str) {
|
||||
self.buffers.remove(name);
|
||||
}
|
||||
|
||||
fn create_buffer_mapped(&mut self, name: &str, size: usize, buffer_usage: wgpu::BufferUsage, setup_data: &mut dyn FnMut(&mut [u8])) {
|
||||
let mut mapped = self.device.create_buffer_mapped(size, buffer_usage);
|
||||
setup_data(&mut mapped.data);
|
||||
mapped.finish();
|
||||
}
|
||||
|
||||
fn copy_buffer_to_buffer(&mut self, source_buffer: &str, source_offset: u64, destination_buffer: &str, destination_offset: u64, size: u64) {
|
||||
let source = self.buffers.get(source_buffer).unwrap();
|
||||
let destination = self.buffers.get(destination_buffer).unwrap();
|
||||
}
|
||||
fn get_dynamic_uniform_buffer_info(&self, name: &str) -> Option<&DynamicUniformBufferInfo> {
|
||||
self.dynamic_uniform_buffer_info.get(name)
|
||||
}
|
||||
|
||||
fn get_dynamic_uniform_buffer_info_mut(&mut self, name: &str) -> Option<&mut DynamicUniformBufferInfo> {
|
||||
self.dynamic_uniform_buffer_info.get_mut(name)
|
||||
}
|
||||
|
||||
fn add_dynamic_uniform_buffer_info(&mut self, name: &str, info: DynamicUniformBufferInfo) {
|
||||
self.dynamic_uniform_buffer_info.insert(name.to_string(), info);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WgpuRenderPass<'a, 'b, 'c, 'd> {
|
||||
|
@ -622,6 +656,7 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||
.offsets
|
||||
.get(entity.unwrap())
|
||||
.unwrap();
|
||||
|
||||
dynamic_uniform_indices.push(*index);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue