aboutsummaryrefslogtreecommitdiff
path: root/stockton-render
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:24 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:24 +0100
commit982c053f3946b53e1d763df71e4ffcb81362e8d3 (patch)
treecab91964c0e456db51c487d8ca2051b18ec70bcd /stockton-render
parent3b21e4c9d1d72a2ba71e4e4c1a2f60fb51f67205 (diff)
fix(render): unsoundness in handle_surface_change
Diffstat (limited to 'stockton-render')
-rw-r--r--stockton-render/src/level.rs396
-rw-r--r--stockton-render/src/ui.rs288
2 files changed, 335 insertions, 349 deletions
diff --git a/stockton-render/src/level.rs b/stockton-render/src/level.rs
index b1f7b7c..f577569 100644
--- a/stockton-render/src/level.rs
+++ b/stockton-render/src/level.rs
@@ -10,8 +10,8 @@ use stockton_skeleton::{
image::{BoundImageView, ImageSpec, DEPTH_RESOURCES},
},
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},
@@ -57,14 +57,10 @@ struct UvPoint(pub Vector3, pub i32, pub Vector2);
/// Draw a level
pub struct LevelDrawPass<'a, M> {
- pipeline: CompletePipeline,
repo: TextureRepo<TexturesPool, StagingPool>,
active_camera: Entity,
draw_buffers: DrawBuffers<'a, UvPoint, DataPool, StagingPool>,
-
- framebuffers: TargetSpecificResources<FramebufferT>,
- depth_buffers: TargetSpecificResources<BoundImageView<DepthBufferPool>>,
-
+ surface_resources: SurfaceDependentResources,
_d: PhantomData<M>,
}
@@ -96,8 +92,8 @@ where
.context("Couldn't find camera components")?;
let camera_vp = {
- let aspect_ratio =
- self.pipeline.render_area.w as f32 / self.pipeline.render_area.h as f32;
+ let aspect_ratio = self.surface_resources.pipeline.render_area.w as f32
+ / self.surface_resources.pipeline.render_area.h as f32;
// Get look direction from euler angles
let direction = euler_to_direction(&camera_transform.rotation);
@@ -131,14 +127,14 @@ where
let map = map_lock.read().map_err(|_| LockPoisoned::Map)?;
// Get framebuffer and depth buffer
- let fb = self.framebuffers.get_next();
- let db = self.depth_buffers.get_next();
+ let fb = self.surface_resources.framebuffers.get_next();
+ let db = self.surface_resources.depth_buffers.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,
@@ -161,13 +157,13 @@ where
.into_iter(),
SubpassContents::Inline,
);
- cmd_buffer.bind_graphics_pipeline(&self.pipeline.pipeline);
+ cmd_buffer.bind_graphics_pipeline(&self.surface_resources.pipeline.pipeline);
// VP Matrix
let vp = &*(camera_vp.data.as_slice() as *const [f32] as *const [u32]);
cmd_buffer.push_graphics_constants(
- &self.pipeline.pipeline_layout,
+ &self.surface_resources.pipeline.pipeline_layout,
ShaderStageFlags::VERTEX,
0,
vp,
@@ -270,16 +266,7 @@ where
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);
- }
- }
- for db in self.depth_buffers.dissolve() {
- db.deactivate_with_context(context);
- }
+ self.surface_resources.deactivate(context)?;
self.repo.deactivate(context);
Ok(())
@@ -290,39 +277,21 @@ where
_session: &Session,
context: &mut RenderingContext,
) -> Result<Self> {
- // TODO: Handle deactivation if any of this fails.
-
- // Recreate depth buffers
- for db in self.depth_buffers.dissolve() {
- db.deactivate_with_context(context);
- }
- self.depth_buffers = create_depth_buffers(context)?;
-
- {
- 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_resources =
+ SurfaceDependentResources::new::<P>(context, &*self.repo.get_ds_layout()?)?;
+ let old_resources = self.surface_resources;
+ self.surface_resources = new_resources;
+
+ match old_resources.deactivate(context) {
+ Ok(_) => Ok(self),
+ Err(e) => {
+ <Self as DrawPass<P>>::deactivate(self, context)?;
+ Err(e)
}
- self.framebuffers = create_framebuffers(&mut device, &self.pipeline, context)?;
}
-
- Ok(self)
}
}
+
impl<'a, M> LevelDrawPass<'a, M> {
fn draw_or_queue(
&mut self,
@@ -334,7 +303,7 @@ impl<'a, M> LevelDrawPass<'a, M> {
if let Some(ds) = self.repo.attempt_get_descriptor_set(current_chunk) {
unsafe {
cmd_buffer.bind_graphics_descriptor_sets(
- &*self.pipeline.pipeline_layout,
+ &*self.surface_resources.pipeline.pipeline_layout,
0,
once(ds),
empty(),
@@ -365,7 +334,6 @@ where
_session: &mut Session,
context: &mut RenderingContext,
) -> Result<LevelDrawPass<'a, M>> {
- let spec = create_pipeline_spec::<P>(context)?;
let repo = TextureRepo::new::<_, TexLoadQueue>(
context,
TextureLoadConfig {
@@ -375,33 +343,18 @@ where
},
)
.context("Error creating texture repo")?;
-
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, &pipeline, context)?;
-
- (pipeline, framebuffers)
- };
- let depth_buffers = create_depth_buffers(context)?;
+ let surface_resources =
+ SurfaceDependentResources::new::<P>(context, &*repo.get_ds_layout()?)?;
Ok(LevelDrawPass {
- pipeline,
repo,
draw_buffers,
active_camera: self.active_camera,
+ surface_resources,
_d: PhantomData,
- framebuffers,
- depth_buffers,
})
}
@@ -415,30 +368,6 @@ where
}
}
-fn create_framebuffers(
- device: &mut DeviceT,
- pipeline: &CompletePipeline,
- context: &RenderingContext,
-) -> Result<TargetSpecificResources<FramebufferT>> {
- let fat = context.properties().swapchain_framebuffer_attachment();
- let dat = FramebufferAttachment {
- usage: Usage::DEPTH_STENCIL_ATTACHMENT,
- format: context.properties().depth_format,
- view_caps: ViewCapabilities::empty(),
- };
-
- TargetSpecificResources::new(
- || unsafe {
- Ok(device.create_framebuffer(
- &pipeline.renderpass,
- IntoIter::new([fat.clone(), dat.clone()]),
- context.properties().extent,
- )?)
- },
- context.properties().image_count as usize,
- )
-}
-
/// Indicates an issue with the level object being used
#[derive(Debug, Error)]
pub enum LevelError {
@@ -446,6 +375,173 @@ pub enum LevelError {
BadReference,
}
+/// Used to store resources which depend on the surface, for convenience in handle_surface_change
+struct SurfaceDependentResources {
+ pub pipeline: CompletePipeline,
+ pub framebuffers: TargetSpecificResources<FramebufferT>,
+ pub depth_buffers: TargetSpecificResources<BoundImageView<DepthBufferPool>>,
+}
+
+impl SurfaceDependentResources {
+ pub fn new<P: PassPosition>(
+ context: &mut RenderingContext,
+ ds_layout: &DescriptorSetLayoutT,
+ ) -> Result<Self> {
+ let db_spec = ImageSpec {
+ width: context.properties().extent.width,
+ height: context.properties().extent.height,
+ format: context.properties().depth_format,
+ usage: Usage::DEPTH_STENCIL_ATTACHMENT,
+ resources: DEPTH_RESOURCES,
+ };
+ let img_count = context.properties().image_count;
+
+ let depth_buffers = TargetSpecificResources::new(
+ || {
+ BoundImageView::from_context(context, &db_spec)
+ .context("Error creating depth buffer")
+ },
+ img_count as usize,
+ )?;
+
+ let (pipeline, framebuffers) = {
+ let pipeline_spec = PipelineSpecBuilder::default()
+ .rasterizer(Rasterizer {
+ polygon_mode: PolygonMode::Fill,
+ cull_face: Face::BACK,
+ front_face: FrontFace::CounterClockwise,
+ depth_clamping: false,
+ depth_bias: None,
+ conservative: true,
+ line_width: State::Static(1.0),
+ })
+ .depth_stencil(DepthStencilDesc {
+ depth: Some(DepthTest {
+ fun: Comparison::Less,
+ write: true,
+ }),
+ 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::Rgb32Sfloat, Format::R32Sint, Format::Rg32Sfloat],
+ rate: VertexInputRate::Vertex,
+ }],
+ ))
+ .shader_vertex(ShaderDesc {
+ source: include_str!("./data/3d.vert").to_string(),
+ entry: "main".to_string(),
+ kind: ShaderKind::Vertex,
+ })
+ .shader_fragment(ShaderDesc {
+ source: include_str!("./data/3d.frag").to_string(),
+ entry: "main".to_string(),
+ kind: ShaderKind::Fragment,
+ })
+ .push_constants(vec![(ShaderStageFlags::VERTEX, 0..64)])
+ .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: Some(AttachmentSpec {
+ attachment: Attachment {
+ format: Some(context.properties().depth_format),
+ samples: 1,
+ ops: AttachmentOps::new(
+ AttachmentLoadOp::Clear,
+ AttachmentStoreOp::DontCare,
+ ),
+ stencil_ops: AttachmentOps::new(
+ AttachmentLoadOp::DontCare,
+ AttachmentStoreOp::DontCare,
+ ),
+ layouts: Layout::Undefined..Layout::DepthStencilAttachmentOptimal,
+ },
+ used_layout: Layout::DepthStencilAttachmentOptimal,
+ }),
+ inputs: vec![],
+ resolves: vec![],
+ preserves: vec![],
+ })
+ .build()
+ .context("Error building pipeline")?;
+ let mut device = context.lock_device()?;
+
+ let pipeline = pipeline_spec
+ .build(&mut device, context.properties().extent, once(ds_layout))
+ .context("Error building pipeline")?;
+
+ let fat = context.properties().swapchain_framebuffer_attachment();
+ let dat = FramebufferAttachment {
+ usage: Usage::DEPTH_STENCIL_ATTACHMENT,
+ format: context.properties().depth_format,
+ view_caps: ViewCapabilities::empty(),
+ };
+
+ let framebuffers = TargetSpecificResources::new(
+ || unsafe {
+ Ok(device.create_framebuffer(
+ &pipeline.renderpass,
+ IntoIter::new([fat.clone(), dat.clone()]),
+ context.properties().extent,
+ )?)
+ },
+ context.properties().image_count as usize,
+ )?;
+
+ (pipeline, framebuffers)
+ };
+
+ Ok(Self {
+ pipeline,
+ framebuffers,
+ depth_buffers,
+ })
+ }
+
+ pub fn deactivate(self, context: &mut RenderingContext) -> Result<()> {
+ for db in self.depth_buffers.dissolve() {
+ db.deactivate_with_context(context);
+ }
+ unsafe {
+ let mut device = context.lock_device()?;
+ for fb in self.framebuffers.dissolve() {
+ device.destroy_framebuffer(fb);
+ }
+
+ self.pipeline.deactivate(&mut device);
+ }
+
+ Ok(())
+ }
+}
+
fn euler_to_direction(euler: &Vector3) -> Vector3 {
let pitch = euler.x;
let yaw = euler.y;
@@ -457,107 +553,3 @@ fn euler_to_direction(euler: &Vector3) -> Vector3 {
yaw.cos() * pitch.cos(),
)
}
-
-fn create_pipeline_spec<P: PassPosition>(context: &RenderingContext) -> Result<PipelineSpec> {
- Ok(PipelineSpecBuilder::default()
- .rasterizer(Rasterizer {
- polygon_mode: PolygonMode::Fill,
- cull_face: Face::BACK,
- front_face: FrontFace::CounterClockwise,
- depth_clamping: false,
- depth_bias: None,
- conservative: true,
- line_width: State::Static(1.0),
- })
- .depth_stencil(DepthStencilDesc {
- depth: Some(DepthTest {
- fun: Comparison::Less,
- write: true,
- }),
- 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::Rgb32Sfloat, Format::R32Sint, Format::Rg32Sfloat],
- rate: VertexInputRate::Vertex,
- }],
- ))
- .shader_vertex(ShaderDesc {
- source: include_str!("./data/3d.vert").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Vertex,
- })
- .shader_fragment(ShaderDesc {
- source: include_str!("./data/3d.frag").to_string(),
- entry: "main".to_string(),
- kind: ShaderKind::Fragment,
- })
- .push_constants(vec![(ShaderStageFlags::VERTEX, 0..64)])
- .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: Some(AttachmentSpec {
- attachment: Attachment {
- format: Some(context.properties().depth_format),
- samples: 1,
- ops: AttachmentOps::new(AttachmentLoadOp::Clear, AttachmentStoreOp::DontCare),
- stencil_ops: AttachmentOps::new(
- AttachmentLoadOp::DontCare,
- AttachmentStoreOp::DontCare,
- ),
- layouts: Layout::Undefined..Layout::DepthStencilAttachmentOptimal,
- },
- used_layout: Layout::DepthStencilAttachmentOptimal,
- }),
- inputs: vec![],
- resolves: vec![],
- preserves: vec![],
- })
- .build()
- .context("Error building pipeline")?)
-}
-
-fn create_depth_buffers(
- context: &mut RenderingContext,
-) -> Result<TargetSpecificResources<BoundImageView<DepthBufferPool>>> {
- let db_spec = ImageSpec {
- width: context.properties().extent.width,
- height: context.properties().extent.height,
- format: context.properties().depth_format,
- usage: Usage::DEPTH_STENCIL_ATTACHMENT,
- resources: DEPTH_RESOURCES,
- };
- let img_count = context.properties().image_count;
-
- TargetSpecificResources::new(
- || BoundImageView::from_context(context, &db_spec).context("Error creating depth buffer"),
- img_count as usize,
- )
-}
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(())
+ }
+}