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:
parent
bf19ddf191
commit
40fccd29ca
@ -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 bevy_core::{cast_slice, Pod};
|
||||||
use wgpu::BufferUsage;
|
use wgpu::BufferUsage;
|
||||||
|
|
||||||
pub struct BufferVec<T: Pod> {
|
pub struct BufferVec<T: Pod> {
|
||||||
values: Vec<T>,
|
values: Vec<T>,
|
||||||
staging_buffer: Option<Buffer>,
|
|
||||||
buffer: Option<Buffer>,
|
buffer: Option<Buffer>,
|
||||||
capacity: usize,
|
capacity: usize,
|
||||||
item_size: usize,
|
item_size: usize,
|
||||||
@ -15,7 +17,6 @@ impl<T: Pod> Default for BufferVec<T> {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
values: Vec::new(),
|
values: Vec::new(),
|
||||||
staging_buffer: None,
|
|
||||||
buffer: None,
|
buffer: None,
|
||||||
capacity: 0,
|
capacity: 0,
|
||||||
buffer_usage: BufferUsage::all(),
|
buffer_usage: BufferUsage::all(),
|
||||||
@ -31,10 +32,6 @@ impl<T: Pod> BufferVec<T> {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
|
||||||
pub fn staging_buffer(&self) -> Option<&Buffer> {
|
|
||||||
self.staging_buffer.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn buffer(&self) -> Option<&Buffer> {
|
pub fn buffer(&self) -> Option<&Buffer> {
|
||||||
@ -47,10 +44,10 @@ impl<T: Pod> BufferVec<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, value: T) -> usize {
|
pub fn push(&mut self, value: T) -> usize {
|
||||||
if self.values.len() < self.capacity {
|
let len = self.values.len();
|
||||||
let index = self.values.len();
|
if len < self.capacity {
|
||||||
self.values.push(value);
|
self.values.push(value);
|
||||||
index
|
len
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
"Cannot push value because capacity of {} has been reached",
|
"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) {
|
pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
|
||||||
if capacity > self.capacity {
|
if capacity > self.capacity {
|
||||||
self.capacity = capacity;
|
self.capacity = capacity;
|
||||||
let size = (self.item_size * capacity) as wgpu::BufferAddress;
|
let size = self.item_size * capacity;
|
||||||
self.staging_buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
|
|
||||||
label: None,
|
|
||||||
size,
|
|
||||||
usage: BufferUsage::COPY_SRC | BufferUsage::MAP_WRITE,
|
|
||||||
mapped_at_creation: false,
|
|
||||||
}));
|
|
||||||
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
|
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
size,
|
size: size as wgpu::BufferAddress,
|
||||||
usage: BufferUsage::COPY_DST | self.buffer_usage,
|
usage: BufferUsage::COPY_DST | self.buffer_usage,
|
||||||
mapped_at_creation: false,
|
mapped_at_creation: false,
|
||||||
}));
|
}));
|
||||||
@ -83,28 +74,11 @@ impl<T: Pod> BufferVec<T> {
|
|||||||
self.reserve(capacity, device);
|
self.reserve(capacity, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_to_staging_buffer(&self, render_device: &RenderDevice) {
|
pub fn write_buffer(&mut self, queue: &RenderQueue) {
|
||||||
if let Some(staging_buffer) = &self.staging_buffer {
|
if let Some(buffer) = &self.buffer {
|
||||||
let end = (self.values.len() * self.item_size) as u64;
|
let range = 0..self.item_size * self.values.len();
|
||||||
let slice = staging_buffer.slice(0..end);
|
let bytes: &[u8] = cast_slice(&self.values);
|
||||||
render_device.map_buffer(&slice, wgpu::MapMode::Write);
|
queue.write_buffer(buffer, 0, &bytes[range]);
|
||||||
{
|
|
||||||
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,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,9 +17,7 @@ pub use texture_atlas_builder::*;
|
|||||||
use bevy_app::prelude::*;
|
use bevy_app::prelude::*;
|
||||||
use bevy_asset::AddAsset;
|
use bevy_asset::AddAsset;
|
||||||
use bevy_core_pipeline::Transparent2d;
|
use bevy_core_pipeline::Transparent2d;
|
||||||
use bevy_render2::{
|
use bevy_render2::{render_phase::DrawFunctions, RenderApp, RenderStage};
|
||||||
render_graph::RenderGraph, render_phase::DrawFunctions, RenderApp, RenderStage,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SpritePlugin;
|
pub struct SpritePlugin;
|
||||||
@ -44,10 +42,5 @@ impl Plugin for SpritePlugin {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.write()
|
.write()
|
||||||
.add(draw_sprite);
|
.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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,9 @@ use bevy_math::{Mat4, Vec2, Vec3, Vec4Swizzles};
|
|||||||
use bevy_render2::{
|
use bevy_render2::{
|
||||||
mesh::{shape::Quad, Indices, Mesh, VertexAttributeValues},
|
mesh::{shape::Quad, Indices, Mesh, VertexAttributeValues},
|
||||||
render_asset::RenderAssets,
|
render_asset::RenderAssets,
|
||||||
render_graph::{Node, NodeRunError, RenderGraphContext},
|
|
||||||
render_phase::{Draw, DrawFunctions, RenderPhase, TrackedRenderPass},
|
render_phase::{Draw, DrawFunctions, RenderPhase, TrackedRenderPass},
|
||||||
render_resource::*,
|
render_resource::*,
|
||||||
renderer::{RenderContext, RenderDevice},
|
renderer::{RenderDevice, RenderQueue},
|
||||||
shader::Shader,
|
shader::Shader,
|
||||||
texture::{BevyDefault, Image},
|
texture::{BevyDefault, Image},
|
||||||
view::{ViewUniformOffset, ViewUniforms},
|
view::{ViewUniformOffset, ViewUniforms},
|
||||||
@ -246,6 +245,7 @@ impl Default for SpriteMeta {
|
|||||||
|
|
||||||
pub fn prepare_sprites(
|
pub fn prepare_sprites(
|
||||||
render_device: Res<RenderDevice>,
|
render_device: Res<RenderDevice>,
|
||||||
|
render_queue: Res<RenderQueue>,
|
||||||
mut sprite_meta: ResMut<SpriteMeta>,
|
mut sprite_meta: ResMut<SpriteMeta>,
|
||||||
mut extracted_sprites: Query<&mut ExtractedSprite>,
|
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.vertices.write_buffer(&render_queue);
|
||||||
sprite_meta.indices.write_to_staging_buffer(&render_device);
|
sprite_meta.indices.write_buffer(&render_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[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 {
|
pub struct DrawSprite {
|
||||||
params: SystemState<(
|
params: SystemState<(
|
||||||
SRes<SpriteShaders>,
|
SRes<SpriteShaders>,
|
||||||
|
Loading…
Reference in New Issue
Block a user