mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
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
3 changed files with 19 additions and 73 deletions
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
|
|
Loading…
Reference in a new issue