mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
AssetRenderResourceNodes now consume asset change events. Remove EntitiesWaitingForAssets in favor of DrawState.
This commit is contained in:
parent
2e48269923
commit
fc4160ea41
14 changed files with 202 additions and 167 deletions
|
@ -71,6 +71,7 @@ impl<T> Assets<T> {
|
|||
}
|
||||
|
||||
pub fn get_mut(&mut self, handle: &Handle<T>) -> Option<&mut T> {
|
||||
self.events.send(AssetEvent::Modified { handle: *handle });
|
||||
self.assets.get_mut(&handle)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use bevy_render::{
|
|||
base_render_graph,
|
||||
pipeline::PipelineDescriptor,
|
||||
render_graph::{
|
||||
nodes::{AssetUniformNode, UniformNode},
|
||||
nodes::{AssetRenderResourcesNode, RenderResourcesNode},
|
||||
RenderGraph,
|
||||
},
|
||||
shader::Shader,
|
||||
|
@ -28,10 +28,10 @@ pub trait ForwardPbrRenderGraphBuilder {
|
|||
|
||||
impl ForwardPbrRenderGraphBuilder for RenderGraph {
|
||||
fn add_pbr_graph(&mut self, resources: &Resources) -> &mut Self {
|
||||
self.add_system_node(node::TRANSFORM, UniformNode::<Transform>::new(true));
|
||||
self.add_system_node(node::TRANSFORM, RenderResourcesNode::<Transform>::new(true));
|
||||
self.add_system_node(
|
||||
node::STANDARD_MATERIAL,
|
||||
AssetUniformNode::<StandardMaterial>::new(true),
|
||||
AssetRenderResourcesNode::<StandardMaterial>::new(true),
|
||||
);
|
||||
self.add_system_node(node::LIGHTS, LightsNode::new(10));
|
||||
let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap();
|
||||
|
|
|
@ -39,7 +39,6 @@ use draw::{clear_draw_system, Draw, RenderPipelines};
|
|||
use legion::prelude::IntoSystem;
|
||||
use mesh::mesh_resource_provider_system;
|
||||
use render_graph::RenderGraph;
|
||||
use render_resource::EntitiesWaitingForAssets;
|
||||
use std::ops::Range;
|
||||
use texture::{PngTextureLoader, TextureResourceSystemState};
|
||||
|
||||
|
@ -83,7 +82,6 @@ impl AppPlugin for RenderPlugin {
|
|||
.init_resource::<PipelineCompiler>()
|
||||
.init_resource::<RenderResourceAssignments>()
|
||||
.init_resource::<VertexBufferDescriptors>()
|
||||
.init_resource::<EntitiesWaitingForAssets>()
|
||||
.init_resource::<TextureResourceSystemState>()
|
||||
.add_system_to_stage(bevy_app::stage::PRE_UPDATE, clear_draw_system.system())
|
||||
.init_system_to_stage(
|
||||
|
@ -94,10 +92,6 @@ impl AppPlugin for RenderPlugin {
|
|||
bevy_app::stage::POST_UPDATE,
|
||||
camera::camera_system::<PerspectiveProjection>,
|
||||
)
|
||||
.add_system_to_stage(
|
||||
bevy_app::stage::PRE_UPDATE,
|
||||
EntitiesWaitingForAssets::clear_system.system(),
|
||||
)
|
||||
.init_system_to_stage(stage::RENDER_RESOURCE, mesh_resource_provider_system)
|
||||
.add_system_to_stage(
|
||||
stage::RENDER_RESOURCE,
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
mod camera_node;
|
||||
mod pass_node;
|
||||
mod texture_copy_node;
|
||||
mod uniform_node;
|
||||
mod render_resources_node;
|
||||
mod window_swapchain_node;
|
||||
mod window_texture_node;
|
||||
|
||||
pub use camera_node::*;
|
||||
pub use pass_node::*;
|
||||
pub use texture_copy_node::*;
|
||||
pub use uniform_node::*;
|
||||
pub use render_resources_node::*;
|
||||
pub use window_swapchain_node::*;
|
||||
pub use window_texture_node::*;
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
use crate::{
|
||||
draw::{Draw, RenderCommand},
|
||||
pass::{PassDescriptor, TextureAttachment},
|
||||
pipeline::PipelineDescriptor,
|
||||
render_graph::{Node, ResourceSlotInfo, ResourceSlots},
|
||||
render_resource::{EntitiesWaitingForAssets, RenderResourceAssignments, ResourceInfo},
|
||||
render_resource::{
|
||||
RenderResourceAssignments, RenderResourceId, RenderResourceSetId, ResourceInfo,
|
||||
},
|
||||
renderer::RenderContext,
|
||||
};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use legion::prelude::*;
|
||||
|
||||
pub struct MainPassNode {
|
||||
|
@ -63,8 +67,8 @@ impl Node for MainPassNode {
|
|||
input: &ResourceSlots,
|
||||
_output: &mut ResourceSlots,
|
||||
) {
|
||||
let entities_waiting_for_assets = resources.get::<EntitiesWaitingForAssets>().unwrap();
|
||||
let render_resource_assignments = resources.get::<RenderResourceAssignments>().unwrap();
|
||||
let pipelines = resources.get::<Assets<PipelineDescriptor>>().unwrap();
|
||||
|
||||
for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
|
||||
if let Some(input_index) = self.color_attachment_input_indices[i] {
|
||||
|
@ -85,8 +89,9 @@ impl Node for MainPassNode {
|
|||
&self.descriptor,
|
||||
&render_resource_assignments,
|
||||
&mut |render_pass| {
|
||||
for (entity, draw) in <Read<Draw>>::query().iter_entities(&world) {
|
||||
if !draw.is_visible || entities_waiting_for_assets.contains(&entity) {
|
||||
let mut draw_state = DrawState::default();
|
||||
for draw in <Read<Draw>>::query().iter(&world) {
|
||||
if !draw.is_visible {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -95,17 +100,23 @@ impl Node for MainPassNode {
|
|||
RenderCommand::SetPipeline { pipeline } => {
|
||||
// TODO: Filter pipelines
|
||||
render_pass.set_pipeline(*pipeline);
|
||||
let descriptor = pipelines.get(pipeline).unwrap();
|
||||
draw_state.set_pipeline(*pipeline, descriptor);
|
||||
}
|
||||
RenderCommand::DrawIndexed {
|
||||
base_vertex,
|
||||
indices,
|
||||
instances,
|
||||
} => {
|
||||
if draw_state.can_draw_indexed() {
|
||||
render_pass.draw_indexed(
|
||||
indices.clone(),
|
||||
*base_vertex,
|
||||
instances.clone(),
|
||||
);
|
||||
} else {
|
||||
log::info!("Could not draw indexed because the pipeline layout wasn't fully set for pipeline: {:?}", draw_state.pipeline);
|
||||
}
|
||||
}
|
||||
RenderCommand::SetVertexBuffer {
|
||||
buffer,
|
||||
|
@ -113,9 +124,11 @@ impl Node for MainPassNode {
|
|||
slot,
|
||||
} => {
|
||||
render_pass.set_vertex_buffer(*slot, *buffer, *offset);
|
||||
draw_state.set_vertex_buffer(*slot, *buffer);
|
||||
}
|
||||
RenderCommand::SetIndexBuffer { buffer, offset } => {
|
||||
render_pass.set_index_buffer(*buffer, *offset);
|
||||
draw_state.set_index_buffer(*buffer)
|
||||
}
|
||||
RenderCommand::SetBindGroup {
|
||||
index,
|
||||
|
@ -131,6 +144,7 @@ impl Node for MainPassNode {
|
|||
.as_ref()
|
||||
.map(|indices| indices.as_slice()),
|
||||
);
|
||||
draw_state.set_bind_group(*index, *render_resource_set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,3 +153,48 @@ impl Node for MainPassNode {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Tracks the current pipeline state to ensure draw calls are valid.
|
||||
#[derive(Default)]
|
||||
struct DrawState {
|
||||
pipeline: Option<Handle<PipelineDescriptor>>,
|
||||
bind_groups: Vec<Option<RenderResourceSetId>>,
|
||||
vertex_buffers: Vec<Option<RenderResourceId>>,
|
||||
index_buffer: Option<RenderResourceId>,
|
||||
}
|
||||
|
||||
impl DrawState {
|
||||
pub fn set_bind_group(&mut self, index: u32, render_resource_set: RenderResourceSetId) {
|
||||
self.bind_groups[index as usize] = Some(render_resource_set);
|
||||
}
|
||||
|
||||
pub fn set_vertex_buffer(&mut self, index: u32, buffer: RenderResourceId) {
|
||||
self.vertex_buffers[index as usize] = Some(buffer);
|
||||
}
|
||||
|
||||
pub fn set_index_buffer(&mut self, buffer: RenderResourceId) {
|
||||
self.index_buffer = Some(buffer);
|
||||
}
|
||||
|
||||
pub fn can_draw_indexed(&self) -> bool {
|
||||
self.bind_groups.iter().all(|b| b.is_some())
|
||||
&& self.vertex_buffers.iter().all(|v| v.is_some())
|
||||
&& self.index_buffer.is_some()
|
||||
}
|
||||
|
||||
pub fn set_pipeline(
|
||||
&mut self,
|
||||
handle: Handle<PipelineDescriptor>,
|
||||
descriptor: &PipelineDescriptor,
|
||||
) {
|
||||
self.bind_groups.clear();
|
||||
self.vertex_buffers.clear();
|
||||
self.index_buffer = None;
|
||||
|
||||
self.pipeline = Some(handle);
|
||||
let layout = descriptor.get_layout().unwrap();
|
||||
self.bind_groups.resize(layout.bind_groups.len(), None);
|
||||
self.vertex_buffers
|
||||
.resize(layout.vertex_buffer_descriptors.len(), None);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,19 +2,21 @@ use crate::{
|
|||
draw::{Draw, RenderPipelines},
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{
|
||||
self, BufferInfo, BufferUsage, EntitiesWaitingForAssets, RenderResourceAssignment,
|
||||
RenderResourceAssignments, RenderResourceAssignmentsId, RenderResourceHints,
|
||||
RenderResourceId,
|
||||
self, BufferInfo, BufferUsage, RenderResourceAssignment, RenderResourceAssignments,
|
||||
RenderResourceAssignmentsId, RenderResourceHints, RenderResourceId,
|
||||
},
|
||||
renderer::{RenderContext, RenderResourceContext, RenderResources},
|
||||
texture,
|
||||
};
|
||||
|
||||
use bevy_app::EventReader;
|
||||
use bevy_app::{EventReader, Events};
|
||||
use bevy_asset::{AssetEvent, Assets, Handle};
|
||||
use legion::prelude::*;
|
||||
use render_resource::ResourceInfo;
|
||||
use std::{collections::HashMap, marker::PhantomData};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
pub const BIND_BUFFER_ALIGNMENT: usize = 256;
|
||||
#[derive(Debug)]
|
||||
|
@ -25,7 +27,7 @@ struct QueuedBufferWrite {
|
|||
|
||||
#[derive(Debug)]
|
||||
struct BufferArrayStatus {
|
||||
new_item_count: usize,
|
||||
changed_item_count: usize,
|
||||
item_size: usize,
|
||||
aligned_size: usize,
|
||||
staging_buffer_offset: usize,
|
||||
|
@ -78,15 +80,15 @@ impl<T> UniformBufferArrays<T>
|
|||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
fn reset_new_item_counts(&mut self) {
|
||||
fn reset_changed_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;
|
||||
buffer_status.changed_item_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn increment_uniform_counts(&mut self, uniforms: &T) {
|
||||
fn increment_changed_item_counts(&mut self, uniforms: &T) {
|
||||
if self.uniform_arrays.len() != uniforms.render_resources_len() {
|
||||
self.uniform_arrays
|
||||
.resize_with(uniforms.render_resources_len(), || None);
|
||||
|
@ -96,12 +98,12 @@ where
|
|||
let render_resource_name = uniforms.get_render_resource_name(i).unwrap();
|
||||
let size = render_resource.buffer_byte_len().unwrap();
|
||||
if let Some((ref _name, ref mut buffer_array_status)) = self.uniform_arrays[i] {
|
||||
buffer_array_status.new_item_count += 1;
|
||||
buffer_array_status.changed_item_count += 1;
|
||||
} else {
|
||||
self.uniform_arrays[i] = Some((
|
||||
render_resource_name.to_string(),
|
||||
BufferArrayStatus {
|
||||
new_item_count: 1,
|
||||
changed_item_count: 1,
|
||||
queued_buffer_writes: Vec::new(),
|
||||
aligned_size: Self::get_aligned_dynamic_uniform_size(size),
|
||||
item_size: size,
|
||||
|
@ -134,7 +136,7 @@ where
|
|||
}
|
||||
|
||||
buffer_array_status.queued_buffer_writes =
|
||||
Vec::with_capacity(buffer_array_status.new_item_count);
|
||||
Vec::with_capacity(buffer_array_status.changed_item_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,9 +146,9 @@ where
|
|||
render_resource_context: &dyn RenderResourceContext,
|
||||
align: bool,
|
||||
) {
|
||||
if buffer_array_status.current_item_capacity < buffer_array_status.new_item_count {
|
||||
if buffer_array_status.current_item_capacity < buffer_array_status.changed_item_count {
|
||||
let new_capacity =
|
||||
buffer_array_status.new_item_count + buffer_array_status.new_item_count / 2;
|
||||
buffer_array_status.changed_item_count + buffer_array_status.changed_item_count / 2;
|
||||
let mut item_size = buffer_array_status.item_size;
|
||||
if align {
|
||||
item_size = Self::get_aligned_dynamic_uniform_size(item_size);
|
||||
|
@ -177,7 +179,7 @@ where
|
|||
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 += buffer_array_status.item_size * buffer_array_status.changed_item_count;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,7 +300,7 @@ where
|
|||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UniformNode<T>
|
||||
pub struct RenderResourcesNode<T>
|
||||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
|
@ -307,12 +309,12 @@ where
|
|||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> UniformNode<T>
|
||||
impl<T> RenderResourcesNode<T>
|
||||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
pub fn new(dynamic_uniforms: bool) -> Self {
|
||||
UniformNode {
|
||||
RenderResourcesNode {
|
||||
command_queue: CommandQueue::default(),
|
||||
dynamic_uniforms,
|
||||
_marker: PhantomData::default(),
|
||||
|
@ -320,7 +322,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Node for UniformNode<T>
|
||||
impl<T> Node for RenderResourcesNode<T>
|
||||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
|
@ -336,7 +338,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> SystemNode for UniformNode<T>
|
||||
impl<T> SystemNode for RenderResourcesNode<T>
|
||||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
|
@ -347,35 +349,30 @@ where
|
|||
// TODO: maybe run "update" here
|
||||
(move |world: &mut SubWorld,
|
||||
render_resources: Res<RenderResources>,
|
||||
entities_waiting_for_assets: Res<EntitiesWaitingForAssets>,
|
||||
query: &mut Query<(Read<T>, Read<Draw>, Write<RenderPipelines>)>| {
|
||||
let render_resource_context = &*render_resources.context;
|
||||
|
||||
uniform_buffer_arrays.reset_new_item_counts();
|
||||
uniform_buffer_arrays.reset_changed_item_counts();
|
||||
// update uniforms info
|
||||
for (uniforms, draw, _render_pipelines) in query.iter_mut(world) {
|
||||
if !draw.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
uniform_buffer_arrays.increment_uniform_counts(&uniforms);
|
||||
uniform_buffer_arrays.increment_changed_item_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 (entity, (uniforms, draw, mut render_pipelines)) in
|
||||
query.iter_entities_mut(world)
|
||||
{
|
||||
for (uniforms, draw, mut render_pipelines) in query.iter_mut(world) {
|
||||
if !draw.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
setup_uniform_texture_resources::<T>(
|
||||
entity,
|
||||
&uniforms,
|
||||
render_resource_context,
|
||||
&entities_waiting_for_assets,
|
||||
&mut render_pipelines.render_resource_assignments,
|
||||
)
|
||||
}
|
||||
|
@ -403,9 +400,7 @@ where
|
|||
..Default::default()
|
||||
},
|
||||
&mut |mut staging_buffer, _render_resources| {
|
||||
for (uniforms, draw, mut render_pipelines) in
|
||||
query.iter_mut(world)
|
||||
{
|
||||
for (uniforms, draw, mut render_pipelines) in query.iter_mut(world) {
|
||||
if !draw.is_visible {
|
||||
return;
|
||||
}
|
||||
|
@ -431,7 +426,7 @@ where
|
|||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct AssetUniformNode<T>
|
||||
pub struct AssetRenderResourcesNode<T>
|
||||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
|
@ -440,12 +435,12 @@ where
|
|||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> AssetUniformNode<T>
|
||||
impl<T> AssetRenderResourcesNode<T>
|
||||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
pub fn new(dynamic_uniforms: bool) -> Self {
|
||||
AssetUniformNode {
|
||||
AssetRenderResourcesNode {
|
||||
dynamic_uniforms,
|
||||
command_queue: Default::default(),
|
||||
_marker: Default::default(),
|
||||
|
@ -453,7 +448,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Node for AssetUniformNode<T>
|
||||
impl<T> Node for AssetRenderResourcesNode<T>
|
||||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
|
@ -469,72 +464,79 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> SystemNode for AssetUniformNode<T>
|
||||
const EXPECT_ASSET_MESSAGE: &str = "Only assets that exist should be in the modified assets list";
|
||||
|
||||
impl<T> SystemNode for AssetRenderResourcesNode<T>
|
||||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
fn get_system(&self) -> Box<dyn Schedulable> {
|
||||
let mut command_queue = self.command_queue.clone();
|
||||
let mut uniform_buffer_arrays = UniformBufferArrays::<T>::default();
|
||||
let mut asset_event_reader = EventReader::<AssetEvent<T>>::default();
|
||||
let mut asset_render_resource_assignments =
|
||||
HashMap::<Handle<T>, RenderResourceAssignments>::default();
|
||||
let dynamic_uniforms = self.dynamic_uniforms;
|
||||
(move |world: &mut SubWorld,
|
||||
assets: Res<Assets<T>>,
|
||||
asset_events: Res<Events<AssetEvent<T>>>,
|
||||
render_resources: Res<RenderResources>,
|
||||
entities_waiting_for_assets: Res<EntitiesWaitingForAssets>,
|
||||
query: &mut Query<(Read<Handle<T>>, Read<Draw>, Write<RenderPipelines>)>| {
|
||||
let render_resource_context = &*render_resources.context;
|
||||
uniform_buffer_arrays.reset_new_item_counts();
|
||||
uniform_buffer_arrays.reset_changed_item_counts();
|
||||
|
||||
let mut modified_assets = HashSet::new();
|
||||
for event in asset_event_reader.iter(&asset_events) {
|
||||
match event {
|
||||
AssetEvent::Created { handle } => {
|
||||
modified_assets.insert(*handle);
|
||||
}
|
||||
AssetEvent::Modified { handle } => {
|
||||
modified_assets.insert(*handle);
|
||||
}
|
||||
AssetEvent::Removed { handle } => {
|
||||
// TODO: handle removals
|
||||
modified_assets.remove(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update uniform handles info
|
||||
for (entity, (handle, draw, _render_pipelines)) in query.iter_entities_mut(world) {
|
||||
if !draw.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(uniforms) = assets.get(&handle) {
|
||||
// TODO: only increment count if we haven't seen this uniform handle before
|
||||
uniform_buffer_arrays.increment_uniform_counts(&uniforms);
|
||||
} else {
|
||||
entities_waiting_for_assets.add(entity)
|
||||
}
|
||||
for asset_handle in modified_assets.iter() {
|
||||
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
|
||||
uniform_buffer_arrays.increment_changed_item_counts(&asset);
|
||||
}
|
||||
|
||||
uniform_buffer_arrays.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
|
||||
let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets();
|
||||
|
||||
for (entity, (handle, draw, mut render_pipelines)) in
|
||||
query.iter_entities_mut(world)
|
||||
{
|
||||
if !draw.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(uniforms) = assets.get(&handle) {
|
||||
for asset_handle in modified_assets.iter() {
|
||||
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
|
||||
let mut render_resource_assignments = asset_render_resource_assignments
|
||||
.entry(*asset_handle)
|
||||
.or_insert_with(|| RenderResourceAssignments::default());
|
||||
setup_uniform_texture_resources::<T>(
|
||||
entity,
|
||||
&uniforms,
|
||||
&asset,
|
||||
render_resource_context,
|
||||
&entities_waiting_for_assets,
|
||||
&mut render_pipelines.render_resource_assignments,
|
||||
)
|
||||
}
|
||||
}
|
||||
if staging_buffer_size == 0 {
|
||||
let mut staging_buffer: [u8; 0] = [];
|
||||
for (handle, draw, mut render_pipelines) in query.iter_mut(world) {
|
||||
if !draw.is_visible {
|
||||
return;
|
||||
}
|
||||
if let Some(uniforms) = assets.get(&handle) {
|
||||
// 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 render_pipelines.render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
&mut render_resource_assignments,
|
||||
);
|
||||
}
|
||||
|
||||
if staging_buffer_size == 0 {
|
||||
let mut staging_buffer: [u8; 0] = [];
|
||||
for asset_handle in modified_assets.iter() {
|
||||
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
|
||||
let mut render_resource_assignments = asset_render_resource_assignments
|
||||
.entry(*asset_handle)
|
||||
.or_insert_with(|| RenderResourceAssignments::default());
|
||||
// TODO: only setup buffer if we haven't seen this handle before
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&asset,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let staging_buffer = render_resource_context.create_buffer_mapped(
|
||||
|
@ -544,21 +546,20 @@ where
|
|||
..Default::default()
|
||||
},
|
||||
&mut |mut staging_buffer, _render_resources| {
|
||||
for (handle, draw, mut render_pipelines) in query.iter_mut(world) {
|
||||
if !draw.is_visible {
|
||||
return;
|
||||
}
|
||||
if let Some(uniforms) = assets.get(&handle) {
|
||||
for asset_handle in modified_assets.iter() {
|
||||
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);
|
||||
let mut render_resource_assignments = asset_render_resource_assignments
|
||||
.entry(*asset_handle)
|
||||
.or_insert_with(|| RenderResourceAssignments::default());
|
||||
// TODO: only setup buffer if we haven't seen this handle before
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
&asset,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut render_pipelines.render_resource_assignments,
|
||||
&mut render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -566,16 +567,20 @@ where
|
|||
.copy_staging_buffer_to_final_buffers(&mut command_queue, staging_buffer);
|
||||
command_queue.free_buffer(staging_buffer);
|
||||
}
|
||||
|
||||
for (asset_handle, _draw, mut render_pipelines) in query.iter_mut(world) {
|
||||
if let Some(asset_assignments) = asset_render_resource_assignments.get(&asset_handle) {
|
||||
render_pipelines.render_resource_assignments.extend(asset_assignments);
|
||||
}
|
||||
}
|
||||
})
|
||||
.system()
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_uniform_texture_resources<T>(
|
||||
entity: Entity,
|
||||
uniforms: &T,
|
||||
render_resource_context: &dyn RenderResourceContext,
|
||||
entities_waiting_for_assets: &EntitiesWaitingForAssets,
|
||||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
) where
|
||||
T: render_resource::RenderResources,
|
||||
|
@ -600,11 +605,7 @@ fn setup_uniform_texture_resources<T>(
|
|||
RenderResourceAssignment::Sampler(sampler_resource),
|
||||
);
|
||||
continue;
|
||||
} else {
|
||||
entities_waiting_for_assets.add(entity);
|
||||
}
|
||||
} else {
|
||||
entities_waiting_for_assets.add(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
use legion::prelude::{Entity, Res};
|
||||
use std::{collections::HashSet, sync::RwLock};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct EntitiesWaitingForAssets {
|
||||
pub entities: RwLock<HashSet<Entity>>,
|
||||
}
|
||||
|
||||
impl EntitiesWaitingForAssets {
|
||||
pub fn add(&self, entity: Entity) {
|
||||
self.entities
|
||||
.write()
|
||||
.expect("RwLock poisoned")
|
||||
.insert(entity);
|
||||
}
|
||||
|
||||
pub fn contains(&self, entity: &Entity) -> bool {
|
||||
self.entities
|
||||
.read()
|
||||
.expect("RwLock poisoned")
|
||||
.contains(entity)
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
self.entities.write().expect("RwLock poisoned").clear();
|
||||
}
|
||||
|
||||
pub fn clear_system(entities_waiting_for_assets: Res<EntitiesWaitingForAssets>) {
|
||||
entities_waiting_for_assets.clear();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
mod buffer;
|
||||
mod entities_waiting_for_assets;
|
||||
mod render_resource;
|
||||
mod render_resource_set;
|
||||
mod render_resource_assignments;
|
||||
|
@ -7,7 +6,6 @@ mod resource_info;
|
|||
mod systems;
|
||||
|
||||
pub use buffer::*;
|
||||
pub use entities_waiting_for_assets::*;
|
||||
pub use render_resource::*;
|
||||
pub use render_resource_set::*;
|
||||
pub use render_resource_assignments::*;
|
||||
|
|
|
@ -2,7 +2,7 @@ use super::{RenderResourceId, RenderResourceSet, RenderResourceSetId};
|
|||
use crate::pipeline::{BindGroupDescriptor, BindGroupDescriptorId, PipelineSpecialization};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
hash::{Hash, Hasher},
|
||||
hash::Hash,
|
||||
ops::Range,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
@ -60,6 +60,7 @@ impl RenderResourceAssignments {
|
|||
fn try_set_dirty(&mut self, name: &str, assignment: &RenderResourceAssignment) {
|
||||
if let Some(current_assignment) = self.render_resources.get(name) {
|
||||
if current_assignment != assignment {
|
||||
// TODO: this is crude. we shouldn't need to invalidate all render resource sets
|
||||
for id in self.render_resource_sets.keys() {
|
||||
self.dirty_render_resource_sets.insert(*id);
|
||||
}
|
||||
|
@ -67,6 +68,18 @@ impl RenderResourceAssignments {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, render_resource_assignments: &RenderResourceAssignments) {
|
||||
for (name, assignment) in render_resource_assignments.render_resources.iter() {
|
||||
self.set(name, assignment.clone());
|
||||
}
|
||||
|
||||
for (name, (vertex_buffer, index_buffer)) in
|
||||
render_resource_assignments.vertex_buffers.iter()
|
||||
{
|
||||
self.set_vertex_buffer(name, *vertex_buffer, index_buffer.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_vertex_buffer(
|
||||
&self,
|
||||
name: &str,
|
||||
|
|
|
@ -16,10 +16,10 @@ pub struct IndexedRenderResourceAssignment {
|
|||
}
|
||||
|
||||
// TODO: consider renaming this to BindGroup for parity with renderer terminology
|
||||
#[derive(Eq, PartialEq, Debug)]
|
||||
#[derive(Clone, Eq, PartialEq, Debug)]
|
||||
pub struct RenderResourceSet {
|
||||
pub id: RenderResourceSetId,
|
||||
pub indexed_assignments: Vec<IndexedRenderResourceAssignment>,
|
||||
pub indexed_assignments: Arc<Vec<IndexedRenderResourceAssignment>>,
|
||||
pub dynamic_uniform_indices: Option<Arc<Vec<u32>>>,
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ impl RenderResourceSetBuilder {
|
|||
self.indexed_assignments.sort_by_key(|i| i.index);
|
||||
RenderResourceSet {
|
||||
id: RenderResourceSetId(self.hasher.finish()),
|
||||
indexed_assignments: self.indexed_assignments,
|
||||
indexed_assignments: Arc::new(self.indexed_assignments),
|
||||
dynamic_uniform_indices: if self.dynamic_uniform_indices.is_empty() {
|
||||
None
|
||||
} else {
|
||||
|
|
|
@ -4,7 +4,7 @@ use bevy_render::{
|
|||
base_render_graph,
|
||||
pipeline::{state_descriptors::*, PipelineDescriptor},
|
||||
render_graph::{
|
||||
nodes::{AssetUniformNode, UniformNode},
|
||||
nodes::{AssetRenderResourcesNode, RenderResourcesNode},
|
||||
RenderGraph,
|
||||
},
|
||||
shader::{Shader, ShaderStage, ShaderStages},
|
||||
|
@ -123,23 +123,23 @@ impl SpriteRenderGraphBuilder for RenderGraph {
|
|||
fn add_sprite_graph(&mut self, resources: &Resources) -> &mut Self {
|
||||
self.add_system_node(
|
||||
node::COLOR_MATERIAL,
|
||||
AssetUniformNode::<ColorMaterial>::new(false),
|
||||
AssetRenderResourcesNode::<ColorMaterial>::new(false),
|
||||
);
|
||||
self.add_node_edge(node::COLOR_MATERIAL, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
|
||||
self.add_system_node(node::QUAD, UniformNode::<Quad>::new(false));
|
||||
self.add_system_node(node::QUAD, RenderResourcesNode::<Quad>::new(false));
|
||||
self.add_node_edge(node::QUAD, base_render_graph::node::MAIN_PASS)
|
||||
.unwrap();
|
||||
|
||||
self.add_system_node(
|
||||
node::SPRITE_SHEET,
|
||||
AssetUniformNode::<TextureAtlas>::new(false),
|
||||
AssetRenderResourcesNode::<TextureAtlas>::new(false),
|
||||
);
|
||||
|
||||
self.add_system_node(
|
||||
node::SPRITE_SHEET_SPRITE,
|
||||
UniformNode::<TextureAtlasSprite>::new(true),
|
||||
RenderResourcesNode::<TextureAtlasSprite>::new(true),
|
||||
);
|
||||
|
||||
let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap();
|
||||
|
|
|
@ -53,7 +53,7 @@ fn setup(
|
|||
fragment: Some(shaders.add(Shader::from_glsl(ShaderStage::Fragment, FRAGMENT_SHADER))),
|
||||
}));
|
||||
|
||||
render_graph.add_system_node("my_material", AssetUniformNode::<MyMaterial>::new(true));
|
||||
render_graph.add_system_node("my_material", AssetRenderResourcesNode::<MyMaterial>::new(true));
|
||||
pipeline_handle
|
||||
};
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ fn setup(
|
|||
vertex: shaders.add(Shader::from_glsl(ShaderStage::Vertex, VERTEX_SHADER)),
|
||||
fragment: Some(shaders.add(Shader::from_glsl(ShaderStage::Fragment, FRAGMENT_SHADER))),
|
||||
}));
|
||||
render_graph.add_system_node("my_material", AssetUniformNode::<MyMaterial>::new(true));
|
||||
render_graph.add_system_node("my_material", AssetRenderResourcesNode::<MyMaterial>::new(true));
|
||||
pipeline_handle
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ pub use crate::{
|
|||
pipeline::PipelineDescriptor,
|
||||
render_graph::{
|
||||
nodes::{
|
||||
AssetUniformNode, CameraNode, MainPassNode, UniformNode, WindowSwapChainNode,
|
||||
AssetRenderResourcesNode, CameraNode, MainPassNode, RenderResourcesNode, WindowSwapChainNode,
|
||||
WindowTextureNode,
|
||||
},
|
||||
RenderGraph,
|
||||
|
|
Loading…
Reference in a new issue