以OpenGL/ES视角介绍gfx-hal(Vulkan) Framebuffer接口使用

栏目: 后端 · 发布时间: 5年前

内容简介:TheAtodo: 描述Images和Framebuffer的区别。

The Swapchain is the backend representation of the surface. It consists of multiple buffers, which will be presented on the surface.

A Surface abstracts the surface of a native window, which will be presented on the display.

Backbuffer - Swapchain的后端缓冲区类型

todo: 描述Images和Framebuffer的区别。

/// Swapchain backbuffer type
#[derive(Debug)]
pub enum Backbuffer<B: Backend> {
    /// Color image chain
    Images(Vec<B::Image>),
    /// A single opaque framebuffer
    Framebuffer(B::Framebuffer),
}
复制代码

SwapchainConfig

SwapchainConfig定义

/// Contains all the data necessary to create a new `Swapchain`:
/// color, depth, and number of images.
///
/// # Examples
///
/// This type implements the builder pattern, method calls can be
/// easily chained.
///
/// ```no_run
/// # extern crate gfx_hal;
/// # fn main() {
/// # use gfx_hal::{SwapchainConfig};
/// # use gfx_hal::format::Format;
/// let config = SwapchainConfig::new(100, 100, Format::Bgra8Unorm, 2);
/// # }
/// ```
#[derive(Debug, Clone)]
pub struct SwapchainConfig {
    /// Presentation mode.
    pub present_mode: PresentMode,
    /// Format of the backbuffer images.
    pub format: Format,
    /// Requested image extent. Must be in
    /// `SurfaceCapabilities::extents` range.
    pub extent: Extent2D,
    /// Number of images in the swapchain. Must be in
    /// `SurfaceCapabilities::image_count` range.
    pub image_count: SwapImageIndex,
    /// Number of image layers. Must be lower or equal to
    /// `SurfaceCapabilities::max_image_layers`.
    pub image_layers: image::Layer,
    /// Image usage of the backbuffer images.
    pub image_usage: image::Usage,
}
复制代码

初始化SwapchainConfig

let (caps, formats, _present_modes) = surface.compatibility(&physical_device);
println!("formats: {:?}", formats);
let format = formats
    .map_or(f::Format::Rgba8Srgb, |formats| {
        formats
            .iter()
            .find(|format| format.base_format().1 == ChannelType::Srgb)
            .map(|format| *format)
            .unwrap_or(formats[0])
    });

println!("Surface format: {:?}", format);
let swap_config = SwapchainConfig::from_caps(&caps, format);
复制代码

创建Swapchain

todo: 描述Render To Texture(RTT)情况的Swapchain创建注意事项。

let (swapchain, backbuffer) = device.create_swapchain(
    &mut surface,
    swap_config,
    None,
);
复制代码

RenderPass

创建RenderPass

let render_pass = {
    let attachment = pass::Attachment {
        format: Some(swapchain.format.clone()),
        samples: 1,
        ops: pass::AttachmentOps::new(
            pass::AttachmentLoadOp::Clear,
            pass::AttachmentStoreOp::Store,
        ),
        stencil_ops: pass::AttachmentOps::DONT_CARE,
        layouts: image::Layout::Undefined..image::Layout::Present,
    };

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

    let dependency = pass::SubpassDependency {
        passes: pass::SubpassRef::External..pass::SubpassRef::Pass(0),
        stages: PipelineStage::COLOR_ATTACHMENT_OUTPUT
            ..PipelineStage::COLOR_ATTACHMENT_OUTPUT,
        accesses: image::Access::empty()
            ..(image::Access::COLOR_ATTACHMENT_READ | image::Access::COLOR_ATTACHMENT_WRITE),
    };

    device.create_render_pass(&[attachment], &[subpass], &[dependency])
};
复制代码

Framebuffer

创建Framebuffer

let (frame_images, framebuffers) = match swapchain.backbuffer.take().unwrap() {
    Backbuffer::Images(images) => {
        let extent = image::Extent {
            width: swapchain.extent.width as _,
            height: swapchain.extent.height as _,
            depth: 1,
        };
        let pairs = images
            .into_iter()
            .map(|image| {
                let rtv = device
                    .create_image_view(
                        &image,
                        image::ViewKind::D2,
                        swapchain.format,
                        Swizzle::NO,
                        COLOR_RANGE.clone(),
                    )
                    .unwrap();
                (image, rtv)
            })
            .collect::<Vec<_>>();
        let fbos = pairs
            .iter()
            .map(|&(_, ref rtv)| {
                device
                    .create_framebuffer(
                        render_pass.render_pass.as_ref().unwrap(),
                        Some(rtv),
                        extent,
                    )
                    .unwrap()
            })
            .collect();
        (pairs, fbos)
    }
    Backbuffer::Framebuffer(fbo) => (Vec::new(), vec![fbo]),
};

let iter_count = if frame_images.len() != 0 {
    frame_images.len()
} else {
    1 // GL can have zero
};

let mut fences: Vec<B::Fence> = vec![];
let mut command_pools: Vec<hal::CommandPool<B, hal::Graphics>> = vec![];
let mut acquire_semaphores: Vec<B::Semaphore> = vec![];
let mut present_semaphores: Vec<B::Semaphore> = vec![];

for _ in 0..iter_count {
    fences.push(device.create_fence(true));
    command_pools.push(device.create_command_pool_typed(
        &queues,
        pool::CommandPoolCreateFlags::empty(),
        16,
    ));

    acquire_semaphores.push(device.create_semaphore());
    present_semaphores.push(device.create_semaphore());
}
复制代码

创建渲染命令

// Rendering
let submit = {
    let mut cmd_buffer = command_pool.acquire_command_buffer(false);
    cmd_buffer.set_viewports(0, &[self.viewport.clone()]);
    cmd_buffer.set_scissors(0, &[self.viewport.rect]);
    cmd_buffer.bind_graphics_pipeline(self.pipeline.pipeline.as_ref().unwrap());
    cmd_buffer.bind_vertex_buffers(
        0,
        Some((self.vertex_buffer.get_buffer(), 0)),
    );
    cmd_buffer.bind_graphics_descriptor_sets(
        self.pipeline.pipeline_layout.as_ref().unwrap(),
        0,
        vec![self.image.desc.set.as_ref().unwrap(), self.uniform.desc.as_ref().unwrap().set.as_ref().unwrap()],
        &[],
    ); //TODO

    {
        let mut encoder = cmd_buffer.begin_render_pass_inline(
            render_pass.as_ref().unwrap(),
            framebuffer,
            self.viewport.rect,
            &[command::ClearValue::Color(command::ClearColor::Float([
                cr, cg, cb, 1.0,
            ]))],
        );
        encoder.draw(0..6, 0..1);
    }

    cmd_buffer.finish()
};
复制代码

提交渲染命令到GPU队列

Render to Texture(RTT)场景到这一步就结束了,通常还会配置Submission执行完成的回调,方便我们提交下一个Submission。

let submission = Submission::new()
    .wait_on(&[(&*image_acquired, PipelineStage::BOTTOM_OF_PIPE)])
    .signal(&[&*image_present])
    .submit(Some(submit));
queues.queues[0].submit(submission, Some(framebuffer_fence));
复制代码

交换前后帧缓冲区

目前来看,渲染到屏幕才需要 swapchain.present()

// present frame
swapchain.as_ref().unwrap().present(
    &mut queues.queues[0],
    frame,
    Some(&*image_present),
)
复制代码

以上所述就是小编给大家介绍的《以OpenGL/ES视角介绍gfx-hal(Vulkan) Framebuffer接口使用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

We Are the Nerds

We Are the Nerds

Christine Lagorio-Chafkin / Hachette Books / 2018-10-2 / USD 18.30

Reddit hails itself as "the front page of the Internet." It's the third most-visited website in the United States--and yet, millions of Americans have no idea what it is. We Are the Nerds is an eng......一起来看看 《We Are the Nerds》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具