Detailed changes
@@ -1509,7 +1509,7 @@ dependencies = [
[[package]]
name = "blade-graphics"
version = "0.4.0"
-source = "git+https://github.com/kvark/blade?rev=9c9cabf69e869fc7d9aef2fc76f7d5c354d5710a#9c9cabf69e869fc7d9aef2fc76f7d5c354d5710a"
+source = "git+https://github.com/kvark/blade?rev=bdaf8c534fbbc9fbca71d1cf272f45640b3a068d#bdaf8c534fbbc9fbca71d1cf272f45640b3a068d"
dependencies = [
"ash",
"ash-window",
@@ -1539,13 +1539,24 @@ dependencies = [
[[package]]
name = "blade-macros"
version = "0.2.1"
-source = "git+https://github.com/kvark/blade?rev=9c9cabf69e869fc7d9aef2fc76f7d5c354d5710a#9c9cabf69e869fc7d9aef2fc76f7d5c354d5710a"
+source = "git+https://github.com/kvark/blade?rev=bdaf8c534fbbc9fbca71d1cf272f45640b3a068d#bdaf8c534fbbc9fbca71d1cf272f45640b3a068d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.59",
]
+[[package]]
+name = "blade-util"
+version = "0.1.0"
+source = "git+https://github.com/kvark/blade?rev=bdaf8c534fbbc9fbca71d1cf272f45640b3a068d#bdaf8c534fbbc9fbca71d1cf272f45640b3a068d"
+dependencies = [
+ "blade-graphics",
+ "bytemuck",
+ "log",
+ "profiling",
+]
+
[[package]]
name = "block"
version = "0.1.6"
@@ -3378,7 +3389,7 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
dependencies = [
- "libloading 0.8.0",
+ "libloading 0.7.4",
]
[[package]]
@@ -4689,6 +4700,7 @@ dependencies = [
"bindgen 0.65.1",
"blade-graphics",
"blade-macros",
+ "blade-util",
"block",
"bytemuck",
"calloop",
@@ -262,8 +262,9 @@ async-tar = "0.4.2"
async-trait = "0.1"
async_zip = { version = "0.0.17", features = ["deflate", "deflate64"] }
bitflags = "2.4.2"
-blade-graphics = { git = "https://github.com/kvark/blade", rev = "9c9cabf69e869fc7d9aef2fc76f7d5c354d5710a" }
-blade-macros = { git = "https://github.com/kvark/blade", rev = "9c9cabf69e869fc7d9aef2fc76f7d5c354d5710a" }
+blade-graphics = { git = "https://github.com/kvark/blade", rev = "bdaf8c534fbbc9fbca71d1cf272f45640b3a068d" }
+blade-macros = { git = "https://github.com/kvark/blade", rev = "bdaf8c534fbbc9fbca71d1cf272f45640b3a068d" }
+blade-util = { git = "https://github.com/kvark/blade", rev = "bdaf8c534fbbc9fbca71d1cf272f45640b3a068d" }
cap-std = "3.0"
cargo_toml = "0.20"
chrono = { version = "0.4", features = ["serde"] }
@@ -14,7 +14,7 @@ workspace = true
default = []
test-support = ["backtrace", "collections/test-support", "util/test-support", "http/test-support"]
runtime_shaders = []
-macos-blade = ["blade-graphics", "blade-macros", "bytemuck"]
+macos-blade = ["blade-graphics", "blade-macros", "blade-util", "bytemuck"]
[lib]
path = "src/gpui.rs"
@@ -26,6 +26,7 @@ async-task = "4.7"
backtrace = { version = "0.3", optional = true }
blade-graphics = { workspace = true, optional = true }
blade-macros = { workspace = true, optional = true }
+blade-util = { workspace = true, optional = true }
bytemuck = { version = "1", optional = true }
collections.workspace = true
ctor.workspace = true
@@ -96,6 +97,7 @@ flume = "0.11"
#TODO: use these on all platforms
blade-graphics.workspace = true
blade-macros.workspace = true
+blade-util.workspace = true
bytemuck = "1"
cosmic-text = "0.11.2"
copypasta = "0.10.1"
@@ -1,8 +1,5 @@
mod blade_atlas;
-mod blade_belt;
mod blade_renderer;
pub(crate) use blade_atlas::*;
pub(crate) use blade_renderer::*;
-
-use blade_belt::*;
@@ -1,10 +1,10 @@
-use super::{BladeBelt, BladeBeltDescriptor};
use crate::{
AtlasKey, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, DevicePixels, PlatformAtlas,
Point, Size,
};
use anyhow::Result;
use blade_graphics as gpu;
+use blade_util::{BufferBelt, BufferBeltDescriptor};
use collections::FxHashMap;
use etagere::BucketedAtlasAllocator;
use parking_lot::Mutex;
@@ -22,7 +22,7 @@ struct PendingUpload {
struct BladeAtlasState {
gpu: Arc<gpu::Context>,
- upload_belt: BladeBelt,
+ upload_belt: BufferBelt,
storage: BladeAtlasStorage,
tiles_by_key: FxHashMap<AtlasKey, AtlasTile>,
initializations: Vec<AtlasTextureId>,
@@ -48,7 +48,7 @@ impl BladeAtlas {
pub(crate) fn new(gpu: &Arc<gpu::Context>) -> Self {
BladeAtlas(Mutex::new(BladeAtlasState {
gpu: Arc::clone(gpu),
- upload_belt: BladeBelt::new(BladeBeltDescriptor {
+ upload_belt: BufferBelt::new(BufferBeltDescriptor {
memory: gpu::Memory::Upload,
min_chunk_size: 0x10000,
alignment: 64, // Vulkan `optimalBufferCopyOffsetAlignment` on Intel XE
@@ -212,7 +212,7 @@ impl BladeAtlasState {
}
fn upload_texture(&mut self, id: AtlasTextureId, bounds: Bounds<DevicePixels>, bytes: &[u8]) {
- let data = unsafe { self.upload_belt.alloc_data(bytes, &self.gpu) };
+ let data = self.upload_belt.alloc_bytes(bytes, &self.gpu);
self.uploads.push(PendingUpload { id, bounds, data });
}
@@ -1,101 +0,0 @@
-use blade_graphics as gpu;
-use std::mem;
-
-struct ReusableBuffer {
- raw: gpu::Buffer,
- size: u64,
-}
-
-pub struct BladeBeltDescriptor {
- pub memory: gpu::Memory,
- pub min_chunk_size: u64,
- pub alignment: u64,
-}
-
-/// A belt of buffers, used by the BladeAtlas to cheaply
-/// find staging space for uploads.
-pub struct BladeBelt {
- desc: BladeBeltDescriptor,
- buffers: Vec<(ReusableBuffer, gpu::SyncPoint)>,
- active: Vec<(ReusableBuffer, u64)>,
-}
-
-impl BladeBelt {
- pub fn new(desc: BladeBeltDescriptor) -> Self {
- assert_ne!(desc.alignment, 0);
- Self {
- desc,
- buffers: Vec::new(),
- active: Vec::new(),
- }
- }
-
- 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);
- }
- }
-
- #[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()
- }
-
- // SAFETY: T should be zeroable and ordinary data, no references, pointers, cells or other complicated data type.
- pub unsafe fn alloc_data<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
- }
-
- pub fn flush(&mut self, sp: &gpu::SyncPoint) {
- self.buffers
- .extend(self.active.drain(..).map(|(rb, _)| (rb, sp.clone())));
- }
-}
@@ -1,7 +1,7 @@
// Doing `if let` gives you nice scoping with passes/encoders
#![allow(irrefutable_let_patterns)]
-use super::{BladeAtlas, BladeBelt, BladeBeltDescriptor, PATH_TEXTURE_FORMAT};
+use super::{BladeAtlas, PATH_TEXTURE_FORMAT};
use crate::{
AtlasTextureKind, AtlasTile, Bounds, ContentMask, Hsla, MonochromeSprite, Path, PathId,
PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size,
@@ -15,6 +15,7 @@ use media::core_video::CVMetalTextureCache;
use std::{ffi::c_void, ptr::NonNull};
use blade_graphics as gpu;
+use blade_util::{BufferBelt, BufferBeltDescriptor};
use std::{mem, sync::Arc};
const MAX_FRAME_TIME_MS: u32 = 1000;
@@ -346,7 +347,7 @@ pub struct BladeRenderer {
command_encoder: gpu::CommandEncoder,
last_sync_point: Option<gpu::SyncPoint>,
pipelines: BladePipelines,
- instance_belt: BladeBelt,
+ instance_belt: BufferBelt,
path_tiles: HashMap<PathId, AtlasTile>,
atlas: Arc<BladeAtlas>,
atlas_sampler: gpu::Sampler,
@@ -371,7 +372,7 @@ impl BladeRenderer {
buffer_count: 2,
});
let pipelines = BladePipelines::new(&gpu, surface_info);
- let instance_belt = BladeBelt::new(BladeBeltDescriptor {
+ let instance_belt = BufferBelt::new(BufferBeltDescriptor {
memory: gpu::Memory::Shared,
min_chunk_size: 0x1000,
alignment: 0x40, // Vulkan `minStorageBufferOffsetAlignment` on Intel Xe
@@ -492,7 +493,7 @@ impl BladeRenderer {
pad: 0,
};
- let vertex_buf = unsafe { self.instance_belt.alloc_data(&vertices, &self.gpu) };
+ let vertex_buf = unsafe { self.instance_belt.alloc_typed(&vertices, &self.gpu) };
let mut pass = self.command_encoder.render(gpu::RenderTargetSet {
colors: &[gpu::RenderTarget {
view: tex_info.raw_view,
@@ -557,7 +558,7 @@ impl BladeRenderer {
match batch {
PrimitiveBatch::Quads(quads) => {
let instance_buf =
- unsafe { self.instance_belt.alloc_data(quads, &self.gpu) };
+ unsafe { self.instance_belt.alloc_typed(quads, &self.gpu) };
let mut encoder = pass.with(&self.pipelines.quads);
encoder.bind(
0,
@@ -570,7 +571,7 @@ impl BladeRenderer {
}
PrimitiveBatch::Shadows(shadows) => {
let instance_buf =
- unsafe { self.instance_belt.alloc_data(shadows, &self.gpu) };
+ unsafe { self.instance_belt.alloc_typed(shadows, &self.gpu) };
let mut encoder = pass.with(&self.pipelines.shadows);
encoder.bind(
0,
@@ -598,7 +599,7 @@ impl BladeRenderer {
}];
let instance_buf =
- unsafe { self.instance_belt.alloc_data(&sprites, &self.gpu) };
+ unsafe { self.instance_belt.alloc_typed(&sprites, &self.gpu) };
encoder.bind(
0,
&ShaderPathsData {
@@ -613,7 +614,7 @@ impl BladeRenderer {
}
PrimitiveBatch::Underlines(underlines) => {
let instance_buf =
- unsafe { self.instance_belt.alloc_data(underlines, &self.gpu) };
+ unsafe { self.instance_belt.alloc_typed(underlines, &self.gpu) };
let mut encoder = pass.with(&self.pipelines.underlines);
encoder.bind(
0,
@@ -630,7 +631,7 @@ impl BladeRenderer {
} => {
let tex_info = self.atlas.get_texture_info(texture_id);
let instance_buf =
- unsafe { self.instance_belt.alloc_data(sprites, &self.gpu) };
+ unsafe { self.instance_belt.alloc_typed(sprites, &self.gpu) };
let mut encoder = pass.with(&self.pipelines.mono_sprites);
encoder.bind(
0,
@@ -649,7 +650,7 @@ impl BladeRenderer {
} => {
let tex_info = self.atlas.get_texture_info(texture_id);
let instance_buf =
- unsafe { self.instance_belt.alloc_data(sprites, &self.gpu) };
+ unsafe { self.instance_belt.alloc_typed(sprites, &self.gpu) };
let mut encoder = pass.with(&self.pipelines.poly_sprites);
encoder.bind(
0,