From 3851fb6d2cf8c5d56ecb029a12476dd1d220c10b Mon Sep 17 00:00:00 2001 From: Josh Simmons Date: Thu, 16 May 2024 20:29:37 +0200 Subject: [PATCH] shark: Render UI with compute --- title/shark-shaders/build.rs | 10 +- .../shaders/display_transform.comp.glsl | 80 +++++++- title/shark-shaders/shaders/ui.frag.glsl | 13 -- title/shark-shaders/shaders/ui.vert.glsl | 80 -------- title/shark/src/main.rs | 194 ++++++------------ .../shark/src/pipelines/display_transform.rs | 55 ++++- title/shark/src/pipelines/mod.rs | 7 +- title/shark/src/pipelines/ui.rs | 129 ------------ 8 files changed, 193 insertions(+), 375 deletions(-) delete mode 100644 title/shark-shaders/shaders/ui.frag.glsl delete mode 100644 title/shark-shaders/shaders/ui.vert.glsl delete mode 100644 title/shark/src/pipelines/ui.rs diff --git a/title/shark-shaders/build.rs b/title/shark-shaders/build.rs index 6b48486..149caf1 100644 --- a/title/shark-shaders/build.rs +++ b/title/shark-shaders/build.rs @@ -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() { diff --git a/title/shark-shaders/shaders/display_transform.comp.glsl b/title/shark-shaders/shaders/display_transform.comp.glsl index 1b440dc..e17c6e4 100644 --- a/title/shark-shaders/shaders/display_transform.comp.glsl +++ b/title/shark-shaders/shaders/display_transform.comp.glsl @@ -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 index 26af4ae..0000000 --- a/title/shark-shaders/shaders/ui.frag.glsl +++ /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 index 9d83d06..0000000 --- a/title/shark-shaders/shaders/ui.vert.glsl +++ /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; -} diff --git a/title/shark/src/main.rs b/title/shark/src/main.rs index dcabd7c..5aec15b 100644 --- a/title/shark/src/main.rs +++ b/title/shark/src/main.rs @@ -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, - primitive_vertices: Vec, } 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"), ); diff --git a/title/shark/src/pipelines/display_transform.rs b/title/shark/src/pipelines/display_transform.rs index f0c1e00..9af1af6 100644 --- a/title/shark/src/pipelines/display_transform.rs +++ b/title/shark/src/pipelines/display_transform.rs @@ -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, }, ], diff --git a/title/shark/src/pipelines/mod.rs b/title/shark/src/pipelines/mod.rs index 02b802f..1e5732a 100644 --- a/title/shark/src/pipelines/mod.rs +++ b/title/shark/src/pipelines/mod.rs @@ -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 index 85260f3..0000000 --- a/title/shark/src/pipelines/ui.rs +++ /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, - } - } -} -- 2.49.0