Shub's logo

T-2: Render Pass

06 Jun, 2020

2 min read

Quoting directly from LunarG Tutorials

A render pass describes the scope of a rendering operation by specifying the collection of attachments, subpasses, and dependencies used during the rendering operation. A render pass consists of at least one subpass. The communication of this information to the driver allows the driver to know what to expect when rendering begins and to set up the hardware optimally for the rendering operation.

As we all know, a Train cannot fly or sail, as it's scope is limited to rails. Similarly, RenderPass helps to define a scope for rendering, i.e., what kind of rendering will happen when commands are executed on GPU. For e.g. a shader pass will only handle shading an image while rendering.

Since GPU can handle many parallel tasks in one go, we can create different render passes to do different scoped rendering per thread.

I won't discuss this topic in-depth, as even I have to explore this topic a lot more.

For now, I would suggest you read LunarG RenderPass Post.

In this section, we will only be creating and defining the render pass and not using it in a command buffer until later.

Code

struct Renderer<B: Backend> {
    ...
    // Render Pass instance
    render_pass: ManuallyDrop<B::RenderPass>,
}
impl<B: Backend> Renderer<B> {
    pub fn new(
        instance: B::Instance,
        mut surface: B::Surface,
        init_extent: hal_window::Extent2D,
    ) -> Result<Self, &'static str> {
        ...
        let render_pass = {
            let color_attachment = Attachment {
                format: Some(format),
                samples: 1,
                ops: AttachmentOps::INIT,
                stencil_ops: AttachmentOps::DONT_CARE,
                layouts: Layout::Undefined..Layout::Present,
            };

            let subpass = SubpassDesc {
                colors: &[(0, Layout::ColorAttachmentOptimal)],
                depth_stencil: None,
                inputs: &[],
                resolves: &[],
                preserves: &[],
            };

            unsafe {
                device
                    .create_render_pass(&[color_attachment], &[subpass], &[])
                    .expect("Out of memory")
            }
        };
        Renderer {
            ...
            render_pass: ManuallyDrop::new(render_pass),
        }
    }
}

impl<B: Backend> Drop for Renderer<B> {
    fn drop(&mut self) {
        unsafe {
            self.device
                .destroy_render_pass(ManuallyDrop::into_inner(ptr::read(&self.render_pass)));
            ...
        }
    }
}

Attachments are details about resources that will be passed in this RenderPass. For example, we will be initially working with only Colors; thus, a Color Attachment (which would be an Image for a color) will be passed as an Attachment to Render Pass.

Later on, we will also be adding an attachment to Depth Buffer, which will be used as Z depth of the cube.

Subpass here is used for defining which attachment to use while rendering during the subpass.

© Copyright 2020 Subroto Biswas

Share