1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use gfx_hal::{
  device::Device,
  image::Extent,
};

use super::{
  gpu::Gpu,
  render_pass::RenderPass,
  surface::Surface,
};

/// Framebuffer for the given render backend.
#[derive(Debug)]
pub struct Framebuffer<RenderBackend: gfx_hal::Backend> {
  frame_buffer: RenderBackend::Framebuffer,
}

impl<RenderBackend: gfx_hal::Backend> Framebuffer<RenderBackend> {
  /// Destroys the framebuffer from the given GPU.
  pub fn destroy(self, gpu: &super::gpu::Gpu<RenderBackend>) {
    unsafe {
      gpu
        .internal_logical_device()
        .destroy_framebuffer(self.frame_buffer);
    }
  }
}

impl<RenderBackend: gfx_hal::Backend> Framebuffer<RenderBackend> {
  /// Retrieve a reference to the internal frame buffer.
  pub(super) fn internal_frame_buffer(&self) -> &RenderBackend::Framebuffer {
    return &self.frame_buffer;
  }
}
pub struct FramebufferBuilder {}

impl FramebufferBuilder {
  pub fn new() -> Self {
    return Self {};
  }

  /// Build a frame buffer on a given GPU for the given surface.
  pub fn build<RenderBackend: gfx_hal::Backend>(
    self,
    gpu: &mut Gpu<RenderBackend>,
    render_pass: &RenderPass<RenderBackend>,
    surface: &Surface<RenderBackend>,
  ) -> Framebuffer<RenderBackend> {
    let (width, height) = surface.size().expect("A surface without a swapchain cannot be used in a framebeen configured with a swapchain");
    let image = surface
      .internal_frame_buffer_attachment()
      .expect("A surface without a swapchain cannot be used in a frame.");

    let frame_buffer = unsafe {
      gpu
        .internal_logical_device()
        .create_framebuffer(
          render_pass.internal_render_pass(),
          vec![image].into_iter(),
          Extent {
            width,
            height,
            depth: 1,
          },
        )
        .expect("Failed to create a framebuffer")
    };
    return Framebuffer { frame_buffer };
  }
}