Take a primitive's kind from its type, and keep images out of the rest
A `Primitive` now carries its own WGSL, and `PrimitiveRegistry` keys ids by `TypeId`, so `Painter::primitive` takes only the value and the `RECT`, `GLYPH` and `TEXTURE` constants are gone. Registering is what a first draw does; the built-ins are seeded up front so first-draw order cannot decide anything about them. What a primitive samples is no longer something every registration states. The glyph atlas and the one sampler moved into the shared group, which is where a mask texture would go too, so a rect's pipeline has no texture in its layout at all. Only a primitive whose type sets `TEXTURE` gets an image group, and that is also what records the slot at write time -- so nothing reads a `u32` back out of the instance payload. Verified on the headless rig: the tabs example, two images added at runtime, an image alone in a layer, and text spanning a four-layer atlas after the array grew twice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7b318e3271
commit
29d390da52
11 files changed
+268
-333
No files matched your search
+21
-21
@@ -2,10 +2,7 @@ use wgpu::*;
|
||||
|
||||
use crate::GlyphAtlas;
|
||||
|
||||
use super::{
|
||||
atlas::PAGE,
|
||||
texture::{array_view, texture_group, write_region},
|
||||
};
|
||||
use super::{atlas::PAGE, texture::write_region};
|
||||
|
||||
/// The glyph atlas on the GPU: one array texture whose layers are the pages
|
||||
/// `GlyphAtlas` packs.
|
||||
@@ -17,29 +14,25 @@ pub struct GpuPages {
|
||||
device: Device,
|
||||
queue: Queue,
|
||||
texture: Texture,
|
||||
group: BindGroup,
|
||||
view: TextureView,
|
||||
}
|
||||
|
||||
impl GpuPages {
|
||||
pub fn new(
|
||||
device: &Device,
|
||||
queue: &Queue,
|
||||
layout: &BindGroupLayout,
|
||||
sampler: &Sampler,
|
||||
) -> Self {
|
||||
pub fn new(device: &Device, queue: &Queue) -> Self {
|
||||
let texture = create_array(device, 1);
|
||||
let group = texture_group(device, layout, &array_view(&texture), sampler);
|
||||
Self {
|
||||
device: device.clone(),
|
||||
queue: queue.clone(),
|
||||
view: array_view(&texture),
|
||||
texture,
|
||||
group,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, atlas: &mut GlyphAtlas, layout: &BindGroupLayout, sampler: &Sampler) {
|
||||
if atlas.page_count() > self.texture.depth_or_array_layers() {
|
||||
self.grow(atlas.page_count(), layout, sampler);
|
||||
/// Returns whether the array was replaced, which stales the view.
|
||||
pub fn update(&mut self, atlas: &mut GlyphAtlas) -> bool {
|
||||
let grew = atlas.page_count() > self.texture.depth_or_array_layers();
|
||||
if grew {
|
||||
self.grow(atlas.page_count());
|
||||
}
|
||||
for (upload, page) in atlas.uploads() {
|
||||
let dst = TexelCopyTextureInfo {
|
||||
@@ -54,15 +47,15 @@ impl GpuPages {
|
||||
};
|
||||
write_region(&self.queue, dst, page, upload.rect);
|
||||
}
|
||||
grew
|
||||
}
|
||||
|
||||
pub fn group(&self) -> &BindGroup {
|
||||
&self.group
|
||||
pub fn view(&self) -> &TextureView {
|
||||
&self.view
|
||||
}
|
||||
|
||||
/// Doubles until `needed` fits and copies the old layers across GPU side.
|
||||
/// The new view invalidates the old group, so that is rebuilt here.
|
||||
fn grow(&mut self, needed: u32, layout: &BindGroupLayout, sampler: &Sampler) {
|
||||
fn grow(&mut self, needed: u32) {
|
||||
let old = self.texture.depth_or_array_layers();
|
||||
let mut layers = old;
|
||||
while layers < needed {
|
||||
@@ -84,11 +77,18 @@ impl GpuPages {
|
||||
},
|
||||
);
|
||||
self.queue.submit(std::iter::once(encoder.finish()));
|
||||
self.group = texture_group(&self.device, layout, &array_view(&texture), sampler);
|
||||
self.view = array_view(&texture);
|
||||
self.texture = texture;
|
||||
}
|
||||
}
|
||||
|
||||
fn array_view(texture: &Texture) -> TextureView {
|
||||
texture.create_view(&TextureViewDescriptor {
|
||||
dimension: Some(TextureViewDimension::D2Array),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
||||
fn create_array(device: &Device, layers: u32) -> Texture {
|
||||
device.create_texture(&TextureDescriptor {
|
||||
label: Some("glyph atlas"),
|
||||
|
||||
Reference in new issue
Block a user