Skip to content

Commit

Permalink
Generic belt
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaslihotzki committed Jul 21, 2024
1 parent 710d54b commit 622f49c
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 43 deletions.
2 changes: 1 addition & 1 deletion blade-egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl GuiTexture {
pub struct GuiPainter {
pipeline: blade_graphics::RenderPipeline,
//TODO: find a better way to allocate temporary buffers.
belt: BufferBelt,
belt: BufferBelt<blade_graphics::Context>,
textures: HashMap<egui::TextureId, GuiTexture>,
//TODO: this could also look better
textures_dropped: Vec<GuiTexture>,
Expand Down
29 changes: 6 additions & 23 deletions blade-graphics/src/common/lib.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,12 @@
#[derive(Clone, Copy, Debug)]
pub struct BufferPiece {
pub buffer: Buffer,
pub offset: u64,
}

impl From<Buffer> for BufferPiece {
fn from(buffer: Buffer) -> Self {
Self { buffer, offset: 0 }
}
}

impl BufferPiece {
pub fn data(&self) -> *mut u8 {
let base = self.buffer.data();
assert!(!base.is_null());
unsafe { base.offset(self.offset as isize) }
}
}
pub type BufferPiece = crate::GenericBufferPiece<Buffer>;

// re-expose the trait methods as inherent impl for compatibility reasons.
impl Buffer {
pub fn at(self, offset: u64) -> BufferPiece {
BufferPiece {
buffer: self,
offset,
}
<Buffer as crate::traits::Buffer>::at(self, offset)
}
pub fn data(&self) -> *mut u8 {
<Buffer as crate::traits::Buffer>::data(self)
}
}

Expand Down
4 changes: 2 additions & 2 deletions blade-graphics/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ pub struct Buffer {
unsafe impl Send for Buffer {}
unsafe impl Sync for Buffer {}

impl Buffer {
pub fn data(&self) -> *mut u8 {
impl crate::traits::Buffer for Buffer {
fn data(&self) -> *mut u8 {
self.data
}
}
Expand Down
22 changes: 21 additions & 1 deletion blade-graphics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub mod gles;
)]
mod hal;
mod shader;
mod traits;
pub mod traits;
pub mod util;
pub mod limits {
pub const PLAIN_DATA_SIZE: u32 = 256;
Expand Down Expand Up @@ -143,6 +143,26 @@ pub struct BufferDesc<'a> {
pub memory: Memory,
}

#[derive(Clone, Copy, Debug)]
pub struct GenericBufferPiece<T: traits::Buffer> {
pub buffer: T,
pub offset: u64,
}

impl<T: traits::Buffer> GenericBufferPiece<T> {
pub fn data(&self) -> *mut u8 {
let base = self.buffer.data();
assert!(!base.is_null());
unsafe { base.offset(self.offset as isize) }
}
}

impl<T: traits::Buffer> From<T> for GenericBufferPiece<T> {
fn from(buffer: T) -> Self {
Self { buffer, offset: 0 }
}
}

pub type ResourceIndex = u32;
/// An array of resources to be used with shader bindings.
/// The generic argument tells the maximum number of resources.
Expand Down
13 changes: 12 additions & 1 deletion blade-graphics/src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{fmt::Debug, hash::Hash};
pub trait ResourceDevice {
type Buffer: Send + Sync + Clone + Copy + Debug + Hash + PartialEq;
type Buffer: Buffer;
type Texture: Send + Sync + Clone + Copy + Debug + Hash + PartialEq;
type TextureView: Send + Sync + Clone + Copy + Debug + Hash + PartialEq;
type Sampler: Send + Sync + Clone + Copy + Debug + Hash + PartialEq;
Expand Down Expand Up @@ -32,3 +32,14 @@ pub trait CommandDevice {
fn submit(&self, encoder: &mut Self::CommandEncoder) -> Self::SyncPoint;
fn wait_for(&self, sp: &Self::SyncPoint, timeout_ms: u32) -> bool;
}

pub trait Buffer: Send + Sync + Clone + Copy + Debug + Hash + PartialEq {
fn data(&self) -> *mut u8;

fn at(self, offset: u64) -> crate::GenericBufferPiece<Self> {
crate::GenericBufferPiece {
buffer: self,
offset,
}
}
}
4 changes: 2 additions & 2 deletions blade-graphics/src/vulkan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ impl Default for Buffer {
}
}

impl Buffer {
pub fn data(&self) -> *mut u8 {
impl crate::traits::Buffer for Buffer {
fn data(&self) -> *mut u8 {
self.mapped_data
}
}
Expand Down
31 changes: 18 additions & 13 deletions blade-util/src/belt.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use blade_graphics as gpu;
use std::mem;

struct ReusableBuffer {
raw: gpu::Buffer,
struct ReusableBuffer<B> {
raw: B,
size: u64,
}

Expand All @@ -16,13 +16,13 @@ pub struct BufferBeltDescriptor {

/// A belt of reusable buffer space.
/// Could be useful for temporary data, such as texture staging areas.
pub struct BufferBelt {
pub struct BufferBelt<D: gpu::traits::ResourceDevice + gpu::traits::CommandDevice> {
desc: BufferBeltDescriptor,
buffers: Vec<(ReusableBuffer, gpu::SyncPoint)>,
active: Vec<(ReusableBuffer, u64)>,
buffers: Vec<(ReusableBuffer<D::Buffer>, D::SyncPoint)>,
active: Vec<(ReusableBuffer<D::Buffer>, u64)>,
}

impl BufferBelt {
impl<D: gpu::traits::ResourceDevice + gpu::traits::CommandDevice> BufferBelt<D> {
/// Create a new belt.
pub fn new(desc: BufferBeltDescriptor) -> Self {
assert_ne!(desc.alignment, 0);
Expand All @@ -34,7 +34,7 @@ impl BufferBelt {
}

/// Destroy this belt.
pub fn destroy(&mut self, gpu: &gpu::Context) {
pub fn destroy(&mut self, gpu: &D) {
for (buffer, _) in self.buffers.drain(..) {
gpu.destroy_buffer(buffer.raw);
}
Expand All @@ -45,10 +45,11 @@ impl BufferBelt {

/// Allocate a region of `size` bytes.
#[profiling::function]
pub fn alloc(&mut self, size: u64, gpu: &gpu::Context) -> gpu::BufferPiece {
pub fn alloc(&mut self, size: u64, gpu: &D) -> gpu::GenericBufferPiece<D::Buffer> {
for &mut (ref rb, ref mut offset) in self.active.iter_mut() {
let aligned = offset.next_multiple_of(self.desc.alignment);
if aligned + size <= rb.size {
use gpu::traits::Buffer;
let piece = rb.raw.at(aligned);
*offset = aligned + size;
return piece;
Expand Down Expand Up @@ -82,7 +83,7 @@ impl BufferBelt {
}

/// Allocate a region to hold the byte `data` slice contents.
pub fn alloc_bytes(&mut self, data: &[u8], gpu: &gpu::Context) -> gpu::BufferPiece {
pub fn alloc_bytes(&mut self, data: &[u8], gpu: &D) -> gpu::GenericBufferPiece<D::Buffer> {
assert!(!data.is_empty());
let bp = self.alloc(data.len() as u64, gpu);
unsafe {
Expand All @@ -93,7 +94,11 @@ impl BufferBelt {

// SAFETY: T should be zeroable and ordinary data, no references, pointers, cells or other complicated data type.
/// Allocate a region to hold the typed `data` slice contents.
pub unsafe fn alloc_typed<T>(&mut self, data: &[T], gpu: &gpu::Context) -> gpu::BufferPiece {
pub unsafe fn alloc_typed<T>(
&mut self,
data: &[T],
gpu: &D,
) -> gpu::GenericBufferPiece<D::Buffer> {
assert!(!data.is_empty());
let type_alignment = mem::align_of::<T>() as u64;
debug_assert_eq!(
Expand All @@ -114,13 +119,13 @@ impl BufferBelt {
pub fn alloc_pod<T: bytemuck::Pod>(
&mut self,
data: &[T],
gpu: &gpu::Context,
) -> gpu::BufferPiece {
gpu: &D,
) -> gpu::GenericBufferPiece<D::Buffer> {
unsafe { self.alloc_typed(data, gpu) }
}

/// Mark the actively used buffers as used by GPU with a given sync point.
pub fn flush(&mut self, sp: &gpu::SyncPoint) {
pub fn flush(&mut self, sp: &D::SyncPoint) {
self.buffers
.extend(self.active.drain(..).map(|(rb, _)| (rb, sp.clone())));
}
Expand Down

0 comments on commit 622f49c

Please sign in to comment.