Use RenderQueue in BufferVec (#2847)

Using RenderQueue in BufferVec allows removal of the staging buffer entirely, as well as removal of the SpriteNode.

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
This commit is contained in:
Robert Swain 2021-10-07 19:24:48 +00:00
parent bf19ddf191
commit 40fccd29ca
3 changed files with 19 additions and 73 deletions

View file

@ -1,10 +1,12 @@
use crate::{render_resource::Buffer, renderer::RenderDevice};
use crate::{
render_resource::Buffer,
renderer::{RenderDevice, RenderQueue},
};
use bevy_core::{cast_slice, Pod};
use wgpu::BufferUsage;
pub struct BufferVec<T: Pod> {
values: Vec<T>,
staging_buffer: Option<Buffer>,
buffer: Option<Buffer>,
capacity: usize,
item_size: usize,
@ -15,7 +17,6 @@ impl<T: Pod> Default for BufferVec<T> {
fn default() -> Self {
Self {
values: Vec::new(),
staging_buffer: None,
buffer: None,
capacity: 0,
buffer_usage: BufferUsage::all(),
@ -31,10 +32,6 @@ impl<T: Pod> BufferVec<T> {
..Default::default()
}
}
#[inline]
pub fn staging_buffer(&self) -> Option<&Buffer> {
self.staging_buffer.as_ref()
}
#[inline]
pub fn buffer(&self) -> Option<&Buffer> {
@ -47,10 +44,10 @@ impl<T: Pod> BufferVec<T> {
}
pub fn push(&mut self, value: T) -> usize {
if self.values.len() < self.capacity {
let index = self.values.len();
let len = self.values.len();
if len < self.capacity {
self.values.push(value);
index
len
} else {
panic!(
"Cannot push value because capacity of {} has been reached",
@ -62,16 +59,10 @@ impl<T: Pod> BufferVec<T> {
pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
if capacity > self.capacity {
self.capacity = capacity;
let size = (self.item_size * capacity) as wgpu::BufferAddress;
self.staging_buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size,
usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE,
mapped_at_creation: false,
}));
let size = self.item_size * capacity;
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size,
size: size as wgpu::BufferAddress,
usage: BufferUsage::COPY_DST | self.buffer_usage,
mapped_at_creation: false,
}));
@ -83,28 +74,11 @@ impl<T: Pod> BufferVec<T> {
self.reserve(capacity, device);
}
pub fn write_to_staging_buffer(&self, render_device: &RenderDevice) {
if let Some(staging_buffer) = &self.staging_buffer {
let end = (self.values.len() * self.item_size) as u64;
let slice = staging_buffer.slice(0..end);
render_device.map_buffer(&slice, wgpu::MapMode::Write);
{
let mut data = slice.get_mapped_range_mut();
let bytes: &[u8] = cast_slice(&self.values);
data.copy_from_slice(bytes);
}
staging_buffer.unmap();
}
}
pub fn write_to_buffer(&self, command_encoder: &mut wgpu::CommandEncoder) {
if let (Some(staging_buffer), Some(uniform_buffer)) = (&self.staging_buffer, &self.buffer) {
command_encoder.copy_buffer_to_buffer(
staging_buffer,
0,
uniform_buffer,
0,
(self.values.len() * self.item_size) as u64,
);
pub fn write_buffer(&mut self, queue: &RenderQueue) {
if let Some(buffer) = &self.buffer {
let range = 0..self.item_size * self.values.len();
let bytes: &[u8] = cast_slice(&self.values);
queue.write_buffer(buffer, 0, &bytes[range]);
}
}

View file

@ -17,9 +17,7 @@ pub use texture_atlas_builder::*;
use bevy_app::prelude::*;
use bevy_asset::AddAsset;
use bevy_core_pipeline::Transparent2d;
use bevy_render2::{
render_graph::RenderGraph, render_phase::DrawFunctions, RenderApp, RenderStage,
};
use bevy_render2::{render_phase::DrawFunctions, RenderApp, RenderStage};
#[derive(Default)]
pub struct SpritePlugin;
@ -44,10 +42,5 @@ impl Plugin for SpritePlugin {
.unwrap()
.write()
.add(draw_sprite);
let mut graph = render_app.world.get_resource_mut::<RenderGraph>().unwrap();
graph.add_node("sprite", SpriteNode);
graph
.add_node_edge("sprite", bevy_core_pipeline::node::MAIN_PASS_DEPENDENCIES)
.unwrap();
}
}

View file

@ -12,10 +12,9 @@ use bevy_math::{Mat4, Vec2, Vec3, Vec4Swizzles};
use bevy_render2::{
mesh::{shape::Quad, Indices, Mesh, VertexAttributeValues},
render_asset::RenderAssets,
render_graph::{Node, NodeRunError, RenderGraphContext},
render_phase::{Draw, DrawFunctions, RenderPhase, TrackedRenderPass},
render_resource::*,
renderer::{RenderContext, RenderDevice},
renderer::{RenderDevice, RenderQueue},
shader::Shader,
texture::{BevyDefault, Image},
view::{ViewUniformOffset, ViewUniforms},
@ -246,6 +245,7 @@ impl Default for SpriteMeta {
pub fn prepare_sprites(
render_device: Res<RenderDevice>,
render_queue: Res<RenderQueue>,
mut sprite_meta: ResMut<SpriteMeta>,
mut extracted_sprites: Query<&mut ExtractedSprite>,
) {
@ -312,8 +312,8 @@ pub fn prepare_sprites(
}
}
sprite_meta.vertices.write_to_staging_buffer(&render_device);
sprite_meta.indices.write_to_staging_buffer(&render_device);
sprite_meta.vertices.write_buffer(&render_queue);
sprite_meta.indices.write_buffer(&render_queue);
}
#[derive(Default)]
@ -375,27 +375,6 @@ pub fn queue_sprites(
}
}
// TODO: this logic can be moved to prepare_sprites once wgpu::Queue is exposed directly
pub struct SpriteNode;
impl Node for SpriteNode {
fn run(
&self,
_graph: &mut RenderGraphContext,
render_context: &mut RenderContext,
world: &World,
) -> Result<(), NodeRunError> {
let sprite_buffers = world.get_resource::<SpriteMeta>().unwrap();
sprite_buffers
.vertices
.write_to_buffer(&mut render_context.command_encoder);
sprite_buffers
.indices
.write_to_buffer(&mut render_context.command_encoder);
Ok(())
}
}
pub struct DrawSprite {
params: SystemState<(
SRes<SpriteShaders>,