Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move the BufferBelt into a new crate blade-util #119

Merged
merged 1 commit into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ readme = "docs/README.md"
blade-asset = { version = "0.2", path = "blade-asset" }
blade-egui = { version = "0.3", path = "blade-egui" }
blade-graphics = { version = "0.4", path = "blade-graphics" }
blade-util = { version = "0.1", path = "blade-util" }
base64 = { workspace = true }
choir = { workspace = true }
colorsys = "0.6"
Expand Down
7 changes: 4 additions & 3 deletions blade-egui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ repository = "https://github.com/kvark/blade"
[lib]

[dependencies]
blade-graphics = { version = "0.4", path = "../blade-graphics"}
blade-macros = { version = "0.2", path = "../blade-macros"}
bytemuck = { workspace = true }
blade-graphics = { version = "0.4", path = "../blade-graphics" }
blade-macros = { version = "0.2", path = "../blade-macros" }
blade-util = { version = "0.1", path = "../blade-util" }
egui = { workspace = true, features = ["bytemuck"] }
bytemuck = { workspace = true }
profiling = { workspace = true }

[package.metadata.cargo_check_external_types]
Expand Down
92 changes: 0 additions & 92 deletions blade-egui/src/belt.rs

This file was deleted.

13 changes: 6 additions & 7 deletions blade-egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,9 @@
clippy::pattern_type_mismatch,
)]

mod belt;

const SHADER_SOURCE: &'static str = include_str!("../shader.wgsl");

use belt::{BeltDescriptor, BufferBelt};
use blade_util::{BufferBelt, BufferBeltDescriptor};
use std::{
collections::hash_map::{Entry, HashMap},
mem, ptr,
Expand Down Expand Up @@ -144,9 +142,10 @@ impl GuiPainter {
}],
});

let belt = BufferBelt::new(BeltDescriptor {
let belt = BufferBelt::new(BufferBeltDescriptor {
memory: blade_graphics::Memory::Shared,
min_chunk_size: 0x1000,
alignment: 4,
});

let sampler = context.create_sampler(blade_graphics::SamplerDesc {
Expand Down Expand Up @@ -197,7 +196,7 @@ impl GuiPainter {
let mut copies = Vec::new();
for &(texture_id, ref image_delta) in textures_delta.set.iter() {
let src = match image_delta.image {
egui::ImageData::Color(ref c) => self.belt.alloc_data(c.pixels.as_slice(), context),
egui::ImageData::Color(ref c) => self.belt.alloc_pod(c.pixels.as_slice(), context),
egui::ImageData::Font(ref a) => {
let color_iter = a.srgba_pixels(None);
let stage = self.belt.alloc(
Expand Down Expand Up @@ -323,8 +322,8 @@ impl GuiPainter {

if let egui::epaint::Primitive::Mesh(ref mesh) = clipped_prim.primitive {
let texture = self.textures.get(&mesh.texture_id).unwrap();
let index_buf = self.belt.alloc_data(&mesh.indices, context);
let vertex_buf = self.belt.alloc_data(&mesh.vertices, context);
let index_buf = self.belt.alloc_pod(&mesh.indices, context);
let vertex_buf = self.belt.alloc_pod(&mesh.vertices, context);

pc.bind(
1,
Expand Down
19 changes: 19 additions & 0 deletions blade-util/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[package]
name = "blade-util"
version = "0.1.0"
edition = "2021"
description = "Utility logic for Blade applications"
keywords = ["graphics"]
license = "MIT"
repository = "https://github.com/kvark/blade"

[lib]

[dependencies]
blade-graphics = { version = "0.4", path = "../blade-graphics" }
bytemuck = { workspace = true }
log = { workspace = true }
profiling = { workspace = true }

[package.metadata.cargo_check_external_types]
allowed_external_types = ["blade_graphics::*"]
Empty file added blade-util/README.md
Empty file.
127 changes: 127 additions & 0 deletions blade-util/src/belt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use blade_graphics as gpu;
use std::mem;

struct ReusableBuffer {
raw: gpu::Buffer,
size: u64,
}

/// Configuration of the Blade belt.
pub struct BufferBeltDescriptor {
/// Kind of memory to allocate from.
pub memory: gpu::Memory,
pub min_chunk_size: u64,
pub alignment: u64,
}

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

impl BufferBelt {
/// Create a new belt.
pub fn new(desc: BufferBeltDescriptor) -> Self {
assert_ne!(desc.alignment, 0);
Self {
desc,
buffers: Vec::new(),
active: Vec::new(),
}
}

/// Destroy this belt.
pub fn destroy(&mut self, gpu: &gpu::Context) {
for (buffer, _) in self.buffers.drain(..) {
gpu.destroy_buffer(buffer.raw);
}
for (buffer, _) in self.active.drain(..) {
gpu.destroy_buffer(buffer.raw);
}
}

/// Allocate a region of `size` bytes.
#[profiling::function]
pub fn alloc(&mut self, size: u64, gpu: &gpu::Context) -> gpu::BufferPiece {
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 {
let piece = rb.raw.at(aligned);
*offset = aligned + size;
return piece;
}
}

let index_maybe = self
.buffers
.iter()
.position(|(rb, sp)| size <= rb.size && gpu.wait_for(sp, 0));
if let Some(index) = index_maybe {
let (rb, _) = self.buffers.remove(index);
let piece = rb.raw.into();
self.active.push((rb, size));
return piece;
}

let chunk_index = self.buffers.len() + self.active.len();
let chunk_size = size.max(self.desc.min_chunk_size);
let chunk = gpu.create_buffer(gpu::BufferDesc {
name: &format!("chunk-{}", chunk_index),
size: chunk_size,
memory: self.desc.memory,
});
let rb = ReusableBuffer {
raw: chunk,
size: chunk_size,
};
self.active.push((rb, size));
chunk.into()
}

/// Allocate a region to hold the byte `data` slice contents.
pub unsafe fn alloc_bytes<T>(&mut self, data: &[u8], gpu: &gpu::Context) -> gpu::BufferPiece {
assert!(!data.is_empty());
let bp = self.alloc(data.len() as u64, gpu);
unsafe {
std::ptr::copy_nonoverlapping(data.as_ptr(), bp.data(), data.len());
}
bp
}

// 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 {
assert!(!data.is_empty());
let type_alignment = mem::align_of::<T>() as u64;
debug_assert_eq!(
self.desc.alignment % type_alignment,
0,
"Type alignment {} is too big",
type_alignment
);
let total_bytes = std::mem::size_of_val(data);
let bp = self.alloc(total_bytes as u64, gpu);
unsafe {
std::ptr::copy_nonoverlapping(data.as_ptr() as *const u8, bp.data(), total_bytes);
}
bp
}

/// Allocate a region to hold the POD `data` slice contents.
pub fn alloc_pod<T: bytemuck::Pod>(
&mut self,
data: &[T],
gpu: &gpu::Context,
) -> gpu::BufferPiece {
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) {
self.buffers
.extend(self.active.drain(..).map(|(rb, _)| (rb, sp.clone())));
}
}
3 changes: 3 additions & 0 deletions blade-util/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod belt;

pub use belt::{BufferBelt, BufferBeltDescriptor};
20 changes: 11 additions & 9 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
Changelog for Blade

## blade-graphics-0.5, blade-macros-0.3, blade-egui-0.4 (TBD)
## blade-graphics-0.5, blade-macros-0.3, blade-egui-0.4, blade-util-0.1 (TBD)

- vertex buffers support
- surface configuration:
- transparency support
- option to disable exclusive fullscreen
- VK: using linear sRGB color space if available
- crate: `blade-util` for helper utilities
- graphics:
- vertex buffers support
- surface configuration:
- transparency support
- option to disable exclusive fullscreen
- VK: using linear sRGB color space if available
- GLES: support for storage buffer and compute
- GLES: scissor rects, able to run "particle" example
- fixed initial RAM consumption
- window API switched to raw-window-handle-0.6
- GLES: support for storage buffer and compute
- GLES: scissor rects, able to run "particle" example
- fixed initial RAM consumption

## blade-graphics-0.4, blade-render-0.3, blade-0.2 (22 Mar 2024)

Expand Down
16 changes: 8 additions & 8 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Blade Examples

| Example | graphics | macros | egui | asset | render | lib |
| --------- | ----------- | ------ | ------ | ------ | ------ | ------ |
| mini | :star: | | | | | |
| init | :star: | :star: | | | | |
| ray-query | :star: (RT) | :star: | | | | |
| particle | :star: | :star: | :star: | | | |
| scene | :star: (RT) | :star: | :star: | :star: | :star: | |
| vehicle | | | | | | :star: |
| Example | graphics | macros | util | egui | asset | render | lib |
| --------- | ----------- | ------ | ------ | ------ | ------ | ------ | ------ |
| mini | :star: | | | | | | |
| init | :star: | :star: | | | | | |
| ray-query | :star: (RT) | :star: | | | | | |
| particle | :star: | :star: | | :star: | | | |
| scene | :star: (RT) | :star: | | :star: | :star: | :star: | |
| vehicle | | | | | | | :star: |
Loading