GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
refactor: the wgpu API surface retires — cce_ui is Vulkan-only
With cce-cloud ported (the last hand-rolled wgpu client), WgpuAdapter,
the SHADER const + shader.wgsl (merged into vk/shader2d.wgsl earlier), and
Vertex's wgpu descriptor (ATTRIBS/desc) have no users left in the workspace.
wgpu and pollster leave the manifest as direct dependencies; wgpu remains in
the tree only transitively through glyphon, whose cosmic-text/swash re-exports
the text stage shapes with.
Full workspace builds; cce-ui/cce-cloud/cce-designer suites pass.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RFkXq68hDwVDMKnu9fckz3
Cargo.toml | 2 -
src/backend/mod.rs | 2 -
src/backend/wgpu_adapter.rs | 128 -------------------------------------------
src/backend/window_runner.rs | 16 ------
src/lib.rs | 1 -
src/shader.wgsl | 70 -----------------------
6 files changed, 219 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
index e6460ff..b81e0c6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,10 +9,8 @@ path = "src/lib.rs"
[dependencies]
raw-window-handle = "0.6"
-wgpu = "24"
glam = "0.29"
bytemuck = { version = "1", features = ["derive"] }
-pollster = "0.4"
glyphon = "0.8"
# Raw-Vulkan backend (versions match what wgpu 24 already pulls in).
ash = "0.38"
diff --git a/src/backend/mod.rs b/src/backend/mod.rs
index a796238..e8cad30 100644
--- a/src/backend/mod.rs
+++ b/src/backend/mod.rs
@@ -1,7 +1,5 @@
-pub mod wgpu_adapter;
pub mod window_runner;
-pub use wgpu_adapter::WgpuAdapter;
pub use window_runner::{
EngineState, WindowSettings, LogicalPosition, LogicalSize, Application, run,
Vertex, LineCap, PressedKey, get_text_buffer,
diff --git a/src/backend/wgpu_adapter.rs b/src/backend/wgpu_adapter.rs
deleted file mode 100644
index b8c2b8b..0000000
--- a/src/backend/wgpu_adapter.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-use crate::wayland::WaylandSurfaceHandle;
-use glyphon::{Cache, FontSystem, Resolution, SwashCache, TextAtlas, TextRenderer, Viewport};
-
-pub struct WgpuAdapter {
- pub instance: wgpu::Instance,
- pub surface: wgpu::Surface<'static>,
- pub adapter: wgpu::Adapter,
- pub device: wgpu::Device,
- pub queue: wgpu::Queue,
- pub config: wgpu::SurfaceConfiguration,
- pub font_system: FontSystem,
- pub swash_cache: SwashCache,
- pub text_atlas: TextAtlas,
- pub text_renderer: TextRenderer,
- pub text_viewport: Viewport,
-}
-
-impl WgpuAdapter {
- pub async fn new(
- display_ptr: *mut std::ffi::c_void,
- surface_ptr: *mut std::ffi::c_void,
- width: u32,
- height: u32,
- load_system_fonts: bool,
- ) -> Self {
- let wayland_handle = Box::leak(Box::new(WaylandSurfaceHandle {
- display_ptr,
- surface_ptr,
- }));
-
- let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
- backends: wgpu::Backends::VULKAN,
- ..Default::default()
- });
-
- let surface = instance
- .create_surface(wayland_handle)
- .expect("Failed to create surface");
-
- let adapter = instance
- .request_adapter(&wgpu::RequestAdapterOptions {
- power_preference: wgpu::PowerPreference::LowPower,
- compatible_surface: Some(&surface),
- force_fallback_adapter: false,
- })
- .await
- .expect("Failed to find adapter");
-
- let (device, queue) = adapter
- .request_device(
- &wgpu::DeviceDescriptor {
- label: Some("GPU Device"),
- required_features: wgpu::Features::empty(),
- required_limits: wgpu::Limits::downlevel_webgl2_defaults().using_resolution(adapter.limits()),
- memory_hints: wgpu::MemoryHints::MemoryUsage,
- },
- None,
- )
- .await
- .expect("Failed to create device");
-
- let mut config = surface
- .get_default_config(&adapter, width.max(1), height.max(1))
- .expect("Failed to get surface default config");
-
- let capabilities = surface.get_capabilities(&adapter);
- let alpha_mode = if capabilities.alpha_modes.contains(&wgpu::CompositeAlphaMode::PreMultiplied) {
- wgpu::CompositeAlphaMode::PreMultiplied
- } else if capabilities.alpha_modes.contains(&wgpu::CompositeAlphaMode::PostMultiplied) {
- wgpu::CompositeAlphaMode::PostMultiplied
- } else {
- capabilities.alpha_modes[0]
- };
- config.alpha_mode = alpha_mode;
- config.usage = wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_DST;
-
- let present_mode = if capabilities.present_modes.contains(&wgpu::PresentMode::Mailbox) {
- wgpu::PresentMode::Mailbox
- } else if capabilities.present_modes.contains(&wgpu::PresentMode::Immediate) {
- wgpu::PresentMode::Immediate
- } else if capabilities.present_modes.contains(&wgpu::PresentMode::FifoRelaxed) {
- wgpu::PresentMode::FifoRelaxed
- } else {
- wgpu::PresentMode::Fifo
- };
- config.present_mode = present_mode;
-
- surface.configure(&device, &config);
-
- // Initialize text rendering. The render FontSystem is bundled-fonts-only unless the
- // app opts into system fonts (Application::load_system_fonts — the font picker must
- // shape and rasterize every installed family).
- let font_system = if load_system_fonts {
- crate::create_font_system_with_system_fonts()
- } else {
- crate::create_font_system()
- };
- let swash_cache = SwashCache::new();
- let cache = Cache::new(&device);
- let mut text_atlas = TextAtlas::new(&device, &queue, &cache, config.format);
- let text_renderer = TextRenderer::new(&mut text_atlas, &device, wgpu::MultisampleState::default(), None);
- let mut text_viewport = Viewport::new(&device, &cache);
- text_viewport.update(&queue, Resolution { width: width.max(1), height: height.max(1) });
-
- Self {
- instance,
- surface,
- adapter,
- device,
- queue,
- config,
- font_system,
- swash_cache,
- text_atlas,
- text_renderer,
- text_viewport,
- }
- }
-
- pub fn resize(&mut self, width: u32, height: u32) {
- if width > 0 && height > 0 {
- self.config.width = width;
- self.config.height = height;
- self.surface.configure(&self.device, &self.config);
- self.text_viewport.update(&self.queue, Resolution { width, height });
- }
- }
-}
diff --git a/src/backend/window_runner.rs b/src/backend/window_runner.rs
index f2cb6e8..b6a4e5f 100644
--- a/src/backend/window_runner.rs
+++ b/src/backend/window_runner.rs
@@ -344,22 +344,6 @@ pub struct Vertex {
pub clip_circle: [f32; 3], // [cx, cy, r]
}
-impl Vertex {
- const ATTRIBS: [wgpu::VertexAttribute; 3] = wgpu::vertex_attr_array![
- 0 => Float32x2,
- 1 => Float32x4,
- 2 => Float32x3,
- ];
-
- pub fn desc() -> wgpu::VertexBufferLayout<'static> {
- wgpu::VertexBufferLayout {
- array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
- step_mode: wgpu::VertexStepMode::Vertex,
- attributes: &Self::ATTRIBS,
- }
- }
-}
-
pub fn quad_vertices(x: f32, y: f32, w: f32, h: f32, sw: f32, sh: f32, c: [f32; 4]) -> [Vertex; 6] {
let x0 = (x / sw) * 2.0 - 1.0;
let y0 = 1.0 - (y / sh) * 2.0;
diff --git a/src/lib.rs b/src/lib.rs
index 03db058..4e5a9cb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -18,7 +18,6 @@ pub mod colors {
pub use crate::color::*;
}
-pub const SHADER: &str = include_str!("shader.wgsl");
pub static IS_VERTICAL: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
pub static BAR_THICKNESS: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(24);
diff --git a/src/shader.wgsl b/src/shader.wgsl
deleted file mode 100644
index 1e12bbb..0000000
--- a/src/shader.wgsl
+++ /dev/null
@@ -1,70 +0,0 @@
-struct VertexOutput {
- @builtin(position) clip_position: vec4f,
- @location(0) color: vec4f,
- @location(1) ndc_position: vec2f,
- @location(2) is_background: f32,
- @location(3) clip_circle: vec3f,
-}
-
-@vertex
-fn vs_main(
- @location(0) position: vec2f,
- @location(1) color: vec4f,
- @location(2) clip_circle: vec3f,
-) -> VertexOutput {
- var out: VertexOutput;
- out.clip_position = vec4f(position, 0.0, 1.0);
- out.color = color;
- out.ndc_position = position;
- out.clip_circle = clip_circle;
-
- // Check if the vertex is exactly at the NDC boundaries (meaning it is the background quad)
- if (abs(position.x) > 0.999 && abs(position.y) > 0.999) {
- out.is_background = 1.0;
- } else {
- out.is_background = 0.0;
- }
-
- return out;
-}
-
-@fragment
-fn fs_main(in: VertexOutput) -> @location(0) vec4f {
- if (in.clip_circle.x == -999.0) {
- let y = length(vec2f(in.ndc_position.x, in.ndc_position.y));
- let x = atan2(in.ndc_position.y, in.ndc_position.x);
-
- // Wavy boundary radius with 7 lobes
- let R_theta = 0.60 + 0.06 * sin(7.0 * x);
-
- // Radial density: 1.0 at center, fading out to 0.0 at R_theta
- let density = 1.0 - smoothstep(R_theta - 0.25, R_theta, y);
-
- // Sine wave effect driven by the x value (distance around the circle)
- let sin_effect = sin(7.0 * x);
-
- // Normalized radius from 0.0 (center) to 1.0 (boundary)
- let r_normalized = clamp(y / R_theta, 0.0, 1.0);
-
- let gray = in.color.xyz;
-
- // Scale the ripple amplitude by the normalized radius to fade it out at the center
- let alpha = clamp(density * (1.0 - r_normalized * 0.25 * (1.0 - sin_effect)), 0.0, 1.0);
-
- if (y > R_theta + 0.02) {
- discard;
- }
-
- let final_alpha = alpha * (1.0 - smoothstep(R_theta - 0.02, R_theta + 0.02, y)) * in.color.w;
- return vec4f(gray, final_alpha);
- }
-
- if (in.clip_circle.z > 0.0) {
- let dx = in.clip_position.x - in.clip_circle.x;
- let dy = in.clip_position.y - in.clip_circle.y;
- if (dx * dx + dy * dy > in.clip_circle.z * in.clip_circle.z) {
- discard;
- }
- }
- return in.color;
-}