Skip to content

Commit

Permalink
New vec stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
jamescarterbell committed Dec 23, 2023
1 parent 32a677c commit 5b7f348
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 67 deletions.
97 changes: 85 additions & 12 deletions crates/bevy_tiles_render/src/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bevy::{
ecs::{
query::ROQueryItem,
system::{
lifetimeless::{Read, SRes},
lifetimeless::{Read, SRes, SResMut},
SystemParamItem,
},
},
Expand All @@ -12,24 +12,96 @@ use bevy::{
render_phase::{
PhaseItem, RenderCommand, RenderCommandResult, SetItemPipeline, TrackedRenderPass,
},
render_resource::PipelineCache,
render_resource::{BindGroupEntries, PipelineCache},
renderer::{RenderDevice, RenderQueue},
},
sprite::{DrawMesh2d, SetMesh2dViewBindGroup},
transform::components::GlobalTransform,
};

use crate::{prepare::TilesChunkMeshBindGroup, tiles_render::TriThingBindGroups};
use crate::{
bindings::TilesChunkModelUniform, gpu_storage_buffer::GpuStorageBuffer,
pipeline::TilesChunkPipeline, prepare::TilesChunkMeshBindGroup,
tiles_render::TriThingBindGroups,
};

pub type LoadChunk = AddTransform;

pub type DrawTiles = (
pub type DrawChunks = (
// Set the pipeline
SetItemPipeline,
// Set the view uniform as bind group 0
SetMesh2dViewBindGroup<0>,
// Set the mesh uniform as bind group 1
SetChunkBindGroup<1>,
// Draw the mesh
DrawChunks,
DrawChunkBatch,
);

pub struct AddTransform;
impl RenderCommand<Transparent2d> for AddTransform {
type Param = SResMut<GpuStorageBuffer<TilesChunkModelUniform>>;

type ViewWorldQuery = ();

type ItemWorldQuery = Read<GlobalTransform>;

#[inline]
fn render<'w>(
item: &Transparent2d,
_view: (),
uniforms: ROQueryItem<'w, Self::ItemWorldQuery>,
mut chunk_uniforms: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult {
chunk_uniforms.push(uniforms.into());
RenderCommandResult::Success
}
}
pub struct CreateUniformBindGroups;
impl RenderCommand<Transparent2d> for CreateUniformBindGroups {
type Param = (
SRes<RenderDevice>,
SRes<RenderQueue>,
SRes<TilesChunkPipeline>,
SRes<GpuStorageBuffer<TilesChunkModelUniform>>,
SResMut<TilesChunkMeshBindGroup>,
);

type ViewWorldQuery = ();

type ItemWorldQuery = ();

#[inline]
fn render<'w>(
item: &Transparent2d,
_view: (),
_item_query: (),
(device, queue, base_pipeline, mut model_buffer, mut bind_groups): SystemParamItem<
'w,
'_,
Self::Param,
>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult {
model_buffer.write_buffer(&device, &queue);

let Some(binding) = model_buffer.binding() else {
return RenderCommandResult::Failure;
};

let bind_group = device.create_bind_group(
"tiles_bind_group",
&base_pipeline.tiles_bind_groups.mesh_layout,
&BindGroupEntries::single(binding),
);

bind_groups.value = Some(bind_group);

RenderCommandResult::Success
}
}

pub struct SetChunkBindGroup<const I: usize>;
impl<const I: usize> RenderCommand<Transparent2d> for SetChunkBindGroup<I> {
type Param = SRes<TilesChunkMeshBindGroup>;
Expand All @@ -52,17 +124,18 @@ impl<const I: usize> RenderCommand<Transparent2d> for SetChunkBindGroup<I> {
dynamic_offsets[offset_count] = dynamic_offset.get();
offset_count += 1;
}
pass.set_bind_group(
I,
&mesh2d_bind_group.into_inner().value,
&dynamic_offsets[..offset_count],
);

let Some(model_bindgroup) = mesh2d_bind_group.value else {
return RenderCommandResult::Failure;
};

pass.set_bind_group(I, &model_bindgroup, &dynamic_offsets[..offset_count]);
RenderCommandResult::Success
}
}

pub struct DrawChunks;
impl RenderCommand<Transparent2d> for DrawChunks {
pub struct DrawChunkBatch;
impl RenderCommand<Transparent2d> for DrawChunkBatch {
type Param = ();

type ViewWorldQuery = ();
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_tiles_render/src/extract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use bevy::{

use crate::tiles::TriThing;

pub fn extract_tri_things(
pub fn extract_chunks(
mut commands: Commands,
tri_things: Extract<Query<(Entity, &GlobalTransform, &TriThing)>>,
) {
Expand Down
12 changes: 7 additions & 5 deletions crates/bevy_tiles_render/src/gpu_storage_buffer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{marker::PhantomData, mem};

use bevy::{
ecs::system::Resource,
ecs::{system::Resource, world::FromWorld},
render::{
render_resource::{
BindGroupLayoutEntry, BindingResource, BindingType, BufferBindingType,
Expand All @@ -20,14 +20,16 @@ pub struct GpuStorageBuffer<T: GpuArrayBufferable> {
buffer: Vec<T>,
}

impl<T: GpuArrayBufferable> GpuStorageBuffer<T> {
pub fn new(device: &RenderDevice) -> Self {
impl<T: GpuArrayBufferable> Default for GpuStorageBuffer<T> {
fn default() -> Self {
Self {
gpu_buffer: StorageBuffer::default(),
buffer: Vec::new(),
gpu_buffer: Default::default(),
buffer: Default::default(),
}
}
}

impl<T: GpuArrayBufferable> GpuStorageBuffer<T> {
pub fn clear(&mut self) {
self.buffer.clear()
}
Expand Down
26 changes: 14 additions & 12 deletions crates/bevy_tiles_render/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ use bevy::{
ExtractSchedule, Render, RenderApp, RenderSet,
},
};
use draw::DrawTiles;
use extract::extract_tri_things;
use prepare::prepare_chunk_bind_groups;
use queue::queue_tri_things;

use extract::extract_chunks;
use queue::queue_chunks;

use crate::{
bindings::TilesChunkModelUniform, gpu_storage_buffer::GpuStorageBuffer,
bindings::TilesChunkModelUniform,
draw::{DrawChunkBatch, LoadChunk},
gpu_storage_buffer::GpuStorageBuffer,
pipeline::TilesChunkPipeline,
prepare::TilesChunkMeshBindGroup,
};

mod bindings;
Expand All @@ -27,6 +29,7 @@ mod gpu_storage_buffer;
mod pipeline;
mod prepare;
mod queue;
pub mod settings;
pub mod tiles;
mod tiles_render;

Expand All @@ -41,9 +44,8 @@ impl Plugin for TilesRenderPlugin {

// Respawn chunks that we saved from the last frame
// Copy over tile data
render_app.add_systems(ExtractSchedule, extract_tri_things);
render_app.add_systems(Render, prepare_chunk_bind_groups.in_set(RenderSet::Prepare));
render_app.add_systems(Render, queue_tri_things.in_set(RenderSet::Queue));
render_app.add_systems(ExtractSchedule, extract_chunks);
render_app.add_systems(Render, queue_chunks.in_set(RenderSet::Queue));
/*
render_app.add_systems(
ExtractSchedule,
Expand All @@ -62,11 +64,11 @@ impl Plugin for TilesRenderPlugin {
fn finish(&self, app: &mut bevy::prelude::App) {
let render_app = app.get_sub_app_mut(RenderApp).expect("No RenderApp found!");

render_app.add_render_command::<Transparent2d, DrawTiles>();
render_app.add_render_command::<Transparent2d, DrawChunkBatch>();
render_app.add_render_command::<Transparent2d, LoadChunk>();
render_app
.insert_resource(GpuStorageBuffer::<TilesChunkModelUniform>::new(
render_app.world.resource::<RenderDevice>(),
))
.init_resource::<TilesChunkMeshBindGroup>()
.init_resource::<GpuStorageBuffer<TilesChunkModelUniform>>()
.init_resource::<TilesChunkPipeline>()
.init_resource::<SpecializedRenderPipelines<TilesChunkPipeline>>();

Expand Down
28 changes: 2 additions & 26 deletions crates/bevy_tiles_render/src/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,7 @@ use crate::{
pipeline::TilesChunkPipeline, tiles::TriThing, tiles_render::TriThingBindGroups,
};

#[derive(Resource)]
#[derive(Resource, Default)]
pub struct TilesChunkMeshBindGroup {
pub value: BindGroup,
}

pub fn prepare_chunk_bind_groups(
mut commands: Commands,
tiles_chunk_pipeline: Res<TilesChunkPipeline>,
render_device: Res<RenderDevice>,
render_queue: Res<RenderQueue>,
mut mesh_uniforms: ResMut<GpuStorageBuffer<TilesChunkModelUniform>>,
chunks: Query<&GlobalTransform, With<TriThing>>,
) {
mesh_uniforms.clear();
for transform in chunks.iter() {
mesh_uniforms.push(transform.into());
}
mesh_uniforms.write_buffer(&render_device, &render_queue);
if let Some(binding) = mesh_uniforms.binding() {
commands.insert_resource(TilesChunkMeshBindGroup {
value: render_device.create_bind_group(
"tiles_bind_group",
&tiles_chunk_pipeline.tiles_bind_groups.mesh_layout,
&BindGroupEntries::single(binding),
),
});
}
pub value: Option<BindGroup>,
}
54 changes: 43 additions & 11 deletions crates/bevy_tiles_render/src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,39 +17,71 @@ use bevy::{
utils::FloatOrd,
};

use crate::{draw::DrawTiles, pipeline::TilesChunkPipeline, tiles::TriThing};
use crate::{
draw::{DrawChunkBatch, LoadChunk},
pipeline::TilesChunkPipeline,
settings::ChunkRenderSettings,
tiles::TriThing,
};

pub fn queue_tri_things(
pub fn queue_chunks(
mut pipelines: ResMut<SpecializedRenderPipelines<TilesChunkPipeline>>,
colored_mesh2d_pipeline: Res<TilesChunkPipeline>,
transparent_draw_functions: Res<DrawFunctions<Transparent2d>>,
pipeline_cache: Res<PipelineCache>,
msaa: Res<Msaa>,
mut views: Query<(&mut RenderPhase<Transparent2d>, &ExtractedView)>,
mut views: Query<(Entity, &mut RenderPhase<Transparent2d>, &ExtractedView)>,
chunks: Query<Entity, With<TriThing>>,
chunk_render_settings: Res<ChunkRenderSettings>,
) {
for (mut transparent_phase, view) in &mut views {
for (view_id, mut transparent_phase, view) in &mut views {
let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples())
| Mesh2dPipelineKey::from_hdr(view.hdr)
| Mesh2dPipelineKey::from_primitive_topology(PrimitiveTopology::TriangleList);
let pipeline_id = pipelines.specialize(&pipeline_cache, &colored_mesh2d_pipeline, mesh_key);

let draw_tiles = transparent_draw_functions.read().id::<DrawTiles>();
let load_chunk = transparent_draw_functions.read().id::<LoadChunk>();
let draw_chunks = transparent_draw_functions.read().id::<DrawChunkBatch>();

let mut batch_size = 0;

// Queue all entities visible to that view
for chunk_id in chunks.iter() {
debug!("Drawing chunk: {:?}", chunk_id);
batch_size += 1;

transparent_phase.add(Transparent2d {
entity: chunk_id,
draw_function: draw_tiles,
draw_function: load_chunk,
pipeline: pipeline_id,
// The 2d render items are sorted according to their z value before rendering,
// in order to get correct transparency
sort_key: FloatOrd(10.0),
// This material is not batched
sort_key: FloatOrd(0.0),
batch_range: 0..1,
dynamic_offset: None,
});

if batch_size == chunk_render_settings.max_chunk_batch_size {
transparent_phase.add(Transparent2d {
entity: view_id,
draw_function: draw_chunks,
pipeline: pipeline_id,
sort_key: FloatOrd(0.0),
batch_range: 0..batch_size,
dynamic_offset: None,
});

batch_size = 0;
}
}

// Add one more draw call at the end
if batch_size > 0 {
transparent_phase.add(Transparent2d {
entity: view_id,
draw_function: draw_chunks,
pipeline: pipeline_id,
sort_key: FloatOrd(0.0),
batch_range: 0..batch_size,
dynamic_offset: None,
});
}
}
}
14 changes: 14 additions & 0 deletions crates/bevy_tiles_render/src/settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use bevy::ecs::system::Resource;

#[derive(Resource)]
pub struct ChunkRenderSettings {
pub max_chunk_batch_size: u32,
}

impl Default for ChunkRenderSettings {
fn default() -> Self {
Self {
max_chunk_batch_size: 128,
}
}
}

0 comments on commit 5b7f348

Please sign in to comment.