RenderGraph2: UniformNode

This commit is contained in:
Carter Anderson 2020-04-24 11:08:46 -07:00
parent 209b4b48d9
commit 512bf118bf
7 changed files with 673 additions and 20 deletions

View file

@ -54,7 +54,7 @@ use bevy_window::{WindowCreated, WindowReference, WindowResized};
use pass::PassDescriptor; use pass::PassDescriptor;
use pipeline::pipelines::build_forward_pipeline; use pipeline::pipelines::build_forward_pipeline;
use render_graph_2::{ use render_graph_2::{
nodes::{Camera2dNode, CameraNode, PassNode, WindowSwapChainNode, WindowTextureNode}, nodes::{Camera2dNode, CameraNode, PassNode, WindowSwapChainNode, WindowTextureNode, UniformNode},
RenderGraph2, RenderGraph2,
}; };
use render_resource::resource_providers::mesh_resource_provider_system; use render_resource::resource_providers::mesh_resource_provider_system;
@ -78,7 +78,6 @@ impl RenderPlugin {
render_graph render_graph
.build(&mut pipelines, &mut shaders) .build(&mut pipelines, &mut shaders)
.add_resource_provider(LightResourceProvider::new(10)) .add_resource_provider(LightResourceProvider::new(10))
.add_resource_provider(UniformResourceProvider::<StandardMaterial>::new(true))
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true)); .add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true));
} }
} }
@ -124,6 +123,7 @@ impl AppPlugin for RenderPlugin {
let resources = app.resources_mut(); let resources = app.resources_mut();
render_graph.add_system_node_named("camera", CameraNode::default(), resources); render_graph.add_system_node_named("camera", CameraNode::default(), resources);
render_graph.add_system_node_named("camera2d", Camera2dNode::default(), resources); render_graph.add_system_node_named("camera2d", Camera2dNode::default(), resources);
render_graph.add_system_node_named("standard_material", UniformNode::<StandardMaterial>::new(true), resources);
render_graph.add_node_named( render_graph.add_node_named(
"swapchain", "swapchain",
WindowSwapChainNode::new( WindowSwapChainNode::new(
@ -185,6 +185,7 @@ impl AppPlugin for RenderPlugin {
// TODO: replace these with "autowire" groups // TODO: replace these with "autowire" groups
render_graph.add_node_edge("camera", "main_pass").unwrap(); render_graph.add_node_edge("camera", "main_pass").unwrap();
render_graph.add_node_edge("camera2d", "main_pass").unwrap(); render_graph.add_node_edge("camera2d", "main_pass").unwrap();
render_graph.add_node_edge("standard_material", "main_pass").unwrap();
render_graph render_graph
.add_slot_edge( .add_slot_edge(
"swapchain", "swapchain",

View file

@ -6,7 +6,7 @@ use crate::{
render_resource::{ render_resource::{
BufferInfo, RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo, BufferInfo, RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo,
}, },
renderer_2::RenderContext, renderer_2::{RenderResourceContext, GlobalRenderResourceContext},
shader::{Shader, ShaderSource}, shader::{Shader, ShaderSource},
Renderable, Renderable,
}; };
@ -48,7 +48,7 @@ impl PipelineCompiler {
shader_storage: &AssetStorage<Shader>, shader_storage: &AssetStorage<Shader>,
vertex_buffer_descriptors: &VertexBufferDescriptors, vertex_buffer_descriptors: &VertexBufferDescriptors,
pipeline_descriptor: &mut PipelineDescriptor, pipeline_descriptor: &mut PipelineDescriptor,
render_context: &dyn RenderContext, render_resource_context: &dyn RenderResourceContext,
render_resource_assignments: &RenderResourceAssignments, render_resource_assignments: &RenderResourceAssignments,
) { ) {
let vertex_spirv = shader_storage let vertex_spirv = shader_storage
@ -75,7 +75,7 @@ impl PipelineCompiler {
for bind_group in layout.bind_groups.iter_mut() { for bind_group in layout.bind_groups.iter_mut() {
for binding in bind_group.bindings.iter_mut() { for binding in bind_group.bindings.iter_mut() {
if let Some(render_resource) = render_resource_assignments.get(&binding.name) { if let Some(render_resource) = render_resource_assignments.get(&binding.name) {
render_context.resources().get_resource_info( render_resource_context.get_resource_info(
render_resource, render_resource,
&mut |resource_info| { &mut |resource_info| {
if let Some(ResourceInfo::Buffer(BufferInfo { is_dynamic, .. })) = if let Some(ResourceInfo::Buffer(BufferInfo { is_dynamic, .. })) =
@ -142,7 +142,7 @@ impl PipelineCompiler {
&mut self, &mut self,
vertex_buffer_descriptors: &VertexBufferDescriptors, vertex_buffer_descriptors: &VertexBufferDescriptors,
shader_storage: &mut AssetStorage<Shader>, shader_storage: &mut AssetStorage<Shader>,
render_context: &dyn RenderContext, render_resource_context: &dyn RenderResourceContext,
pipeline_descriptor: &PipelineDescriptor, pipeline_descriptor: &PipelineDescriptor,
render_resource_assignments: &RenderResourceAssignments, render_resource_assignments: &RenderResourceAssignments,
) -> PipelineDescriptor { ) -> PipelineDescriptor {
@ -173,7 +173,7 @@ impl PipelineCompiler {
shader_storage, shader_storage,
vertex_buffer_descriptors, vertex_buffer_descriptors,
&mut compiled_pipeline_descriptor, &mut compiled_pipeline_descriptor,
render_context, render_resource_context,
render_resource_assignments, render_resource_assignments,
); );
@ -187,7 +187,7 @@ impl PipelineCompiler {
&mut self, &mut self,
vertex_buffer_descriptors: &VertexBufferDescriptors, vertex_buffer_descriptors: &VertexBufferDescriptors,
shader_pipeline_assignments: &mut PipelineAssignments, shader_pipeline_assignments: &mut PipelineAssignments,
render_context: &dyn RenderContext, render_resource_context: &dyn RenderResourceContext,
pipeline_storage: &mut AssetStorage<PipelineDescriptor>, pipeline_storage: &mut AssetStorage<PipelineDescriptor>,
shader_storage: &mut AssetStorage<Shader>, shader_storage: &mut AssetStorage<Shader>,
pipelines: &[Handle<PipelineDescriptor>], pipelines: &[Handle<PipelineDescriptor>],
@ -213,7 +213,7 @@ impl PipelineCompiler {
let compiled_pipeline = self.compile_pipeline( let compiled_pipeline = self.compile_pipeline(
vertex_buffer_descriptors, vertex_buffer_descriptors,
shader_storage, shader_storage,
render_context, render_resource_context,
pipeline_descriptor, pipeline_descriptor,
render_resource_assignments, render_resource_assignments,
); );
@ -286,7 +286,6 @@ impl PipelineAssignments {
pub fn update_shader_assignments( pub fn update_shader_assignments(
world: &mut World, world: &mut World,
resources: &Resources, resources: &Resources,
render_context: &dyn RenderContext,
) { ) {
// PERF: this seems like a lot of work for things that don't change that often. // PERF: this seems like a lot of work for things that don't change that often.
// lots of string + hashset allocations. sees uniform_resource_provider for more context // lots of string + hashset allocations. sees uniform_resource_provider for more context
@ -295,6 +294,7 @@ pub fn update_shader_assignments(
let mut pipeline_compiler = resources.get_mut::<PipelineCompiler>().unwrap(); let mut pipeline_compiler = resources.get_mut::<PipelineCompiler>().unwrap();
let mut shader_storage = resources.get_mut::<AssetStorage<Shader>>().unwrap(); let mut shader_storage = resources.get_mut::<AssetStorage<Shader>>().unwrap();
let vertex_buffer_descriptors = resources.get::<VertexBufferDescriptors>().unwrap(); let vertex_buffer_descriptors = resources.get::<VertexBufferDescriptors>().unwrap();
let global_render_resource_context = resources.get::<GlobalRenderResourceContext>().unwrap();
let mut pipeline_descriptor_storage = resources let mut pipeline_descriptor_storage = resources
.get_mut::<AssetStorage<PipelineDescriptor>>() .get_mut::<AssetStorage<PipelineDescriptor>>()
.unwrap(); .unwrap();
@ -312,7 +312,7 @@ pub fn update_shader_assignments(
pipeline_compiler.update_shader_assignments( pipeline_compiler.update_shader_assignments(
&vertex_buffer_descriptors, &vertex_buffer_descriptors,
&mut shader_pipeline_assignments, &mut shader_pipeline_assignments,
render_context, &*global_render_resource_context.context,
&mut pipeline_descriptor_storage, &mut pipeline_descriptor_storage,
&mut shader_storage, &mut shader_storage,
&renderable.pipelines, &renderable.pipelines,

View file

@ -3,9 +3,11 @@ mod camera2d_node;
mod window_texture_node; mod window_texture_node;
mod window_swapchain_node; mod window_swapchain_node;
mod pass_node; mod pass_node;
mod uniform_node;
pub use camera_node::*; pub use camera_node::*;
pub use camera2d_node::*; pub use camera2d_node::*;
pub use window_texture_node::*; pub use window_texture_node::*;
pub use window_swapchain_node::*; pub use window_swapchain_node::*;
pub use pass_node::*; pub use pass_node::*;
pub use uniform_node::*;

View file

@ -0,0 +1,649 @@
use crate::{
pipeline::VertexBufferDescriptors,
render_graph_2::{CommandQueue, Node, ResourceSlots, SystemNode},
render_resource::{
BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
RenderResourceAssignmentsId, ResourceInfo,
},
renderer_2::{GlobalRenderResourceContext, RenderContext, RenderResourceContext},
shader::{AsUniforms, FieldBindType},
texture, Renderable,
};
use bevy_asset::{AssetStorage, Handle};
use legion::prelude::*;
use std::{collections::HashMap, marker::PhantomData};
use texture::{SamplerDescriptor, Texture, TextureDescriptor};
pub const BIND_BUFFER_ALIGNMENT: usize = 256;
#[derive(Debug)]
struct QueuedBufferWrite {
buffer: RenderResource,
offset: usize,
}
#[derive(Debug)]
struct BufferArrayStatus {
new_item_count: usize,
item_size: usize,
aligned_size: usize,
staging_buffer_offset: usize,
buffer: Option<RenderResource>,
queued_buffer_writes: Vec<QueuedBufferWrite>,
current_item_count: usize,
current_item_capacity: usize,
indices: HashMap<RenderResourceAssignmentsId, usize>,
current_index: usize,
}
impl BufferArrayStatus {
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.current_item_capacity {
panic!("no empty slots available in array");
}
let index = self.current_index;
self.indices.insert(id, index);
self.current_index += 1;
index
}
}
}
struct UniformBufferArrays<T>
where
T: AsUniforms,
{
uniform_arrays: Vec<Option<(String, BufferArrayStatus)>>,
_marker: PhantomData<T>,
}
impl<T> UniformBufferArrays<T>
where
T: AsUniforms,
{
fn new() -> Self {
let mut uniform_arrays = Vec::new();
let field_infos = T::get_field_infos();
uniform_arrays.resize_with(field_infos.len(), || None);
UniformBufferArrays {
uniform_arrays,
_marker: PhantomData::default(),
}
}
fn reset_new_item_counts(&mut self) {
for buffer_status in self.uniform_arrays.iter_mut() {
if let Some((_name, buffer_status)) = buffer_status {
buffer_status.new_item_count = 0;
}
}
}
fn increment_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.uniform_arrays[i] {
buffer_array_status.new_item_count += 1;
} else {
self.uniform_arrays[i] = Some((
field_info.uniform_name.to_string(),
BufferArrayStatus {
new_item_count: 1,
queued_buffer_writes: Vec::new(),
aligned_size: Self::get_aligned_dynamic_uniform_size(size),
item_size: size,
staging_buffer_offset: 0,
buffer: None,
current_index: 0,
current_item_count: 0,
current_item_capacity: 0,
indices: HashMap::new(),
},
))
}
}
}
}
fn get_aligned_dynamic_uniform_size(data_size: usize) -> usize {
BIND_BUFFER_ALIGNMENT * ((data_size as f32 / BIND_BUFFER_ALIGNMENT as f32).ceil() as usize)
}
fn setup_buffer_arrays(
&mut self,
render_resource_context: &dyn RenderResourceContext,
dynamic_uniforms: bool,
) {
for buffer_array_status in self.uniform_arrays.iter_mut() {
if let Some((_name, buffer_array_status)) = buffer_array_status {
if dynamic_uniforms {
Self::setup_buffer_array(buffer_array_status, render_resource_context, true);
}
buffer_array_status.queued_buffer_writes =
Vec::with_capacity(buffer_array_status.new_item_count);
}
}
}
fn setup_buffer_array(
buffer_array_status: &mut BufferArrayStatus,
render_resource_context: &dyn RenderResourceContext,
align: bool,
) {
let new_capacity = if let Some(buffer) = buffer_array_status.buffer {
let mut new_capacity = None;
render_resource_context.get_resource_info(buffer, &mut |resource_info| {
new_capacity = if let Some(ResourceInfo::Buffer(BufferInfo {
array_info: Some(array_info),
..
})) = resource_info
{
if array_info.item_capacity < buffer_array_status.new_item_count {
// over capacity. lets resize
Some(
buffer_array_status.new_item_count
+ buffer_array_status.new_item_count / 2,
)
} else {
// under capacity. no change needed
None
}
} else {
// incorrect resource type. overwrite with new buffer
Some(buffer_array_status.new_item_count)
};
});
new_capacity
} else {
// buffer does not exist. create it now.
Some(buffer_array_status.new_item_count)
};
if let Some(new_capacity) = new_capacity {
let mut item_size = buffer_array_status.item_size;
if align {
item_size = Self::get_aligned_dynamic_uniform_size(item_size);
}
let total_size = item_size * new_capacity;
let buffer = render_resource_context.create_buffer(BufferInfo {
array_info: Some(BufferArrayInfo {
item_capacity: new_capacity,
item_size,
..Default::default()
}),
size: total_size,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
is_dynamic: true,
});
buffer_array_status.current_item_capacity = new_capacity;
log::trace!(
"creating buffer for uniform {}. size: {} item_capacity: {} item_size: {}",
std::any::type_name::<T>(),
total_size,
new_capacity,
item_size
);
buffer_array_status.buffer = Some(buffer);
}
}
fn update_staging_buffer_offsets(&mut self) -> usize {
let mut size = 0;
for dynamic_buffer_array_status in self.uniform_arrays.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
}
fn setup_uniform_buffer_resources(
&mut self,
uniforms: &T,
dynamic_uniforms: bool,
render_resources: &dyn RenderResourceContext,
render_resource_assignments: &mut RenderResourceAssignments,
staging_buffer: &mut [u8],
) {
for (i, field_info) in T::get_field_infos().iter().enumerate() {
let bind_type = uniforms.get_field_bind_type(&field_info.name);
match bind_type {
Some(FieldBindType::Uniform { size }) => {
let (_name, uniform_buffer_status) = self.uniform_arrays[i].as_mut().unwrap();
let (target_buffer, target_offset) = if dynamic_uniforms {
let buffer = uniform_buffer_status.buffer.unwrap();
let mut offset = 0;
render_resources.get_resource_info(buffer, &mut |resource_info| {
if let Some(ResourceInfo::Buffer(BufferInfo {
array_info: Some(ref array_info),
is_dynamic: true,
..
})) = resource_info
{
let index = uniform_buffer_status
.get_or_assign_index(render_resource_assignments.id);
render_resource_assignments.set_indexed(
&field_info.uniform_name,
buffer,
(index * array_info.item_size) as u32,
);
offset = index * uniform_buffer_status.aligned_size;
} else {
panic!("Expected a dynamic uniform buffer");
}
});
(buffer, offset)
} else {
let resource = match render_resource_assignments
.get(field_info.uniform_name)
{
Some(render_resource) => render_resource,
None => {
let resource = render_resources.create_buffer(BufferInfo {
size,
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
..Default::default()
});
render_resource_assignments.set(&field_info.uniform_name, resource);
resource
}
};
(resource, 0)
};
let staging_buffer_start = uniform_buffer_status.staging_buffer_offset
+ (uniform_buffer_status.queued_buffer_writes.len()
* uniform_buffer_status.item_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);
}
staging_buffer
[staging_buffer_start..(staging_buffer_start + uniform_bytes.len())]
.copy_from_slice(uniform_bytes);
} 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);
}
staging_buffer
[staging_buffer_start..(staging_buffer_start + uniform_bytes.len())]
.copy_from_slice(&uniform_bytes);
} else {
panic!(
"failed to get data from uniform: {}",
field_info.uniform_name
);
};
uniform_buffer_status
.queued_buffer_writes
.push(QueuedBufferWrite {
buffer: target_buffer,
offset: target_offset,
});
}
_ => {}
}
}
}
fn copy_staging_buffer_to_final_buffers(
&mut self,
command_queue: &mut CommandQueue,
staging_buffer: RenderResource,
) {
for uniform_buffer_status in self.uniform_arrays.iter_mut() {
if let Some((_name, buffer_array_status)) = uniform_buffer_status {
let start = buffer_array_status.staging_buffer_offset;
for (i, queued_buffer_write) in buffer_array_status
.queued_buffer_writes
.drain(..)
.enumerate()
{
command_queue.copy_buffer_to_buffer(
staging_buffer,
(start + (i * buffer_array_status.item_size)) as u64,
queued_buffer_write.buffer,
queued_buffer_write.offset as u64,
buffer_array_status.item_size as u64,
)
}
}
}
}
}
#[derive(Default)]
pub struct UniformNode<T>
where
T: AsUniforms,
{
command_queue: CommandQueue,
dynamic_uniforms: bool,
_marker: PhantomData<T>,
}
impl<T> UniformNode<T>
where
T: AsUniforms,
{
pub fn new(dynamic_uniforms: bool) -> Self {
UniformNode {
command_queue: CommandQueue::default(),
dynamic_uniforms,
_marker: PhantomData::default(),
}
}
fn initialize_vertex_buffer_descriptor(
vertex_buffer_descriptors: &mut VertexBufferDescriptors,
) {
let vertex_buffer_descriptor = T::get_vertex_buffer_descriptor();
if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor {
if let None = vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name) {
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
}
}
}
fn setup_uniform_texture_resources(
uniforms: &T,
texture_storage: &AssetStorage<Texture>,
render_resource_context: &dyn RenderResourceContext,
render_resource_assignments: &mut RenderResourceAssignments,
) {
for field_info in T::get_field_infos().iter() {
let bind_type = uniforms.get_field_bind_type(&field_info.name);
match bind_type {
Some(FieldBindType::Texture) => {
let texture_handle = uniforms
.get_uniform_texture(&field_info.texture_name)
.unwrap();
let (texture_resource, sampler_resource) = match render_resource_context
.get_asset_resource(texture_handle, texture::TEXTURE_ASSET_INDEX)
{
Some(texture_resource) => (
texture_resource,
render_resource_context
.get_asset_resource(texture_handle, texture::SAMPLER_ASSET_INDEX)
.unwrap(),
),
None => {
let texture = texture_storage.get(&texture_handle).unwrap();
let texture_descriptor: TextureDescriptor = texture.into();
let texture_resource =
render_resource_context.create_texture(&texture_descriptor);
// TODO: queue texture copy
// .create_texture_with_data(&texture_descriptor, &texture.data);
let sampler_descriptor: SamplerDescriptor = texture.into();
let sampler_resource =
render_resource_context.create_sampler(&sampler_descriptor);
render_resource_context.set_asset_resource(
texture_handle,
texture_resource,
0,
);
render_resource_context.set_asset_resource(
texture_handle,
sampler_resource,
1,
);
(texture_resource, sampler_resource)
}
};
render_resource_assignments.set(field_info.texture_name, texture_resource);
render_resource_assignments.set(field_info.sampler_name, sampler_resource);
}
_ => {}
}
}
}
}
impl<T> Node for UniformNode<T>
where
T: AsUniforms,
{
fn update(
&mut self,
_world: &World,
_resources: &Resources,
render_context: &mut dyn RenderContext,
_input: &ResourceSlots,
_output: &mut ResourceSlots,
) {
self.command_queue.execute(render_context);
}
}
impl<T> SystemNode for UniformNode<T>
where
T: AsUniforms,
{
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> {
let mut command_queue = self.command_queue.clone();
let mut uniform_buffer_arrays = UniformBufferArrays::<T>::new();
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
let dynamic_uniforms = self.dynamic_uniforms;
let mut staging_buffer_resource = None;
UniformNode::<T>::initialize_vertex_buffer_descriptor(&mut vertex_buffer_descriptors);
// TODO: maybe run "update" here
SystemBuilder::new("uniform_resource_provider")
.read_resource::<AssetStorage<T>>()
.read_resource::<AssetStorage<Texture>>()
.read_resource::<GlobalRenderResourceContext>()
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
.with_query(<(Read<T>, Read<Renderable>)>::query())
.with_query(<(Read<Handle<T>>, Read<Renderable>)>::query())
.with_query(<(Read<T>, Write<Renderable>)>::query())
.with_query(<(Read<Handle<T>>, Write<Renderable>)>::query())
.build(
move |_,
world,
(assets, textures, global_render_resource_context),
(
read_resource_query,
read_handle_query,
write_resource_query,
write_handle_query,
)| {
let render_resource_context = &*global_render_resource_context.context;
if let Some(staging_buffer_resource) = staging_buffer_resource {
render_resource_context.remove_buffer(staging_buffer_resource);
}
staging_buffer_resource = None;
uniform_buffer_arrays.reset_new_item_counts();
// update uniforms info
for (uniforms, renderable) in read_resource_query.iter(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
panic!("instancing not currently supported");
} else {
uniform_buffer_arrays.increment_uniform_counts(&uniforms);
}
}
// update uniform handles info
for (handle, renderable) in read_handle_query.iter(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
panic!("instancing not currently supported");
} else {
let uniforms = assets
.get(&handle)
.expect("Handle points to a non-existent resource");
// TODO: only increment count if we haven't seen this uniform handle before
uniform_buffer_arrays.increment_uniform_counts(&uniforms);
}
}
uniform_buffer_arrays
.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets();
for (uniforms, mut renderable) in write_resource_query.iter_mut(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
panic!("instancing not currently supported");
} else {
Self::setup_uniform_texture_resources(
&uniforms,
textures,
render_resource_context,
&mut renderable.render_resource_assignments,
)
}
}
for (handle, mut renderable) in write_handle_query.iter_mut(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
panic!("instancing not currently supported");
} else {
let uniforms = assets
.get(&handle)
.expect("Handle points to a non-existent resource");
Self::setup_uniform_texture_resources(
&uniforms,
textures,
render_resource_context,
&mut renderable.render_resource_assignments,
)
}
}
if staging_buffer_size == 0 {
let mut staging_buffer: [u8; 0] = [];
for (uniforms, mut renderable) in write_resource_query.iter_mut(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
panic!("instancing not currently supported");
} else {
uniform_buffer_arrays.setup_uniform_buffer_resources(
&uniforms,
dynamic_uniforms,
render_resource_context,
&mut renderable.render_resource_assignments,
&mut staging_buffer,
);
}
}
for (handle, mut renderable) in write_handle_query.iter_mut(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
panic!("instancing not currently supported");
} else {
let uniforms = assets
.get(&handle)
.expect("Handle points to a non-existent resource");
// TODO: only setup buffer if we haven't seen this handle before
uniform_buffer_arrays.setup_uniform_buffer_resources(
&uniforms,
dynamic_uniforms,
render_resource_context,
&mut renderable.render_resource_assignments,
&mut staging_buffer,
);
}
}
} else {
let staging_buffer = render_resource_context.create_buffer_mapped(
BufferInfo {
buffer_usage: BufferUsage::COPY_SRC,
size: staging_buffer_size,
..Default::default()
},
&mut |mut staging_buffer, _render_resources| {
for (uniforms, mut renderable) in
write_resource_query.iter_mut(world)
{
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
panic!("instancing not currently supported");
} else {
uniform_buffer_arrays.setup_uniform_buffer_resources(
&uniforms,
dynamic_uniforms,
render_resource_context,
&mut renderable.render_resource_assignments,
&mut staging_buffer,
);
}
}
for (handle, mut renderable) in write_handle_query.iter_mut(world) {
if !renderable.is_visible {
return;
}
if renderable.is_instanced {
panic!("instancing not currently supported");
} else {
let uniforms = assets
.get(&handle)
.expect("Handle points to a non-existent resource");
// TODO: only setup buffer if we haven't seen this handle before
uniform_buffer_arrays.setup_uniform_buffer_resources(
&uniforms,
dynamic_uniforms,
render_resource_context,
&mut renderable.render_resource_assignments,
&mut staging_buffer,
);
}
}
},
);
uniform_buffer_arrays.copy_staging_buffer_to_final_buffers(
&mut command_queue,
staging_buffer,
);
staging_buffer_resource = Some(staging_buffer);
}
},
)
}
}

View file

@ -30,6 +30,7 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> RenderResource; fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> RenderResource;
fn create_texture(&self, texture_descriptor: &TextureDescriptor) -> RenderResource; fn create_texture(&self, texture_descriptor: &TextureDescriptor) -> RenderResource;
fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResource; fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResource;
// TODO: remove RenderResourceContext here
fn create_buffer_mapped( fn create_buffer_mapped(
&self, &self,
buffer_info: BufferInfo, buffer_info: BufferInfo,

View file

@ -10,7 +10,7 @@ use bevy_asset::{AssetStorage, Handle};
use bevy_core::bytes::GetBytes; use bevy_core::bytes::GetBytes;
use legion::prelude::*; use legion::prelude::*;
pub trait AsUniforms { pub trait AsUniforms: Send + Sync + 'static {
fn get_field_infos() -> &'static [FieldInfo]; fn get_field_infos() -> &'static [FieldInfo];
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>; fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>;
fn get_uniform_texture(&self, name: &str) -> Option<Handle<Texture>>; fn get_uniform_texture(&self, name: &str) -> Option<Handle<Texture>>;

View file

@ -187,19 +187,20 @@ impl WgpuRenderer {
pub fn run_graph(&mut self, world: &mut World, resources: &mut Resources) { pub fn run_graph(&mut self, world: &mut World, resources: &mut Resources) {
// run systems // run systems
let mut executor = { let mut system_executor = {
let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap(); let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap();
render_graph.take_executor() render_graph.take_executor()
}; };
if let Some(executor) = executor.as_mut() { if let Some(executor) = system_executor.as_mut() {
executor.execute(world, resources); executor.execute(world, resources);
} }
update_shader_assignments(world, resources);
render_resource_sets_system().run(world, resources); render_resource_sets_system().run(world, resources);
let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap(); let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap();
if let Some(executor) = executor.take() { if let Some(executor) = system_executor.take() {
render_graph.set_executor(executor); render_graph.set_executor(executor);
} }
@ -207,12 +208,12 @@ impl WgpuRenderer {
let mut stager = DependentNodeStager::loose_grouping(); let mut stager = DependentNodeStager::loose_grouping();
let stages = stager.get_stages(&render_graph).unwrap(); let stages = stager.get_stages(&render_graph).unwrap();
let mut borrowed = stages.borrow(&mut render_graph); let mut borrowed = stages.borrow(&mut render_graph);
// execute stages // execute stages
let executor = WgpuRenderGraphExecutor { let graph_executor = WgpuRenderGraphExecutor {
max_thread_count: 2, max_thread_count: 2,
}; };
executor.execute( graph_executor.execute(
world, world,
resources, resources,
self.device.clone(), self.device.clone(),
@ -244,7 +245,6 @@ impl WgpuRenderer {
self.update_resource_providers(world, resources, render_resource_context); self.update_resource_providers(world, resources, render_resource_context);
update_shader_assignments(world, resources, &render_context);
self.create_queued_textures(resources, &mut render_context.render_resources); self.create_queued_textures(resources, &mut render_context.render_resources);
}; };