]> git.nega.tv - josh/narcissus/commitdiff
shark: Render UI with compute
authorJosh Simmons <josh@nega.tv>
Thu, 16 May 2024 18:29:37 +0000 (20:29 +0200)
committerJosh Simmons <josh@nega.tv>
Thu, 16 May 2024 18:29:37 +0000 (20:29 +0200)
title/shark-shaders/build.rs
title/shark-shaders/shaders/display_transform.comp.glsl
title/shark-shaders/shaders/ui.frag.glsl [deleted file]
title/shark-shaders/shaders/ui.vert.glsl [deleted file]
title/shark/src/main.rs
title/shark/src/pipelines/display_transform.rs
title/shark/src/pipelines/mod.rs
title/shark/src/pipelines/ui.rs [deleted file]

index 6b4848678f8c5ca674696fd636072a80ed7fbb7f..149caf14f4e85079c7fce94b62657279442f1147 100644 (file)
@@ -26,7 +26,7 @@ struct Shader {
     name: &'static str,
 }
 
-const SHADERS: [Shader; 5] = [
+const SHADERS: [Shader; 3] = [
     Shader {
         stage: ShaderStage::Vertex,
         name: "basic",
@@ -39,14 +39,6 @@ const SHADERS: [Shader; 5] = [
         stage: ShaderStage::Compute,
         name: "display_transform",
     },
-    Shader {
-        stage: ShaderStage::Vertex,
-        name: "ui",
-    },
-    Shader {
-        stage: ShaderStage::Fragment,
-        name: "ui",
-    },
 ];
 
 fn main() {
index 1b440dc3d531adc1ab0f10288949a0e3839fb170..e17c6e43e7bbee2cb7d524871060396851e119b5 100644 (file)
@@ -1,12 +1,50 @@
 #version 460
 
-layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+#extension GL_EXT_scalar_block_layout : require
+#extension GL_EXT_control_flow_attributes : require
+
+struct CachedGlyph {
+    uint x0;
+    uint x1;
+    uint y0;
+    uint y1;
+
+    float offset_x0;
+    float offset_x1;
+    float offset_y0;
+    float offset_y1;
+};
+
+struct GlyphInstance {
+    float x;
+    float y;
+    uint index;
+    uint color;
+};
+
+layout(std430, set = 0, binding = 0) uniform uniformBuffer {
+    uint screen_width;
+    uint screen_height;
+    uint atlas_width;
+    uint atlas_height;
+    uint num_primitives;
+};
+
+layout (set = 0, binding = 1, rgba16f) uniform readonly image2D render_target;
+layout (set = 0, binding = 2, rgba16f) uniform writeonly image2D swapchain_image;
 
-layout (set = 0, binding = 0) uniform sampler linear_sampler;
+layout (set = 0, binding = 3) uniform sampler bilinear_sampler;
 
-layout (set = 0, binding = 1) uniform texture3D tony_mc_mapface_lut;
-layout (set = 0, binding = 2, rgba16f) uniform readonly image2D render_target;
-layout (set = 0, binding = 3, rgba16f) uniform writeonly image2D swapchain_image;
+layout (set = 0, binding = 4) uniform texture2D glyph_atlas;
+layout (set = 0, binding = 5) uniform texture3D tony_mc_mapface_lut;
+
+layout(std430, set = 0, binding = 6) readonly buffer glyphBuffer {
+    CachedGlyph cached_glyphs[];
+};
+
+layout(std430, set = 0, binding = 7) readonly buffer glyphInstanceBuffer {
+    GlyphInstance glyph_instances[];
+};
 
 float srgb_oetf(float a) {
     return (.0031308f >= a) ? 12.92f * a : 1.055f * pow(a, .4166666666666667f) - .055f;
@@ -20,11 +58,37 @@ vec3 tony_mc_mapface(vec3 stimulus) {
     const vec3 encoded = stimulus / (stimulus + 1.0);
     const float LUT_DIMS = 48.0;
     const vec3 uv = (encoded * ((LUT_DIMS - 1.0) / LUT_DIMS) + 0.5 / LUT_DIMS);
-    return textureLod(sampler3D(tony_mc_mapface_lut, linear_sampler), uv, 0.0).rgb;
+    return textureLod(sampler3D(tony_mc_mapface_lut, bilinear_sampler), uv, 0.0).rgb;
 }
 
+layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+
 void main() {
+    vec4 accum = vec4(0.0);
+
+    for (int i = 0; i < num_primitives; i++) {
+        const GlyphInstance gi = glyph_instances[i];
+        const CachedGlyph cg = cached_glyphs[gi.index];
+        const vec4 color = unpackUnorm4x8(gi.color).bgra;
+        const vec2 glyph_top_left = vec2(gi.x + cg.offset_x0, gi.y + cg.offset_y0);
+        const vec2 glyph_bottom_right = vec2(gi.x + cg.offset_x1, gi.y + cg.offset_y1);
+        const vec2 glyph_size = vec2(cg.offset_x1 - cg.offset_x0, cg.offset_y1 - cg.offset_y0);
+        const vec2 sample_center = gl_GlobalInvocationID.xy; // half pixel offset goes here?
+        if (sample_center.x >= glyph_top_left.x &&
+            sample_center.x <= glyph_bottom_right.x &&
+            sample_center.y >= glyph_top_left.y &&
+            sample_center.y <= glyph_bottom_right.y) {
+            const vec2 uv = mix(vec2(cg.x0, cg.y0), vec2(cg.x1, cg.y1), (sample_center - glyph_top_left) / glyph_size) / vec2(atlas_width, atlas_height);
+            const float coverage = textureLod(sampler2D(glyph_atlas, bilinear_sampler), uv, 0.0).r;
+            accum = coverage * color;
+            accum.a = coverage;
+            break;
+        }
+    }
+
     vec3 stimulus = imageLoad(render_target, ivec2(gl_GlobalInvocationID.xy)).rgb;
-    vec3 srgb = srgb_oetf(tony_mc_mapface(stimulus));
-    imageStore(swapchain_image, ivec2(gl_GlobalInvocationID.xy), vec4(srgb, 1.0));
+    vec3 transformed = tony_mc_mapface(stimulus);
+    vec3 srgb = srgb_oetf(transformed);
+    vec3 composited = accum.rgb + (srgb * (1.0 - accum.a));
+    imageStore(swapchain_image, ivec2(gl_GlobalInvocationID.xy), vec4(composited, 1.0));
 }
diff --git a/title/shark-shaders/shaders/ui.frag.glsl b/title/shark-shaders/shaders/ui.frag.glsl
deleted file mode 100644 (file)
index 26af4ae..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#version 460
-
-layout(set = 0, binding = 4) uniform sampler linear_sampler;
-layout(set = 0, binding = 5) uniform texture2D tex;
-
-layout(location = 0) in vec2 texcoord;
-layout(location = 1) in vec4 color;
-layout(location = 0) out vec4 outColor;
-
-void main() {
-    float coverage = texture(sampler2D(tex, linear_sampler), texcoord).r;
-    outColor = color * coverage;
-}
diff --git a/title/shark-shaders/shaders/ui.vert.glsl b/title/shark-shaders/shaders/ui.vert.glsl
deleted file mode 100644 (file)
index 9d83d06..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-#version 460
-
-#extension GL_EXT_scalar_block_layout : require
-
-struct CachedGlyph {
-    uint x0;
-    uint x1;
-    uint y0;
-    uint y1;
-
-    float offset_x0;
-    float offset_x1;
-    float offset_y0;
-    float offset_y1;
-};
-
-struct GlyphInstance {
-    float x;
-    float y;
-    uint index;
-    uint color;
-};
-
-layout(std430, set = 0, binding = 0) uniform uniformBuffer {
-    uint screen_width;
-    uint screen_height;
-    uint atlas_width;
-    uint atlas_height;
-};
-
-layout(std430, set = 0, binding = 1) readonly buffer primitiveBuffer {
-    uint primitive_vertices[];
-};
-
-layout(std430, set = 0, binding = 2) readonly buffer glyphBuffer {
-    CachedGlyph cached_glyphs[];
-};
-
-layout(std430, set = 0, binding = 3) readonly buffer glyphInstanceBuffer {
-    GlyphInstance glyph_instances[];
-};
-
-layout(location = 0) out vec2 out_texcoord;
-layout(location = 1) out flat vec4 out_color;
-
-void main() {
-    uint primitive_packed = primitive_vertices[gl_VertexIndex];
-    uint primitive_kind = bitfieldExtract(primitive_packed, 26, 6);
-    uint primitive_data = bitfieldExtract(primitive_packed, 24, 2);
-    uint instance_index = bitfieldExtract(primitive_packed, 0, 24);
-
-    GlyphInstance gi = glyph_instances[instance_index];
-    CachedGlyph cg = cached_glyphs[gi.index];
-
-    vec2 positions[4] = {
-        vec2(cg.offset_x0, cg.offset_y0),
-        vec2(cg.offset_x0, cg.offset_y1),
-        vec2(cg.offset_x1, cg.offset_y0),
-        vec2(cg.offset_x1, cg.offset_y1)
-    };
-
-    vec2 position = positions[primitive_data];
-    vec2 half_screen_size = vec2(screen_width, screen_height) / 2.0;
-    vec2 glyph_position = vec2(gi.x, gi.y);
-    vec2 vertex_position = (position + glyph_position) / half_screen_size - 1.0;
-    gl_Position = vec4(vertex_position, 0.0, 1.0);
-
-    vec2 texcoords[4] = {
-        vec2(cg.x0, cg.y0),
-        vec2(cg.x0, cg.y1),
-        vec2(cg.x1, cg.y0),
-        vec2(cg.x1, cg.y1)
-    };
-
-    vec2 texcoord = texcoords[primitive_data];
-    vec4 color = unpackUnorm4x8(gi.color).bgra;
-
-    out_texcoord = texcoord / vec2(atlas_width, atlas_height);
-    out_color = color;
-}
index dcabd7c867767a14d69b2d62e42ddc1cbdbb5f96..5aec15b79c317daab5e81dde41d9418d0c933acd 100644 (file)
@@ -24,12 +24,11 @@ use narcissus_image as image;
 use narcissus_maths::{
     clamp, perlin_noise3, sin_pi_f32, vec3, Affine3, Deg, HalfTurn, Mat3, Mat4, Point3, Vec3,
 };
-use pipelines::{
-    BasicPipeline, BasicUniforms, DisplayTransformPipeline, PrimitiveInstance, PrimitiveVertex,
-    UiPipeline,
-};
+use pipelines::{BasicPipeline, BasicUniforms, DisplayTransformPipeline, PrimitiveInstance};
 use spring::simple_spring_damper_exact;
 
+use crate::pipelines::DisplayTransformUniforms;
+
 mod fonts;
 mod helpers;
 mod pipelines;
@@ -450,7 +449,6 @@ struct UiState<'a> {
     tmp_string: String,
 
     primitive_instances: Vec<PrimitiveInstance>,
-    primitive_vertices: Vec<PrimitiveVertex>,
 }
 
 impl<'a> UiState<'a> {
@@ -463,7 +461,6 @@ impl<'a> UiState<'a> {
             glyph_cache,
             tmp_string: default(),
             primitive_instances: vec![],
-            primitive_vertices: vec![],
         }
     }
 
@@ -507,22 +504,12 @@ impl<'a> UiState<'a> {
 
             x += advance * scale;
 
-            let instance_index = self.primitive_instances.len() as u32;
             self.primitive_instances.push(PrimitiveInstance {
                 x,
                 y,
                 touched_glyph_index,
                 color: 0xff000000,
             });
-            let glyph_vertices = &[
-                PrimitiveVertex::glyph(0, instance_index),
-                PrimitiveVertex::glyph(1, instance_index),
-                PrimitiveVertex::glyph(2, instance_index),
-                PrimitiveVertex::glyph(2, instance_index),
-                PrimitiveVertex::glyph(1, instance_index),
-                PrimitiveVertex::glyph(3, instance_index),
-            ];
-            self.primitive_vertices.extend_from_slice(glyph_vertices);
 
             x += advance_width * scale;
         }
@@ -853,7 +840,6 @@ struct DrawState<'gpu> {
     gpu: &'gpu Gpu,
 
     basic_pipeline: BasicPipeline,
-    ui_pipeline: UiPipeline,
     display_transform_pipeline: DisplayTransformPipeline,
 
     width: u32,
@@ -874,8 +860,7 @@ struct DrawState<'gpu> {
 impl<'gpu> DrawState<'gpu> {
     fn new(gpu: &'gpu Gpu, thread_token: &ThreadToken) -> Self {
         let basic_pipeline = BasicPipeline::new(gpu);
-        let ui_pipeline = UiPipeline::new(gpu);
-        let primitive_pipeline = DisplayTransformPipeline::new(gpu);
+        let display_transform_pipeline = DisplayTransformPipeline::new(gpu);
 
         let samplers = Samplers::load(gpu);
         let models = Models::load(gpu);
@@ -884,8 +869,7 @@ impl<'gpu> DrawState<'gpu> {
         Self {
             gpu,
             basic_pipeline,
-            ui_pipeline,
-            display_transform_pipeline: primitive_pipeline,
+            display_transform_pipeline,
             width: 0,
             height: 0,
             depth_image: default(),
@@ -1232,100 +1216,6 @@ impl<'gpu> DrawState<'gpu> {
                 self.transforms.clear();
             }
 
-            // Render UI stuff.
-            {
-                let ui_uniforms = &pipelines::UiUniforms {
-                    screen_width: width,
-                    screen_height: height,
-                    atlas_width,
-                    atlas_height,
-                };
-                let primitive_vertices = ui_state.primitive_vertices.as_slice();
-                let primitive_instances = ui_state.primitive_instances.as_slice();
-                let uniforms_buffer = gpu.request_transient_buffer_with_data(
-                    frame,
-                    thread_token,
-                    BufferUsageFlags::UNIFORM,
-                    ui_uniforms,
-                );
-                let primitive_vertex_buffer = gpu.request_transient_buffer_with_data(
-                    frame,
-                    thread_token,
-                    BufferUsageFlags::STORAGE,
-                    primitive_vertices,
-                );
-                let cached_glyphs_buffer = gpu.request_transient_buffer_with_data(
-                    frame,
-                    thread_token,
-                    BufferUsageFlags::STORAGE,
-                    touched_glyphs,
-                );
-                let glyph_instance_buffer = gpu.request_transient_buffer_with_data(
-                    frame,
-                    thread_token,
-                    BufferUsageFlags::STORAGE,
-                    primitive_instances,
-                );
-
-                {
-                    gpu.cmd_set_pipeline(cmd_encoder, self.ui_pipeline.pipeline);
-                    gpu.cmd_set_bind_group(
-                        frame,
-                        cmd_encoder,
-                        self.ui_pipeline.bind_group_layout,
-                        0,
-                        &[
-                            Bind {
-                                binding: 0,
-                                array_element: 0,
-                                typed: TypedBind::UniformBuffer(&[uniforms_buffer.to_arg()]),
-                            },
-                            Bind {
-                                binding: 1,
-                                array_element: 0,
-                                typed: TypedBind::StorageBuffer(
-                                    &[primitive_vertex_buffer.to_arg()],
-                                ),
-                            },
-                            Bind {
-                                binding: 2,
-                                array_element: 0,
-                                typed: TypedBind::StorageBuffer(&[cached_glyphs_buffer.to_arg()]),
-                            },
-                            Bind {
-                                binding: 3,
-                                array_element: 0,
-                                typed: TypedBind::StorageBuffer(&[glyph_instance_buffer.to_arg()]),
-                            },
-                            Bind {
-                                binding: 4,
-                                array_element: 0,
-                                typed: TypedBind::Sampler(&[self.samplers[SamplerRes::Bilinear]]),
-                            },
-                            Bind {
-                                binding: 5,
-                                array_element: 0,
-                                typed: TypedBind::SampledImage(&[(
-                                    ImageLayout::Optimal,
-                                    self.glyph_atlas_image,
-                                )]),
-                            },
-                        ],
-                    );
-                };
-
-                gpu.cmd_draw(
-                    cmd_encoder,
-                    ui_state.primitive_vertices.len() as u32,
-                    1,
-                    0,
-                    0,
-                );
-
-                ui_state.primitive_instances.clear();
-                ui_state.primitive_vertices.clear();
-            }
-
             gpu.cmd_end_rendering(cmd_encoder);
 
             gpu.cmd_barrier(
@@ -1345,6 +1235,33 @@ impl<'gpu> DrawState<'gpu> {
 
             gpu.cmd_set_pipeline(cmd_encoder, self.display_transform_pipeline.pipeline);
 
+            let uniforms_buffer = gpu.request_transient_buffer_with_data(
+                frame,
+                thread_token,
+                BufferUsageFlags::UNIFORM,
+                &DisplayTransformUniforms {
+                    screen_width: width,
+                    screen_height: height,
+                    atlas_width,
+                    atlas_height,
+                    num_primitives: ui_state.primitive_instances.len() as u32,
+                },
+            );
+            let cached_glyphs_buffer = gpu.request_transient_buffer_with_data(
+                frame,
+                thread_token,
+                BufferUsageFlags::STORAGE,
+                touched_glyphs,
+            );
+            let glyph_instance_buffer = gpu.request_transient_buffer_with_data(
+                frame,
+                thread_token,
+                BufferUsageFlags::STORAGE,
+                ui_state.primitive_instances.as_slice(),
+            );
+
+            ui_state.primitive_instances.clear();
+
             gpu.cmd_set_bind_group(
                 frame,
                 cmd_encoder,
@@ -1354,28 +1271,51 @@ impl<'gpu> DrawState<'gpu> {
                     Bind {
                         binding: 0,
                         array_element: 0,
-                        typed: TypedBind::Sampler(&[self.samplers[SamplerRes::Bilinear]]),
+                        typed: TypedBind::UniformBuffer(&[uniforms_buffer.to_arg()]),
                     },
                     Bind {
                         binding: 1,
                         array_element: 0,
+                        typed: TypedBind::StorageImage(&[(
+                            ImageLayout::General,
+                            self.render_target_image,
+                        )]),
+                    },
+                    Bind {
+                        binding: 2,
+                        array_element: 0,
+                        typed: TypedBind::StorageImage(&[(ImageLayout::General, swapchain_image)]),
+                    },
+                    Bind {
+                        binding: 3,
+                        array_element: 0,
+                        typed: TypedBind::Sampler(&[self.samplers[SamplerRes::Bilinear]]),
+                    },
+                    Bind {
+                        binding: 4,
+                        array_element: 0,
                         typed: TypedBind::SampledImage(&[(
                             ImageLayout::Optimal,
-                            self.images[ImageRes::TonyMcMapfaceLut],
+                            self.glyph_atlas_image,
                         )]),
                     },
                     Bind {
-                        binding: 2,
+                        binding: 5,
                         array_element: 0,
-                        typed: TypedBind::StorageImage(&[(
-                            ImageLayout::General,
-                            self.render_target_image,
+                        typed: TypedBind::SampledImage(&[(
+                            ImageLayout::Optimal,
+                            self.images[ImageRes::TonyMcMapfaceLut],
                         )]),
                     },
                     Bind {
-                        binding: 3,
+                        binding: 6,
                         array_element: 0,
-                        typed: TypedBind::StorageImage(&[(ImageLayout::General, swapchain_image)]),
+                        typed: TypedBind::StorageBuffer(&[cached_glyphs_buffer.to_arg()]),
+                    },
+                    Bind {
+                        binding: 7,
+                        array_element: 0,
+                        typed: TypedBind::StorageBuffer(&[glyph_instance_buffer.to_arg()]),
                     },
                 ],
             );
@@ -1553,17 +1493,17 @@ pub fn main() {
 
             ui_state.text_fmt(
                 5.0,
-                30.0,
+                40.0,
                 FontFamily::RobotoRegular,
-                22.0,
+                30.0,
                 format_args!("tick: {:?}", tick_duration),
             );
 
             ui_state.text_fmt(
                 5.0,
-                60.0,
+                90.0,
                 FontFamily::NotoSansJapanese,
-                18.0,
+                30.0,
                 format_args!("ใŠๆกใ‚Š The Quick Brown Fox Jumped Over The Lazy Dog"),
             );
 
index f0c1e00c9e20cb3c403a85928b3ba19d8434d51e..9af1af6c81b4c65125be21974df29ca49882d6cb 100644 (file)
@@ -1,3 +1,4 @@
+use narcissus_font::TouchedGlyphIndex;
 use narcissus_gpu::{
     BindGroupLayout, BindGroupLayoutDesc, BindGroupLayoutEntryDesc, BindingType,
     ComputePipelineDesc, Pipeline, ShaderDesc, ShaderStageFlags,
@@ -8,8 +9,20 @@ use crate::Gpu;
 #[allow(unused)]
 #[repr(C)]
 pub struct DisplayTransformUniforms {
-    pub width: u32,
-    pub height: u32,
+    pub screen_width: u32,
+    pub screen_height: u32,
+    pub atlas_width: u32,
+    pub atlas_height: u32,
+    pub num_primitives: u32,
+}
+
+#[allow(unused)]
+#[repr(C)]
+pub struct PrimitiveInstance {
+    pub x: f32,
+    pub y: f32,
+    pub touched_glyph_index: TouchedGlyphIndex,
+    pub color: u32,
 }
 
 pub struct DisplayTransformPipeline {
@@ -22,27 +35,59 @@ impl DisplayTransformPipeline {
         let bind_group_layout = gpu.create_bind_group_layout(&BindGroupLayoutDesc {
             entries: &[
                 BindGroupLayoutEntryDesc {
+                    // uniforms
                     slot: 0,
                     stages: ShaderStageFlags::COMPUTE,
-                    binding_type: BindingType::Sampler,
+                    binding_type: BindingType::UniformBuffer,
                     count: 1,
                 },
                 BindGroupLayoutEntryDesc {
+                    // rt
                     slot: 1,
                     stages: ShaderStageFlags::COMPUTE,
-                    binding_type: BindingType::SampledImage,
+                    binding_type: BindingType::StorageImage,
                     count: 1,
                 },
                 BindGroupLayoutEntryDesc {
+                    // swapchain
                     slot: 2,
                     stages: ShaderStageFlags::COMPUTE,
                     binding_type: BindingType::StorageImage,
                     count: 1,
                 },
                 BindGroupLayoutEntryDesc {
+                    // sampler
                     slot: 3,
                     stages: ShaderStageFlags::COMPUTE,
-                    binding_type: BindingType::StorageImage,
+                    binding_type: BindingType::Sampler,
+                    count: 1,
+                },
+                BindGroupLayoutEntryDesc {
+                    // glyph atlas
+                    slot: 4,
+                    stages: ShaderStageFlags::COMPUTE,
+                    binding_type: BindingType::SampledImage,
+                    count: 1,
+                },
+                BindGroupLayoutEntryDesc {
+                    // lut
+                    slot: 5,
+                    stages: ShaderStageFlags::COMPUTE,
+                    binding_type: BindingType::SampledImage,
+                    count: 1,
+                },
+                BindGroupLayoutEntryDesc {
+                    // glyphs
+                    slot: 6,
+                    stages: ShaderStageFlags::COMPUTE,
+                    binding_type: BindingType::StorageBuffer,
+                    count: 1,
+                },
+                BindGroupLayoutEntryDesc {
+                    // glyph instances
+                    slot: 7,
+                    stages: ShaderStageFlags::COMPUTE,
+                    binding_type: BindingType::StorageBuffer,
                     count: 1,
                 },
             ],
index 02b802fede76affa24b8be5b68b6e7ddfaab019e..1e5732a60e398286be614d32d4d3452e109f3522 100644 (file)
@@ -1,9 +1,8 @@
 mod basic;
 mod display_transform;
-mod ui;
 
 pub use basic::{BasicPipeline, BasicUniforms, Vertex};
 
-pub use ui::{PrimitiveInstance, PrimitiveVertex, UiPipeline, UiUniforms};
-
-pub use display_transform::DisplayTransformPipeline;
+pub use display_transform::{
+    DisplayTransformPipeline, DisplayTransformUniforms, PrimitiveInstance,
+};
diff --git a/title/shark/src/pipelines/ui.rs b/title/shark/src/pipelines/ui.rs
deleted file mode 100644 (file)
index 85260f3..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-use narcissus_core::default;
-use narcissus_font::TouchedGlyphIndex;
-use narcissus_gpu::{
-    BindGroupLayout, BindGroupLayoutDesc, BindGroupLayoutEntryDesc, BindingType, BlendMode,
-    CompareOp, CullingMode, FrontFace, GraphicsPipelineDesc, GraphicsPipelineLayout, ImageFormat,
-    Pipeline, PolygonMode, ShaderDesc, ShaderStageFlags, Topology,
-};
-
-use crate::Gpu;
-
-#[allow(unused)]
-#[repr(C)]
-pub struct UiUniforms {
-    pub screen_width: u32,
-    pub screen_height: u32,
-    pub atlas_width: u32,
-    pub atlas_height: u32,
-}
-
-#[repr(u32)]
-pub enum PrimitiveKind {
-    Glyph,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy)]
-pub struct PrimitiveVertex(u32);
-
-impl PrimitiveVertex {
-    #[inline(always)]
-    pub fn glyph(corner: u32, index: u32) -> Self {
-        let kind = PrimitiveKind::Glyph as u32;
-        Self(kind << 26 | corner << 24 | index)
-    }
-}
-
-#[allow(unused)]
-#[repr(C)]
-pub struct PrimitiveInstance {
-    pub x: f32,
-    pub y: f32,
-    pub touched_glyph_index: TouchedGlyphIndex,
-    pub color: u32,
-}
-
-pub struct UiPipeline {
-    pub bind_group_layout: BindGroupLayout,
-    pub pipeline: Pipeline,
-}
-
-impl UiPipeline {
-    pub fn new(gpu: &Gpu) -> Self {
-        let bind_group_layout = gpu.create_bind_group_layout(&BindGroupLayoutDesc {
-            entries: &[
-                BindGroupLayoutEntryDesc {
-                    slot: 0,
-                    stages: ShaderStageFlags::ALL,
-                    binding_type: BindingType::UniformBuffer,
-                    count: 1,
-                },
-                BindGroupLayoutEntryDesc {
-                    slot: 1,
-                    stages: ShaderStageFlags::ALL,
-                    binding_type: BindingType::StorageBuffer,
-                    count: 1,
-                },
-                BindGroupLayoutEntryDesc {
-                    slot: 2,
-                    stages: ShaderStageFlags::ALL,
-                    binding_type: BindingType::StorageBuffer,
-                    count: 1,
-                },
-                BindGroupLayoutEntryDesc {
-                    slot: 3,
-                    stages: ShaderStageFlags::ALL,
-                    binding_type: BindingType::StorageBuffer,
-                    count: 1,
-                },
-                BindGroupLayoutEntryDesc {
-                    slot: 4,
-                    stages: ShaderStageFlags::ALL,
-                    binding_type: BindingType::Sampler,
-                    count: 1,
-                },
-                BindGroupLayoutEntryDesc {
-                    slot: 5,
-                    stages: ShaderStageFlags::ALL,
-                    binding_type: BindingType::SampledImage,
-                    count: 1,
-                },
-            ],
-        });
-
-        let pipeline = gpu.create_graphics_pipeline(&GraphicsPipelineDesc {
-            vertex_shader: ShaderDesc {
-                entry: c"main",
-                code: shark_shaders::UI_VERT_SPV,
-            },
-            fragment_shader: ShaderDesc {
-                entry: c"main",
-                code: shark_shaders::UI_FRAG_SPV,
-            },
-            bind_group_layouts: &[bind_group_layout],
-            layout: GraphicsPipelineLayout {
-                color_attachment_formats: &[ImageFormat::RGBA16_FLOAT],
-                depth_attachment_format: Some(ImageFormat::DEPTH_F32),
-                stencil_attachment_format: None,
-            },
-            topology: Topology::Triangles,
-            primitive_restart: false,
-            polygon_mode: PolygonMode::Fill,
-            culling_mode: CullingMode::None,
-            front_face: FrontFace::CounterClockwise,
-            blend_mode: BlendMode::Premultiplied,
-            depth_bias: None,
-            depth_compare_op: CompareOp::Always,
-            depth_test_enable: false,
-            depth_write_enable: false,
-            stencil_test_enable: false,
-            stencil_back: default(),
-            stencil_front: default(),
-        });
-
-        Self {
-            bind_group_layout,
-            pipeline,
-        }
-    }
-}