diff --git a/core/src/render/mod.rs b/core/src/render/mod.rs index 12c5146..8a31049 100644 --- a/core/src/render/mod.rs +++ b/core/src/render/mod.rs @@ -364,9 +364,9 @@ impl UiRenderNode { }) } - /// One list's per-instance data. Per primitive with `stride` stated: a - /// `None` minimum is filled in from the first pipeline built against the - /// layout, so a shared one would hold every primitive to the largest. + /// One list's per-instance data. Each primitive needs its own, stating its + /// own `stride`: a `None` minimum takes its value from the first pipeline + /// built against the layout, and then holds every later one to that. fn data_layout(device: &Device, stride: u64) -> BindGroupLayout { device.create_bind_group_layout(&BindGroupLayoutDescriptor { entries: &[BindGroupLayoutEntry { @@ -383,8 +383,7 @@ impl UiRenderNode { }) } - /// The one image an instance samples. The sampler is shared, so there is - /// nothing else in here. + /// The image one instance samples. fn image_layout(device: &Device) -> BindGroupLayout { device.create_bind_group_layout(&BindGroupLayoutDescriptor { entries: &[BindGroupLayoutEntry { diff --git a/core/src/render/primitive.rs b/core/src/render/primitive.rs index 0f236da..1f43e47 100644 --- a/core/src/render/primitive.rs +++ b/core/src/render/primitive.rs @@ -1,7 +1,7 @@ use std::{any::TypeId, marker::PhantomData}; use crate::{ - Color, UiRegion, WidgetId, + Color, TextureHandle, UiRegion, WidgetId, render::data::{MaskIdx, PrimitiveInstance}, util::{HashMap, Vec2}, }; @@ -15,13 +15,12 @@ pub trait Primitive: Pod + 'static { /// Compiled after `prelude.wgsl`, which states what it declares and what /// it is given. const WGSL: &'static str; - /// Reads the image an instance samples, for a primitive that draws one. - /// Each instance is then a draw of its own, bound for it alone. + /// Reads the image an instance uses. Each instance is then a draw of its + /// own, with that image bound for it alone. const TEXTURE: Option u32> = None; } -/// Which registered primitive an instance is. Only `PrimitiveRegistry::kind` -/// mints one, so holding it is the proof that `P` has a list to go in. +/// Which registered primitive an instance is. pub struct PrimitiveKind

{ id: u32, _p: PhantomData, @@ -45,6 +44,7 @@ impl

Clone for PrimitiveKind

{ impl

Copy for PrimitiveKind

{} /// Every primitive a ui can draw, in the order they were first drawn. +#[derive(Default)] pub struct PrimitiveRegistry { kinds: Vec, ids: HashMap, @@ -59,21 +59,6 @@ pub struct PrimitiveSource { pub textured: bool, } -impl Default for PrimitiveRegistry { - /// The built-ins are registered up front rather than on first use, so that - /// what a ui happens to draw first cannot decide anything about them. - fn default() -> Self { - let mut registry = Self { - kinds: Vec::new(), - ids: HashMap::default(), - }; - registry.kind::(); - registry.kind::(); - registry.kind::(); - registry - } -} - impl PrimitiveRegistry { /// Registers `P` if this is the first time it has been drawn. pub fn kind(&mut self) -> PrimitiveKind

{ @@ -354,3 +339,11 @@ impl Primitive for TexturePrimitive { const WGSL: &'static str = include_str!("shader/texture.wgsl"); const TEXTURE: Option u32> = Some(|texture| texture.slot); } + +impl From<&TextureHandle> for TexturePrimitive { + fn from(handle: &TextureHandle) -> Self { + Self { + slot: handle.slot(), + } + } +} diff --git a/core/src/render/shader/glyph.wgsl b/core/src/render/shader/glyph.wgsl index 376b4fd..08029ff 100644 --- a/core/src/render/shader/glyph.wgsl +++ b/core/src/render/shader/glyph.wgsl @@ -1,6 +1,12 @@ // Matches `GlyphEntry::IS_COLORED`. const COLORED: u32 = 1u; +// The glyph atlas, whose array layers are its pages. +@group(0) @binding(2) +var atlas: texture_2d_array; +@group(0) @binding(3) +var samp: sampler; + struct GlyphInfo { uv_min: vec2, uv_max: vec2, diff --git a/core/src/render/shader/prelude.wgsl b/core/src/render/shader/prelude.wgsl index c967a24..013fe4b 100644 --- a/core/src/render/shader/prelude.wgsl +++ b/core/src/render/shader/prelude.wgsl @@ -1,17 +1,15 @@ // Prepended to every primitive's shader, which declares its own instance data // as `var : array` at group 1 binding 0, and an `fs_main` -// shading one instance of it. A primitive that samples an image of its own -// takes it at group 2 binding 0; see texture.wgsl. +// shading one instance of it. +// +// The rest of group 0 is bound for every draw but declared by the shaders that +// read it: the glyph atlas at binding 2 and the ui's sampler at binding 3. A +// primitive that samples an image of its own takes it at group 2 binding 0. @group(0) @binding(0) var window: WindowUniform; @group(0) @binding(1) var masks: array; -// The glyph atlas, whose array layers are its pages. -@group(0) @binding(2) -var atlas: texture_2d_array; -@group(0) @binding(3) -var samp: sampler; struct WindowUniform { dim: vec2, diff --git a/core/src/render/shader/texture.wgsl b/core/src/render/shader/texture.wgsl index e4e3cec..179d0a3 100644 --- a/core/src/render/shader/texture.wgsl +++ b/core/src/render/shader/texture.wgsl @@ -1,6 +1,8 @@ // The image this instance draws, bound for it alone. @group(2) @binding(0) var image: texture_2d; +@group(0) @binding(3) +var samp: sampler; @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4 { diff --git a/core/src/ui/painter.rs b/core/src/ui/painter.rs index 11139cb..d0496b5 100644 --- a/core/src/ui/painter.rs +++ b/core/src/ui/painter.rs @@ -28,8 +28,7 @@ impl<'a> Painter<'a> { self.write(kind, primitive, region); } - /// For a caller with many of one primitive to write, since looking the kind - /// up is per type rather than per instance. + /// Takes the kind, for a caller writing many of one primitive. fn write(&mut self, kind: PrimitiveKind

, primitive: P, region: UiRegion) { let h = self.state.layers.write( self.layer, @@ -98,14 +97,12 @@ impl<'a> Painter<'a> { self.texture_at(handle, self.region); } + /// A texture primitive, plus a share of the handle it names -- which a + /// `Pod` primitive cannot carry, and without which the slot could be + /// freed and reused while still drawn. pub fn texture_at(&mut self, handle: &TextureHandle, region: UiRegion) { self.textures.push(handle.clone()); - self.primitive_at( - TexturePrimitive { - slot: handle.slot(), - }, - region, - ); + self.primitive_at(TexturePrimitive::from(handle), region); } pub fn render_text(