Skip to content

Commit

Permalink
Try #3532:
Browse files Browse the repository at this point in the history
  • Loading branch information
bors[bot] authored Mar 14, 2022
2 parents a291b5a + b7be711 commit 7a0cb74
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 107 deletions.
7 changes: 3 additions & 4 deletions crates/bevy_pbr/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,7 @@ pub fn prepare_lights(
lights: view_lights,
},
ViewLightsUniformOffset {
offset: light_meta.view_gpu_lights.push(gpu_lights),
offset: light_meta.view_gpu_lights.push_and_get_offset(gpu_lights),
},
));
}
Expand Down Expand Up @@ -946,7 +946,7 @@ impl ViewClusterBindings {
let component = self.n_offsets & ((1 << 2) - 1);
let packed = pack_offset_and_count(offset, count);

self.cluster_offsets_and_counts.get_mut(0)[array_index][component] = packed;
self.cluster_offsets_and_counts[0][array_index][component] = packed;

self.n_offsets += 1;
}
Expand All @@ -961,8 +961,7 @@ impl ViewClusterBindings {
let sub_index = self.n_indices & ((1 << 2) - 1);
let index = index as u32 & POINT_LIGHT_INDEX_MASK;

self.cluster_light_index_lists.get_mut(0)[array_index][component] |=
index << (8 * sub_index);
self.cluster_light_index_lists[0][array_index][component] |= index << (8 * sub_index);

self.n_indices += 1;
}
Expand Down
78 changes: 45 additions & 33 deletions crates/bevy_render/src/render_resource/buffer_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ use crate::{
renderer::{RenderDevice, RenderQueue},
};
use bevy_core::{cast_slice, Pod};
use copyless::VecHelper;
use std::ops::{Deref, DerefMut};
use wgpu::BufferUsages;

/// A user-friendly wrapper around a [`Buffer`] that provides a `Vec`-like
/// interface for constructing the buffer.
pub struct BufferVec<T: Pod> {
values: Vec<T>,
buffer: Option<Buffer>,
capacity: usize,
item_size: usize,
buffer_usage: BufferUsages,
}

Expand All @@ -21,71 +22,82 @@ impl<T: Pod> Default for BufferVec<T> {
buffer: None,
capacity: 0,
buffer_usage: BufferUsages::all(),
item_size: std::mem::size_of::<T>(),
}
}
}

impl<T: Pod> BufferVec<T> {
/// Creates a new [`BufferVec`] with the associated [`BufferUsages`].
///
/// This does not immediately allocate a system/video RAM buffers.
pub fn new(buffer_usage: BufferUsages) -> Self {
Self {
buffer_usage,
..Default::default()
}
}

/// Gets the reference to the underlying buffer, if one has been allocated.
#[inline]
pub fn buffer(&self) -> Option<&Buffer> {
self.buffer.as_ref()
}

#[inline]
pub fn capacity(&self) -> usize {
self.capacity
}

#[inline]
pub fn len(&self) -> usize {
self.values.len()
/// Queues up a copy of the contents of the [`BufferVec`] into the underlying
/// buffer.
///
/// If no buffer has been allocated yet or if the current size of the contents
/// exceeds the size of the underlying buffer, a new buffer will be allocated.
pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
if self.values.is_empty() {
return;
}
self.reserve_buffer(self.values.len(), device);
if let Some(buffer) = &self.buffer {
let range = 0..self.size();
let bytes: &[u8] = cast_slice(&self.values);
queue.write_buffer(buffer, 0, &bytes[range]);
}
}

#[inline]
pub fn is_empty(&self) -> bool {
self.values.is_empty()
/// Consumes the [`BufferVec`] and returns the underlying [`Vec`].
/// If a buffer was allocated, it will be dropped.
pub fn take_vec(self) -> Vec<T> {
self.values
}

pub fn push(&mut self, value: T) -> usize {
let index = self.values.len();
self.values.alloc().init(value);
index
/// Consumes the [`BufferVec`] and returns the underlying [`Buffer`]
/// if one was allocated.
pub fn take_buffer(self) -> Option<Buffer> {
self.buffer
}

pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
fn reserve_buffer(&mut self, capacity: usize, device: &RenderDevice) {
if capacity > self.capacity {
self.capacity = capacity;
let size = self.item_size * capacity;
self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: size as wgpu::BufferAddress,
size: self.size() as wgpu::BufferAddress,
usage: BufferUsages::COPY_DST | self.buffer_usage,
mapped_at_creation: false,
}));
}
}

pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
if self.values.is_empty() {
return;
}
self.reserve(self.values.len(), device);
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]);
}
fn size(&self) -> usize {
std::mem::size_of::<T>() * self.values.len()
}
}

impl<T: Pod> Deref for BufferVec<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.values
}
}

pub fn clear(&mut self) {
self.values.clear();
impl<T: Pod> DerefMut for BufferVec<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.values
}
}
Loading

0 comments on commit 7a0cb74

Please sign in to comment.