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.rs288
1 files changed, 141 insertions, 147 deletions
diff --git a/stockton-render/src/ui.rs b/stockton-render/src/ui.rs
index 4149d71..91e1b4b 100644
--- a/stockton-render/src/ui.rs
+++ b/stockton-render/src/ui.rs
@@ -4,8 +4,8 @@ use crate::window::UiState;
use stockton_skeleton::{
buffers::draw::DrawBuffers,
builders::{
- AttachmentSpec, CompletePipeline, PipelineSpec, PipelineSpecBuilder, RenderpassSpec,
- ShaderDesc, VertexBufferSpec, VertexPrimitiveAssemblerSpec,
+ AttachmentSpec, CompletePipeline, PipelineSpecBuilder, RenderpassSpec, ShaderDesc,
+ VertexBufferSpec, VertexPrimitiveAssemblerSpec,
},
context::RenderingContext,
draw_passes::{util::TargetSpecificResources, DrawPass, IntoDrawPass, PassPosition},
@@ -47,11 +47,10 @@ pub struct UiPoint(pub Vector2, pub Vector2, pub [f32; 4]);
/// Draw a Ui object
pub struct UiDrawPass<'a> {
- pipeline: CompletePipeline,
repo: TextureRepo<TexturesPool, StagingPool>,
draw_buffers: DrawBuffers<'a, UiPoint, DataPool, StagingPool>,
- framebuffers: TargetSpecificResources<FramebufferT>,
+ surface_resources: SurfaceDependentResources,
}
impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> {
@@ -76,12 +75,12 @@ impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> {
let ui: &mut UiState = &mut session.resources.get_mut::<UiState>().unwrap();
// Get framebuffer and depth buffer
- let fb = self.framebuffers.get_next();
+ let fb = self.surface_resources.framebuffers.get_next();
unsafe {
cmd_buffer.begin_render_pass(
- &self.pipeline.renderpass,
+ &self.surface_resources.pipeline.renderpass,
fb,
- self.pipeline.render_area,
+ self.surface_resources.pipeline.render_area,
vec![RenderAttachmentInfo {
image_view: img_view,
clear_value: ClearValue {
@@ -93,7 +92,7 @@ impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> {
.into_iter(),
SubpassContents::Inline,
);
- cmd_buffer.bind_graphics_pipeline(&self.pipeline.pipeline);
+ cmd_buffer.bind_graphics_pipeline(&self.surface_resources.pipeline.pipeline);
// Bind buffers
cmd_buffer.bind_vertex_buffers(
@@ -153,7 +152,7 @@ impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> {
if let Some(ds) = self.repo.attempt_get_descriptor_set(0) {
unsafe {
cmd_buffer.push_graphics_constants(
- &self.pipeline.pipeline_layout,
+ &self.surface_resources.pipeline.pipeline_layout,
ShaderStageFlags::VERTEX,
0,
&[screen.x.to_bits(), screen.y.to_bits()],
@@ -169,7 +168,7 @@ impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> {
}]),
);
cmd_buffer.bind_graphics_descriptor_sets(
- &self.pipeline.pipeline_layout,
+ &self.surface_resources.pipeline.pipeline_layout,
0,
IntoIter::new([ds]),
empty(),
@@ -198,14 +197,7 @@ impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> {
fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
self.draw_buffers.deactivate(context);
-
- unsafe {
- let mut device = context.lock_device()?;
- self.pipeline.deactivate(&mut device);
- for fb in self.framebuffers.dissolve() {
- device.destroy_framebuffer(fb);
- }
- }
+ self.surface_resources.deactivate(context)?;
self.repo.deactivate(context);
Ok(())
@@ -216,36 +208,23 @@ impl<'a, P: PassPosition> DrawPass<P> for UiDrawPass<'a> {
_session: &Session,
context: &mut RenderingContext,
) -> Result<Self> {
- {
- let mut device = context.lock_device()?;
-
- // Recreate pipeline
- self.pipeline.deactivate(&mut device);
- self.pipeline = create_pipeline_spec::<P>(context)?
- .build(
- &mut device,
- context.properties().extent,
- once(&*self.repo.get_ds_layout()?),
- )
- .context("Error building pipeline")?;
-
- // Recreate framebuffers
- for fb in self.framebuffers.dissolve() {
- unsafe {
- device.destroy_framebuffer(fb);
- }
+ 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)
}
- self.framebuffers = create_framebuffers(&mut device, context, &self.pipeline)?;
}
-
- Ok(self)
}
}
impl<'a, P: PassPosition> IntoDrawPass<UiDrawPass<'a>, P> for () {
fn init(self, session: &mut Session, context: &mut RenderingContext) -> Result<UiDrawPass<'a>> {
- let spec = create_pipeline_spec::<P>(context)?;
-
let ui: &mut UiState = &mut session.resources.get_mut::<UiState>().unwrap();
let repo = TextureRepo::new::<_, TexLoadQueue>(
context,
@@ -260,26 +239,13 @@ impl<'a, P: PassPosition> IntoDrawPass<UiDrawPass<'a>, P> for () {
let draw_buffers =
DrawBuffers::from_context(context).context("Error creating draw buffers")?;
- let (pipeline, framebuffers) = {
- let mut device = context.lock_device()?;
-
- let pipeline = spec
- .build(
- &mut device,
- context.properties().extent,
- once(&*repo.get_ds_layout()?),
- )
- .context("Error building pipeline")?;
-
- let framebuffers = create_framebuffers(&mut device, context, &pipeline)?;
- (pipeline, framebuffers)
- };
+ let surface_resources =
+ SurfaceDependentResources::new::<P>(context, &*repo.get_ds_layout()?)?;
Ok(UiDrawPass {
- pipeline,
repo,
draw_buffers,
- framebuffers,
+ surface_resources,
})
}
@@ -293,96 +259,6 @@ impl<'a, P: PassPosition> IntoDrawPass<UiDrawPass<'a>, P> for () {
}
}
-fn create_framebuffers(
- device: &mut DeviceT,
- context: &RenderingContext,
- pipeline: &CompletePipeline,
-) -> Result<TargetSpecificResources<FramebufferT>> {
- let fat = context.properties().swapchain_framebuffer_attachment();
-
- TargetSpecificResources::new(
- || unsafe {
- Ok(device.create_framebuffer(
- &pipeline.renderpass,
- IntoIter::new([fat.clone()]),
- context.properties().extent,
- )?)
- },
- context.properties().image_count as usize,
- )
-}
-
-fn create_pipeline_spec<P: PassPosition>(context: &RenderingContext) -> Result<PipelineSpec> {
- 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")
-}
-
pub struct UiTexture(Arc<Texture>);
pub struct UiTextures {
@@ -425,3 +301,121 @@ impl LoadableImage for UiTexture {
}
}
}
+
+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(())
+ }
+}