Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions crates/bevy_ecs/src/core/world_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,17 @@ impl<'a> WorldBuilder<'a> {
self.current_entity = Some(self.world.spawn(components));
self
}

#[inline]
pub fn current_entity(&self) -> Option<Entity> {
self.current_entity
}

pub fn for_current_entity(&mut self, f: impl FnOnce(Entity)) -> &mut Self {
let current_entity = self
.current_entity
.expect("The 'current entity' is not set. You should spawn an entity first.");
f(current_entity);
self
}
}
100 changes: 70 additions & 30 deletions crates/bevy_render/src/mesh/mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ use crate::{
use bevy_app::prelude::{EventReader, Events};
use bevy_asset::{AssetEvent, Assets, Handle};
use bevy_core::AsBytes;
use bevy_ecs::{Local, Query, Res};
use bevy_ecs::{Changed, Entity, Local, Mut, Query, QuerySet, Res, With};
use bevy_math::*;
use bevy_reflect::TypeUuid;
use std::borrow::Cow;

use crate::pipeline::{InputStepMode, VertexAttributeDescriptor, VertexBufferDescriptor};
use bevy_utils::HashMap;
use bevy_utils::{HashMap, HashSet};

pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
Expand Down Expand Up @@ -320,17 +320,27 @@ fn remove_current_mesh_resources(
remove_resource_save(render_resource_context, handle, INDEX_BUFFER_ASSET_INDEX);
}

#[derive(Default)]
pub struct MeshEntities {
entities: HashSet<Entity>,
waiting: HashSet<Entity>,
}

#[derive(Default)]
pub struct MeshResourceProviderState {
mesh_event_reader: EventReader<AssetEvent<Mesh>>,
mesh_entities: HashMap<Handle<Mesh>, MeshEntities>,
}

pub fn mesh_resource_provider_system(
mut state: Local<MeshResourceProviderState>,
render_resource_context: Res<Box<dyn RenderResourceContext>>,
meshes: Res<Assets<Mesh>>,
mesh_events: Res<Events<AssetEvent<Mesh>>>,
mut query: Query<(&Handle<Mesh>, &mut RenderPipelines)>,
mut queries: QuerySet<(
Query<&mut RenderPipelines, With<Handle<Mesh>>>,
Query<(Entity, &Handle<Mesh>, &mut RenderPipelines), Changed<Handle<Mesh>>>,
)>,
) {
let mut changed_meshes = bevy_utils::HashSet::<Handle<Mesh>>::default();
let render_resource_context = &**render_resource_context;
Expand Down Expand Up @@ -383,39 +393,69 @@ pub fn mesh_resource_provider_system(
)),
VERTEX_ATTRIBUTE_BUFFER_ID,
);

if let Some(mesh_entities) = state.mesh_entities.get_mut(changed_mesh_handle) {
for entity in mesh_entities.waiting.drain() {
if let Ok(render_pipelines) = queries.q0_mut().get_mut(entity) {
mesh_entities.entities.insert(entity);
update_entity_mesh(
render_resource_context,
mesh,
changed_mesh_handle,
render_pipelines,
);
}
}
}
}
}

// handover buffers to pipeline
for (handle, mut render_pipelines) in query.iter_mut() {
for (entity, handle, render_pipelines) in queries.q1_mut().iter_mut() {
let mesh_entities = state
.mesh_entities
.entry(handle.clone_weak())
.or_insert_with(MeshEntities::default);
if let Some(mesh) = meshes.get(handle) {
for render_pipeline in render_pipelines.pipelines.iter_mut() {
render_pipeline.specialization.primitive_topology = mesh.primitive_topology;
// TODO: don't allocate a new vertex buffer descriptor for every entity
render_pipeline.specialization.vertex_buffer_descriptor =
mesh.get_vertex_buffer_descriptor();
render_pipeline.specialization.index_format = mesh
.indices()
.map(|i| i.into())
.unwrap_or(IndexFormat::Uint32);
}
mesh_entities.entities.insert(entity);
mesh_entities.waiting.remove(&entity);
update_entity_mesh(render_resource_context, mesh, handle, render_pipelines);
} else {
mesh_entities.waiting.insert(entity);
}
}
}

if let Some(RenderResourceId::Buffer(index_buffer_resource)) =
render_resource_context.get_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX)
{
// set index buffer into binding
render_pipelines
.bindings
.set_index_buffer(index_buffer_resource);
}
fn update_entity_mesh(
render_resource_context: &dyn RenderResourceContext,
mesh: &Mesh,
handle: &Handle<Mesh>,
mut render_pipelines: Mut<RenderPipelines>,
) {
for render_pipeline in render_pipelines.pipelines.iter_mut() {
render_pipeline.specialization.primitive_topology = mesh.primitive_topology;
// TODO: don't allocate a new vertex buffer descriptor for every entity
render_pipeline.specialization.vertex_buffer_descriptor =
mesh.get_vertex_buffer_descriptor();
render_pipeline.specialization.index_format = mesh
.indices()
.map(|i| i.into())
.unwrap_or(IndexFormat::Uint32);
}

if let Some(RenderResourceId::Buffer(vertex_attribute_buffer_resource)) =
render_resource_context.get_asset_resource(handle, VERTEX_ATTRIBUTE_BUFFER_ID)
{
// set index buffer into binding
render_pipelines.bindings.vertex_attribute_buffer =
Some(vertex_attribute_buffer_resource);
}
}
if let Some(RenderResourceId::Buffer(index_buffer_resource)) =
render_resource_context.get_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX)
{
// set index buffer into binding
render_pipelines
.bindings
.set_index_buffer(index_buffer_resource);
}

if let Some(RenderResourceId::Buffer(vertex_attribute_buffer_resource)) =
render_resource_context.get_asset_resource(handle, VERTEX_ATTRIBUTE_BUFFER_ID)
{
// set index buffer into binding
render_pipelines.bindings.vertex_attribute_buffer = Some(vertex_attribute_buffer_resource);
}
}
45 changes: 36 additions & 9 deletions crates/bevy_render/src/render_graph/nodes/pass_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,9 @@ where
for render_command in draw.render_commands.iter() {
match render_command {
RenderCommand::SetPipeline { pipeline } => {
// TODO: Filter pipelines
if draw_state.is_pipeline_set(pipeline.clone_weak()) {
continue;
}
render_pass.set_pipeline(pipeline);
let descriptor = pipelines.get(pipeline).unwrap();
draw_state.set_pipeline(pipeline, descriptor);
Expand Down Expand Up @@ -290,18 +292,27 @@ where
offset,
slot,
} => {
if draw_state.is_vertex_buffer_set(*slot, *buffer, *offset) {
continue;
}
render_pass.set_vertex_buffer(*slot, *buffer, *offset);
draw_state.set_vertex_buffer(*slot, *buffer);
draw_state.set_vertex_buffer(*slot, *buffer, *offset);
}
RenderCommand::SetIndexBuffer { buffer, offset } => {
if draw_state.is_index_buffer_set(*buffer, *offset) {
continue;
}
render_pass.set_index_buffer(*buffer, *offset);
draw_state.set_index_buffer(*buffer)
draw_state.set_index_buffer(*buffer, *offset)
}
RenderCommand::SetBindGroup {
index,
bind_group,
dynamic_uniform_indices,
} => {
if dynamic_uniform_indices.is_none() && draw_state.is_bind_group_set(*index, *bind_group) {
continue;
}
let pipeline = pipelines.get(draw_state.pipeline.as_ref().unwrap()).unwrap();
let layout = pipeline.get_layout().unwrap();
let bind_group_descriptor = layout.get_bind_group(*index).unwrap();
Expand Down Expand Up @@ -329,21 +340,33 @@ where
struct DrawState {
pipeline: Option<Handle<PipelineDescriptor>>,
bind_groups: Vec<Option<BindGroupId>>,
vertex_buffers: Vec<Option<BufferId>>,
index_buffer: Option<BufferId>,
vertex_buffers: Vec<Option<(BufferId, u64)>>,
index_buffer: Option<(BufferId, u64)>,
}

impl DrawState {
pub fn set_bind_group(&mut self, index: u32, bind_group: BindGroupId) {
self.bind_groups[index as usize] = Some(bind_group);
}

pub fn set_vertex_buffer(&mut self, index: u32, buffer: BufferId) {
self.vertex_buffers[index as usize] = Some(buffer);
pub fn is_bind_group_set(&self, index: u32, bind_group: BindGroupId) -> bool {
self.bind_groups[index as usize] == Some(bind_group)
}

pub fn set_vertex_buffer(&mut self, index: u32, buffer: BufferId, offset: u64) {
self.vertex_buffers[index as usize] = Some((buffer, offset));
}

pub fn set_index_buffer(&mut self, buffer: BufferId) {
self.index_buffer = Some(buffer);
pub fn is_vertex_buffer_set(&self, index: u32, buffer: BufferId, offset: u64) -> bool {
self.vertex_buffers[index as usize] == Some((buffer, offset))
}

pub fn set_index_buffer(&mut self, buffer: BufferId, offset: u64) {
self.index_buffer = Some((buffer, offset));
}

pub fn is_index_buffer_set(&self, buffer: BufferId, offset: u64) -> bool {
self.index_buffer == Some((buffer, offset))
}

pub fn can_draw(&self) -> bool {
Expand All @@ -355,6 +378,10 @@ impl DrawState {
self.can_draw() && self.index_buffer.is_some()
}

pub fn is_pipeline_set(&self, pipeline: Handle<PipelineDescriptor>) -> bool {
self.pipeline == Some(pipeline)
}

pub fn set_pipeline(
&mut self,
handle: &Handle<PipelineDescriptor>,
Expand Down
Loading