aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/ui.rs
diff options
context:
space:
mode:
Diffstat (limited to 'stockton-render/src/ui.rs')
-rw-r--r--stockton-render/src/ui.rs421
1 files changed, 0 insertions, 421 deletions
diff --git a/stockton-render/src/ui.rs b/stockton-render/src/ui.rs
deleted file mode 100644
index 981be02..0000000
--- a/stockton-render/src/ui.rs
+++ /dev/null
@@ -1,421 +0,0 @@
-//! Minimal code for drawing any level, based on traits from stockton-levels
-use crate::window::UiState;
-
-use stockton_skeleton::{
- buffers::draw::DrawBuffers,
- builders::{
- AttachmentSpec, CompletePipeline, PipelineSpecBuilder, RenderpassSpec, ShaderDesc,
- VertexBufferSpec, VertexPrimitiveAssemblerSpec,
- },
- RenderingContext,
- Session,
- draw_passes::{util::TargetSpecificResources, DrawPass, IntoDrawPass, PassPosition},
- mem::{DataPool, StagingPool, TexturesPool},
- queue_negotiator::QueueFamilyNegotiator,
- texture::{
- TextureResolver, LoadableImage, TexLoadQueue, TextureLoadConfig, TextureRepo,
- },
- types::*,
-};
-
-use std::{
- array::IntoIter,
- convert::TryInto,
- iter::{empty, once},
- sync::Arc,
-};
-
-use anyhow::{anyhow, Context, Result};
-use egui::{ClippedMesh, TextureId};
-use egui::{CtxRef, Texture};
-use hal::{
- buffer::SubRange,
- command::{ClearColor, ClearValue, RenderAttachmentInfo, SubpassContents},
- format::Format,
- image::Layout,
- pass::Attachment,
- pso::{
- BlendDesc, BlendOp, BlendState, ColorBlendDesc, ColorMask, DepthStencilDesc, Face, Factor,
- FrontFace, InputAssemblerDesc, LogicOp, PolygonMode, Primitive, Rasterizer, Rect,
- ShaderStageFlags, State, VertexInputRate,
- },
-};
-use shaderc::ShaderKind;
-
-#[derive(Debug)]
-pub struct UiPoint(pub Vector2, pub Vector2, pub [f32; 4]);
-
-/// Draw a Ui object
-pub struct UiDrawPass<'a> {
- repo: TextureRepo<TexturesPool, StagingPool>,
- draw_buffers: DrawBuffers<'a, UiPoint, DataPool, StagingPool>,
-
- surface_resources: SurfaceDependentResources,
-}
-
-impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> {
- fn queue_draw(
- &mut self,
- session: &Session,
- img_view: &ImageViewT,
- cmd_buffer: &mut CommandBufferT,
- ) -> anyhow::Result<()> {
- // We might have loaded more textures
- self.repo.process_responses();
-
- // Make sure we update the vertex buffers after they're written to, but before they're read from.
- self.draw_buffers
- .vertex_buffer
- .record_commit_cmds(cmd_buffer)?;
- self.draw_buffers
- .index_buffer
- .record_commit_cmds(cmd_buffer)?;
-
- // Get level & camera
- let ui: &mut UiState = &mut session.resources.get_mut::<UiState>().unwrap();
-
- // Get framebuffer and depth buffer
- let fb = self.surface_resources.framebuffers.get_next();
- unsafe {
- cmd_buffer.begin_render_pass(
- &self.surface_resources.pipeline.renderpass,
- fb,
- self.surface_resources.pipeline.render_area,
- vec![RenderAttachmentInfo {
- image_view: img_view,
- clear_value: ClearValue {
- color: ClearColor {
- float32: [0.0, 0.0, 0.0, 1.0],
- },
- },
- }]
- .into_iter(),
- SubpassContents::Inline,
- );
- cmd_buffer.bind_graphics_pipeline(&self.surface_resources.pipeline.pipeline);
-
- // Bind buffers
- cmd_buffer.bind_vertex_buffers(
- 0,
- once((
- self.draw_buffers.vertex_buffer.get_buffer(),
- SubRange {
- offset: 0,
- size: None,
- },
- )),
- );
- cmd_buffer.bind_index_buffer(
- self.draw_buffers.index_buffer.get_buffer(),
- SubRange {
- offset: 0,
- size: None,
- },
- hal::IndexType::U16,
- );
- }
-
- let (_out, shapes) = ui.end_frame();
- let screen = ui
- .dimensions()
- .ok_or_else(|| anyhow!("UI not set up properly."))?;
- let shapes = ui.ctx().tessellate(shapes);
-
- let mut next_idx_idx = 0;
- let mut next_vert_idx = 0;
- for ClippedMesh(rect, tris) in shapes.iter() {
- assert!(tris.texture_id == TextureId::Egui);
-
- // Copy triangles/indicies
- for i in (0..tris.indices.len()).step_by(3) {
- self.draw_buffers.index_buffer[next_idx_idx + (i / 3)] = (
- tris.indices[i].try_into()?,
- tris.indices[i + 1].try_into()?,
- tris.indices[i + 2].try_into()?,
- );
- }
-
- for (i, vertex) in tris.vertices.iter().enumerate() {
- self.draw_buffers.vertex_buffer[next_vert_idx + i] = UiPoint(
- Vector2::new(vertex.pos.x, vertex.pos.y),
- Vector2::new(vertex.uv.x, vertex.uv.y),
- [
- vertex.color.r() as f32 / 255.0,
- vertex.color.g() as f32 / 255.0,
- vertex.color.b() as f32 / 255.0,
- vertex.color.a() as f32 / 255.0,
- ],
- );
- }
-
- // TODO: *Properly* deal with textures
- if let Some(ds) = self.repo.attempt_get_descriptor_set(0) {
- unsafe {
- cmd_buffer.push_graphics_constants(
- &self.surface_resources.pipeline.pipeline_layout,
- ShaderStageFlags::VERTEX,
- 0,
- &[screen.x.to_bits(), screen.y.to_bits()],
- );
-
- cmd_buffer.set_scissors(
- 0,
- IntoIter::new([Rect {
- x: rect.min.x as i16,
- y: rect.min.y as i16,
- w: rect.width() as i16,
- h: rect.height() as i16,
- }]),
- );
- cmd_buffer.bind_graphics_descriptor_sets(
- &self.surface_resources.pipeline.pipeline_layout,
- 0,
- IntoIter::new([ds]),
- empty(),
- );
- // Call draw
- cmd_buffer.draw_indexed(
- (next_idx_idx as u32 * 3)..((next_idx_idx * 3) + tris.indices.len()) as u32,
- next_vert_idx as i32,
- 0..1,
- );
- }
- } else {
- self.repo.queue_load(0)?;
- }
-
- next_idx_idx += tris.indices.len() / 3;
- next_vert_idx += tris.vertices.len();
- }
-
- unsafe {
- cmd_buffer.end_render_pass();
- }
-
- Ok(())
- }
-
- fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
- self.draw_buffers.deactivate(context);
- self.surface_resources.deactivate(context)?;
- self.repo.deactivate(context);
-
- Ok(())
- }
-
- fn handle_surface_change(
- mut self,
- _session: &Session,
- context: &mut RenderingContext,
- ) -> Result<Self> {
- let new_surface_resources =
- SurfaceDependentResources::new::<P>(context, &*self.repo.get_ds_layout()?)?;
- let old_surface_resources = self.surface_resources;
- self.surface_resources = new_surface_resources;
-
- match old_surface_resources.deactivate(context) {
- Ok(_) => Ok(self),
- Err(e) => {
- <Self as DrawPass<P>>::deactivate(self, context)?;
- Err(e)
- }
- }
- }
-}
-
-impl<'a, P: PassPosition> IntoDrawPass<UiDrawPass<'a>, P> for () {
- fn init(self, session: &mut Session, context: &mut RenderingContext) -> Result<UiDrawPass<'a>> {
- let ui: &mut UiState = &mut session.resources.get_mut::<UiState>().unwrap();
- let repo = TextureRepo::new::<_, TexLoadQueue>(
- context,
- TextureLoadConfig {
- resolver: UiTextures::new(ui.ctx().clone()),
- filter: hal::image::Filter::Linear,
- wrap_mode: hal::image::WrapMode::Clamp,
- },
- )
- .context("Error creating texture repo")?;
-
- let draw_buffers =
- DrawBuffers::from_context(context).context("Error creating draw buffers")?;
-
- let surface_resources =
- SurfaceDependentResources::new::<P>(context, &*repo.get_ds_layout()?)?;
-
- Ok(UiDrawPass {
- repo,
- draw_buffers,
- surface_resources,
- })
- }
-
- fn find_aux_queues(
- adapter: &Adapter,
- queue_negotiator: &mut QueueFamilyNegotiator,
- ) -> Result<()> {
- queue_negotiator.find(adapter, &TexLoadQueue, 1)?;
-
- Ok(())
- }
-}
-
-pub struct UiTexture(Arc<Texture>);
-
-pub struct UiTextures {
- ctx: CtxRef,
-}
-
-impl TextureResolver for UiTextures {
- type Image = UiTexture;
- fn resolve(&mut self, tex: u32) -> Option<Self::Image> {
- if tex == 0 {
- Some(UiTexture(self.ctx.texture()))
- } else {
- None
- }
- }
-}
-
-impl UiTextures {
- pub fn new(ctx: CtxRef) -> Self {
- UiTextures { ctx }
- }
-}
-
-impl LoadableImage for UiTexture {
- fn width(&self) -> u32 {
- self.0.width as u32
- }
- fn height(&self) -> u32 {
- self.0.height as u32
- }
- unsafe fn copy_row(&self, y: u32, ptr: *mut u8) {
- let row_size = self.0.width as u32;
- let pixels = &self.0.pixels[(y * row_size) as usize..((y + 1) * row_size) as usize];
-
- for (i, x) in pixels.iter().enumerate() {
- *ptr.offset(i as isize * 4) = 255;
- *ptr.offset((i as isize * 4) + 1) = 255;
- *ptr.offset((i as isize * 4) + 2) = 255;
- *ptr.offset((i as isize * 4) + 3) = *x;
- }
- }
-}
-
-struct SurfaceDependentResources {
- pipeline: CompletePipeline,
- framebuffers: TargetSpecificResources<FramebufferT>,
-}
-
-impl SurfaceDependentResources {
- fn new<P: PassPosition>(
- context: &mut RenderingContext,
- ds_layout: &DescriptorSetLayoutT,
- ) -> Result<Self> {
- let mut device = context.lock_device()?;
-
- let spec = PipelineSpecBuilder::default()
- .rasterizer(Rasterizer {
- polygon_mode: PolygonMode::Fill,
- cull_face: Face::NONE,
- front_face: FrontFace::CounterClockwise,
- depth_clamping: false,
- depth_bias: None,
- conservative: true,
- line_width: State::Static(1.0),
- })
- .depth_stencil(DepthStencilDesc {
- depth: None,
- depth_bounds: false,
- stencil: None,
- })
- .blender(BlendDesc {
- logic_op: Some(LogicOp::Copy),
- targets: vec![ColorBlendDesc {
- mask: ColorMask::ALL,
- blend: Some(BlendState {
- color: BlendOp::Add {
- src: Factor::SrcAlpha,
- dst: Factor::OneMinusSrcAlpha,
- },
- alpha: BlendOp::Add {
- src: Factor::SrcAlpha,
- dst: Factor::OneMinusSrcAlpha,
- },
- }),
- }],
- })
- .primitive_assembler(VertexPrimitiveAssemblerSpec::with_buffers(
- InputAssemblerDesc::new(Primitive::TriangleList),
- vec![VertexBufferSpec {
- attributes: vec![Format::Rg32Sfloat, Format::Rg32Sfloat, Format::Rgba32Sfloat],
- rate: VertexInputRate::Vertex,
- }],
- ))
- .shader_vertex(ShaderDesc {
- source: include_str!("./data/ui.vert").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Vertex,
- })
- .shader_fragment(ShaderDesc {
- source: include_str!("./data/ui.frag").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Fragment,
- })
- .push_constants(vec![(ShaderStageFlags::VERTEX, 0..8)])
- .renderpass(RenderpassSpec {
- colors: vec![AttachmentSpec {
- attachment: Attachment {
- format: Some(context.properties().color_format),
- samples: 1,
- ops: P::attachment_ops(),
- stencil_ops: P::attachment_ops(),
- layouts: P::layout_as_range(),
- },
- used_layout: Layout::ColorAttachmentOptimal,
- }],
- depth: None,
- inputs: vec![],
- resolves: vec![],
- preserves: vec![],
- })
- .dynamic_scissor(true)
- .build()
- .context("Error building pipeline")?;
-
- let pipeline = spec
- .build(&mut device, context.properties().extent, once(ds_layout))
- .context("Error building pipeline")?;
-
- let fat = context.properties().swapchain_framebuffer_attachment();
-
- let framebuffers = TargetSpecificResources::new(
- || unsafe {
- Ok(device.create_framebuffer(
- &pipeline.renderpass,
- IntoIter::new([fat.clone()]),
- context.properties().extent,
- )?)
- },
- context.properties().image_count as usize,
- )?;
-
- Ok(Self {
- framebuffers,
- pipeline,
- })
- }
-
- fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
- unsafe {
- let mut device = context.lock_device()?;
- self.pipeline.deactivate(&mut device);
-
- for fb in self.framebuffers.dissolve() {
- device.destroy_framebuffer(fb);
- }
- }
-
- Ok(())
- }
-}