文档列表见:Rust 移动端跨平台复杂图形渲染项目开发系列总结(目录)

草稿状态

以OpenGL/ES Framebuffer角度看,如果用gfx-hal(Vulkan)接口实现类似OpenGL/ES Framebuffer的功能,这一过程远比OpenGL/ES那几个函数调用复杂,因为涉及了多个组件:Swapchain、RenderPass、Framebuffer、CommandBuffer、Submission等。对于不同场景,这些组件并不是必需的:

  • 当渲染到屏幕时,它们是必需的,全都要合理配置。
  • 当渲染到纹理(Render to Texture,后面简称RTT)时,可忽略Swaphain,只需RenderPass、Framebuffer、CommandBuffer等。

Swapchain

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: 描述ImagesFramebuffer的区别。

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

SwapchainConfig

SwapchainConfig定义

Contains all the data necessary to create a new Swapchain: color, depth, and number of images.

SwapchainConfig初始化

let (caps, formats, _present_modes) = surface.compatibility(&physical_device);
println!("formats: {:?}", formats);
let format = formats.map_or(format::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

值得注意的是,RTT场景无需创建Swapchain。

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

RenderPass

A render pass represents a collection of attachments, subpasses, and dependencies between the subpasses, and describes how the attachments are used over the course of the subpasses. The use of a render pass in a command buffer is a render pass instance.

www.khronos.org/registry/vu…

RenderPass包含Attachment、SubpassDesc和SubpassDependency。RTT场景由于偷懒没创建Surface和Swapchain,那么,在创建Attachment时format值不能再从swapchain获取,改用Image(Texture)的format才合理。

初始化RenderPass

根据前面可知,创建RenderPass需要先创建它的子组件,下面逐次描述。

创建Attachment

let attachment = pass::Attachment {format: Some(swapchain.format.clone()), // NOTE: RTT casesamples: 1,ops: pass::AttachmentOps::new(pass::AttachmentLoadOp::Clear,pass::AttachmentStoreOp::Store,),stencil_ops: pass::AttachmentOps::DONT_CARE,layouts: image::Layout::Undefined..image::Layout::Present,
};
复制代码

创建SubpassDesc

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

创建SubpassDependency

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),
};
复制代码

创建RenderPass

终于,三大组件就绪后,可以从Device创建一个RenderPass。

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

Framebuffer

初始化Framebuffer

创建Framebuffer

渲染到View场景会根据swapchain.backbuffer类型进行不同的Framebuffer创建流程,主体逻辑示意如下:

let (frame_images, framebuffers) = match swapchain.backbuffer.take().unwrap() {Backbuffer::Images(images) => {let extent = // ... let pairs = // ... let fbos = pairs.iter().map(/* ... */device.create_framebuffer(/* ... */);/* ... */).collect();(pairs, fbos)}Backbuffer::Framebuffer(fbo) => (Vec::new(), vec![fbo]),
};
复制代码

创建CommandPool

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());
}
复制代码

创建CommandBuffer

// 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);cmd_buffer.bind_vertex_buffers(0,Some((self.vertex_buffer.get_buffer(), 0)),);cmd_buffer.bind_graphics_descriptor_sets(self.pipeline.pipeline_layout,0,vec![self.image.desc.set, self.uniform.desc.set],&[],); //TODO{let mut encoder = cmd_buffer.begin_render_pass_inline(render_pass,framebuffer,self.viewport.rect,&[command::ClearValue::Color(command::ClearColor::Float([cr, cg, cb, 1.0,]))],);encoder.draw(0..6, 0..1);}cmd_buffer.finish()
};
复制代码

提交CommandBuffer到GPU队列

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(),这一步相当于eglSwapbufferEAGLContext presentRenderbuffer交换前后帧缓冲区,不算OpenGL/ES Framebuffer的操作,但是,不切EGLContext的默认帧缓冲区将看不到画面,为了方便,在此将其当成Framebuffer的协同操作。

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

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

  1. OpenGL ES 简介

    目录 一.前言 1.WebGL 2.OpenCV 3.Direct3D 4.OpenGL 5.OpenGL ES 和 OpenGL 二.OpenGL ES 跨平台 1.OpenGL ES 2.Meta ...

  2. OpenGL ES EGL eglDestroyContext

    目录 一. EGL 前言 二. EGL 绘制流程简介 三.eglDestroyContext 函数简介 四.eglDestroyContext 使用 四.猜你喜欢 零基础 OpenGL ES 学习路线 ...

  3. OpenGL ES EGL eglCreatePbufferSurface

    目录 一. EGL 前言 二. EGL 绘制流程简介 三.eglCreatePbufferSurface 函数简介 1.eglCreatePbufferSurface 简介 2.eglCreatePb ...

  4. OpenGL ES EGL eglQueryContext

    目录 一. EGL 前言 二. EGL 绘制流程简介 三.eglQueryContext 函数简介 四.eglQueryContext 使用 四.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : ...

  5. OpenGL ES glut glew glfw glad freeglut

    目录 一.简介 1.freeglut 2.glew 3.glut 4.glfw 5.glad 二.分类 1.窗口管理 2.函数加载 三.组合使用 1.freeglut + glew 2.glfw + ...

  6. OpenGL ES glfw 下载和使用

    目录 一.glfw 简介 二.glfw 下载 三.glfw 编译 四.glfw 使用 1.OpenGL glfw + glad 效果演示 2.OpenGL glfw + glad <源码下载&g ...

  7. OpenGL ES EGL eglDestroySurface

    目录 一. EGL 前言 二. EGL 绘制流程简介 三.eglDestroySurface 函数简介 四.eglDestroySurface 使用 四.猜你喜欢 零基础 OpenGL ES 学习路线 ...

  8. OpenGL ES EGL 简介

    目录 一.EGL 简介 二.EGL 跨平台之 ANGLE 1.ANGLE 支持跨平台 2.ANGLE 支持渲染器 3.ANGLE 下载地址 三.EGL 坐标系 四.EGL 绘图步骤 五.猜你喜欢 零基 ...

  9. OpenGL ES EGL eglSwapBuffer

    目录 一. EGL 前言 二. EGL 绘制流程简介 三.eglSwapBuffer 函数简介 四.关于多个 EGLContext 五.共享 EGLContext 六.猜你喜欢 零基础 OpenGL ...

最新文章

  1. 【Ubuntu】Ubuntu14.04添加163的源
  2. python能做什么游戏ll-一个简单的python game游戏
  3. 误删Windows文件后恢复技巧
  4. 设计模式整理之简单工厂
  5. AI理论知识整理(11)-线性组合线性相关与线性无关
  6. 8s 使用本地打包镜像_在Docker环境构建、打包和运行Spring Boot应用
  7. YARN体系学习笔记
  8. php7.2 event扩展php_sockets_le_socket错误解决
  9. web前端新手入门教程:Web 框架的架构模式探讨
  10. asp.net中用LinkButton取到gridview中当前行的ID值
  11. python xlutils教程_python xlutils复制表格使用方法
  12. Mac磁盘工具---Disk Xray三大功能使用指南
  13. Java毕业设计-社区疫情防控管理系统
  14. 数学基础知识02——常用积分公式
  15. 因一纸设计稿,我把竞品APP扒得裤衩不剩(上)
  16. 利用Travis IC实现Hexo博客自动化部署
  17. 更新来袭!新增语音添加待办、邮箱通知等功能
  18. 微信小程序使用后台播放器播放音乐
  19. [ExtJS] Tpl模板中的extjs控件无法失焦处理
  20. DBGrid 各属性的设置

热门文章

  1. AI不会很快取代作家——但未来可能比你想象的更近
  2. 整个宇宙可能是个巨大的神经网络?看科学家们是这样解释的
  3. 人工智能的鱼与熊掌:精度与可解释性
  4. 重磅盘点:过去8年中深度学习最重要的想法
  5. 关于征集2020重大科学问题和工程技术难题的通知
  6. 中国17种稀土有啥军事用途?没它们,美军技术优势将归零
  7. 特斯拉烧,特斯拉烧完蔚来烧
  8. 学界 | 量化深度强化学习算法的泛化能力
  9. Nature最新研究:超9000学者每5天发1篇论文,这些高产作家背后的科研圈
  10. Google Brain 团队的研究方法