【Vulkan入门】09-CreateFrameBuffer

目录

  • 先叨叨
  • git信息
  • 关键代码
    • VulkanEnv::FindHostVisitbaleMemoryTypeIndex()
    • TestPipeLine::CreateFramebuffers()

与网上大多数文章不同,其他文章基本上都使用窗口框架(X11、GLFW、WSL等)提供的surface来显示Vulkan渲染出的图像。我认为那样会屏蔽很多细节,因此我选择使用更原生的方式,即让Vulkan渲染到一块内存中,然后将内存读出再渲染到屏幕上。其实surface只不过是封装好的Image而以。

先叨叨

上一篇创建的RenderPass,但还没有给RenderPass分配内存空间。本篇来介绍如何给RenderPass创建内存空间。RenderPass与内存的对应关系如下图:
在这里插入图片描述
Vulkan的架构设计将RenderPass到Memeory的对应关系拉了一条很长的线路,至于为什么和这么设计的好处,我还理解不到。所以先死记硬背下来。

  1. RenderPass中有很多个Attachment每个,Attachment对应一块内存空间。Attachment用于指明该空间在渲染时具体起到的作用。如:颜色缓存、深度缓存、模板缓存等。
  2. 多个Attachment由一个Subpass进行关联,指明一次渲染会用到Subpass中的所有的Attachment。比如将第一个Attachment当作颜色缓存,将第二Attachment当作深度缓存。
  3. 一个RenderPass对应一个FrameBuffer。而FrameBuffer中有多个ImageView,每个ImageView对应一个RenderPass中的Attachment。。ImageView还不是真正的内存空间。
  4. ImageView会关联到一个Image。Image是对内存空间的描述,但Image并不是真正的内存空间。
  5. 真正的内存空间是Memory,Memory需要从Device上申请,申请完后需要绑定到Image上。

git信息

  • repository: https://gitee.com/J8_series/easy-car-ui
  • tag: 09-CreateFrameBuffer
  • url: https://gitee.com/J8_series/easy-car-ui/tree/09-CreateFrameBuffer

关键代码

VulkanEnv::FindHostVisitbaleMemoryTypeIndex()

上面介绍了Memory需要从Device上申请,而Device可能有多个内存空间(堆)。我希望找到一个GPU和CPU都能访问的堆,因为我想把渲染完的图片拷贝出来。渲染需要GPU访问,而拷贝需要CPU访问。

void VulkanEnv::FindHostVisitbaleMemoryTypeIndex()
{
    VkPhysicalDeviceMemoryProperties pMemoryProperties;
    vkGetPhysicalDeviceMemoryProperties(m_selectedPhysicalDevice, &pMemoryProperties);

    bool found = false;
    for (uint32_t i = 0; i < pMemoryProperties.memoryTypeCount; ++i)
    {
        if (pMemoryProperties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
        {
            m_hostVisitbaleMemoryTypeIndex = i;
            found = true;
            break;
        }
    }

    if (false == found)
    {
        throw std::runtime_error("To find host visiable memory is failed");
    }
}

TestPipeLine::CreateFramebuffers()

本方法流程如下:

  1. 创建Image
  2. 申请Memory
  3. 将Image和Memory 绑定到一起
  4. 创建ImageView并关联到Image上
  5. 创建FrameBuffer。framebufferInfo.pAttachments的值是一个ImageView数组,数组里的元素顺序要与RenderPass中的Attachment顺序一致。Vulkan用这种方式实现了Attachment和ImageView的对应。
    void TestPipeline::CreateFramebuffers()
    {
        //https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkImageCreateInfo
        VkImageCreateInfo imageCreateInfo{};
        imageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
        imageCreateInfo.pNext = nullptr;
        imageCreateInfo.flags;
        imageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
        imageCreateInfo.format = VK_FORMAT_R8G8B8A8_UINT;
        imageCreateInfo.extent = VkExtent3D{m_width, m_height, 1};
        imageCreateInfo.mipLevels = 1;
        imageCreateInfo.arrayLayers = 1;
        imageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
        imageCreateInfo.tiling = VK_IMAGE_TILING_LINEAR;
        imageCreateInfo.usage = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
        imageCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
        imageCreateInfo.queueFamilyIndexCount = 0;
        imageCreateInfo.pQueueFamilyIndices = nullptr;
        imageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
        if (VK_SUCCESS != vkCreateImage(m_device, &imageCreateInfo, nullptr, &m_image))
        {
            throw std::runtime_error("To create image is failed!");
        }

        // https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkMemoryAllocateInfo
        VkMemoryAllocateInfo memoryAllocationInfo;
        memoryAllocationInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
        memoryAllocationInfo.pNext = nullptr;
        memoryAllocationInfo.memoryTypeIndex = m_memroyTypeIndex;
        memoryAllocationInfo.allocationSize = m_width * m_height * 4;
        // https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#vkAllocateMemory
        if (VK_SUCCESS != vkAllocateMemory(m_device, &memoryAllocationInfo, nullptr, &m_imageMemory))
        {
            throw std::runtime_error("To allocate memory is failed!");
        }

        // https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#vkBindImageMemory
        if (VK_SUCCESS != vkBindImageMemory(m_device, m_image, m_imageMemory, 0))
        {
            throw std::runtime_error("To bind memory is failed!");
        }

        //https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VkImageViewCreateInfo
        VkImageViewCreateInfo imageViewCreateInfo{};
        imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        imageViewCreateInfo.pNext = nullptr;
        imageViewCreateInfo.flags = 0;
        imageViewCreateInfo.image = m_image;
        imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
        imageViewCreateInfo.format = VK_FORMAT_R8G8B8A8_UINT;
        imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
        imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
        imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
        imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
        imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
        imageViewCreateInfo.subresourceRange.levelCount = 1;
        imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
        imageViewCreateInfo.subresourceRange.layerCount = 1;
        
        if (VK_SUCCESS != vkCreateImageView(m_device, &imageViewCreateInfo, nullptr, &m_imageView))
        {
            throw std::runtime_error("To create image view is failed!");
        }

        VkFramebufferCreateInfo framebufferInfo{};
        framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
        framebufferInfo.renderPass = m_renderPass;
        framebufferInfo.attachmentCount = 1;
        framebufferInfo.pAttachments = &m_imageView;
        framebufferInfo.width = m_width;
        framebufferInfo.height = m_height;
        framebufferInfo.layers = 1;
        //https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#vkCreateFramebuffer
        if (VK_SUCCESS != vkCreateFramebuffer(m_device, &framebufferInfo, nullptr, &m_framebuffer)) {
                throw std::runtime_error("To create framebuffer is failed!");
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/935130.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【人工智能】5G-A技术及应用

文章目录 前言一、5G-A基本概念及产业进展1、5G-A概述2、移动通信发展历史&#xff1a;不断扩大联结规模&#xff0c;扩展业务边界的过程3、标准Ready:首版本R18将于2024年H1冻结4、标准Ready:IMT2020完成5G-A技术测试5、频谱Ready:超大带宽是实现万兆体验的基础6、5G-A全球商用…

与 Cursor AI 对话编程:2小时开发报修维修微信小程序

本文记录了如何通过与 Cursor AI 对话&#xff0c;全程不写一行代码的情况下&#xff0c;完成一个完整的报修小程序。整个过程展示了 AI 如何帮助我们&#xff1a; 生成代码 、解决问题、优化实现、完善细节。 先看一下效果图&#xff1a; 一、项目配置 首先我是这样和 AI 对…

多模态大语言模型 MLLM 部署微调实践

1 MLLM 1.1 什么是 MLLM 多模态大语言模型&#xff08;MultimodalLargeLanguageModel&#xff09;是指能够处理和融合多种不同类型数据&#xff08;如文本、图像、音频、视频等&#xff09;的大型人工智能模型。这些模型通常基于深度学习技术&#xff0c;能够理解和生成多种模…

机器学习:全面学习路径指南

摘要&#xff1a; 本文精心规划了一条从入门到精通机器学习的学习路线&#xff0c;详细涵盖了基础理论构建、核心技术栈掌握、主流算法学习、实践项目锻炼以及前沿领域探索等多个关键阶段。通过逐步深入各个层面&#xff0c;介绍必备的数学知识、编程工具、经典与现代机器学习算…

Kingbase V8R6 数据库自动(逻辑)备份、删除脚本-Linux

脚本说明 1.该脚本为Linux环境下自动备份、删除Kingbase数据库备份脚本&#xff08;逻辑备份&#xff09;&#xff1b; 2.执行脚本前&#xff0c;请先对脚本进行修改后&#xff0c;再使用。脚本效果 1.执行脚本时&#xff0c;若备份目录不存在&#xff0c;则自动创建备份目录…

网络应用技术 实验六:通过 DHCP 管理园区网 IP 地址(华为ensp)

一、实验简介 构建园区网&#xff0c;通过 DHCP 服务器为全网的用户主机提供 IP 地址。 二、实验目的 1 、理解 DHCP 的工作原理&#xff1b; 2 、掌握 DHCP 服务器的创建和配置方法&#xff1b; 3 、掌握将 VirtualBox 虚拟机引入 eNSP 的方法&#xff1b; …

Elasticsearch使用(2):docker安装es、基础操作、mapping映射

1 安装es 1.1 拉取镜像 docker pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/elasticsearch:7.17.3 1.2 运行容器 运行elasticsearch容器&#xff0c;挂载的目录给更高的权限&#xff0c;否则可能会因为目录权限问题导致启动失败&#xff1a; docker r…

Flink 核心知识总结:窗口操作、TopN 案例及架构体系详解

目录 一、FlinkSQL 的窗口操作 &#xff08;一&#xff09;窗口类型概述 &#xff08;二&#xff09;不同时间语义下窗口实践 EventTime&#xff08;事件时间&#xff09; ProcessTime&#xff08;处理时间&#xff09; 二、窗口 TopN 案例解析 三、Flink架构体系 &…

Vscode配置自动切换node版本

Vscode配置自动切换node版本 问题描述 开发环境安装了很多Node JS版本&#xff0c;项目经常切换也常常忘记了使用了什么版本&#xff0c;所以最好在打开项目terminal&#xff0c;安装依赖&#xff0c;启动项目前自动设置好版本 具体配置 .vscode/settings.json中,添加如下代…

【Linux 篇】Docker 的容器之海与镜像之岛:于 Linux 系统内探索容器化的奇妙航行

文章目录&#xff1a; 【Linux 篇】Docker 的容器之海与镜像之岛&#xff1a;于 Linux 系统内探索容器化的奇妙航行前言安装docker-centos7 【Linux 篇】Docker 的容器之海与镜像之岛&#xff1a;于 Linux 系统内探索容器化的奇妙航行 &#x1f4ac;欢迎交流&#xff1a;在学习…

leetcode108.将有序数组转换为二叉搜索树

标签&#xff1a;二叉搜索树 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵平衡二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,…

C# 探险之旅:第二节 - 定义变量与变量赋值

欢迎再次踏上我们的C#学习之旅。今天&#xff0c;我们要聊一个超级重要又好玩的话题——定义变量与变量赋值。想象一下&#xff0c;你正站在一个魔法森林里&#xff0c;手里拿着一本空白的魔法书&#xff08;其实就是你的代码编辑器&#xff09;&#xff0c;准备记录下各种神奇…

基于事件驱动的websocket简单实现

websocket的实现 什么是websocket&#xff1f; WebSocket 是一种网络通信协议&#xff0c;旨在为客户端和服务器之间提供全双工、实时的通信通道。它是在 HTML5 规范中引入的&#xff0c;可以让浏览器与服务器进行持久化连接&#xff0c;以便实现低延迟的数据交换。 WebSock…

libaom 源码分析:av1_rd_use_partition 函数

libaom libaom 是 AOMedia Video 1 (AV1) 视频编码格式的参考实现库,由 Alliance for Open Media (AOMedia) 开发和维护。AV1 是一个高效、开放、免专利授权的下一代视频编解码标准,设计目标是提供较高的视频压缩效率,同时适配各种分辨率、码率和平台。下载:git clone http…

如何恢复使用 Cursor 免费试用

当用户尝试创建过多免费试用账户时&#xff0c;会收到提示&#xff1a;“Too many free trial accounts used on this machine. Please upgrade to pro.” 这限制了用户的试用次数。AI大眼萌帮助大家绕过 Cursor 的设备指纹验证&#xff0c;以继续享受免费试用。 &#x1f6a8;…

【Excel学习记录】01-认识Excel

1.之前的优秀软件Lotus-1-2-3 默认公式以等号开头 兼容Lotus-1-2-3的公式写法&#xff0c;不用写等号 &#xff1a; 文件→选项→高级→勾选&#xff1a;“转换Lotus-1-2-3公式(U)” 备注&#xff1a;对于大范围手动输入公式可以使用该选项&#xff0c;否则请不要勾选&#x…

网络安全——防火墙

基本概念 防火墙是一个系统&#xff0c;通过过滤传输数据达到防止未经授权的网络传输侵入私有网络&#xff0c;阻止不必要流量的同时允许必要流量进入。防火墙旨在私有和共有网络间建立一道安全屏障&#xff0c;因为网上总有黑客和恶意攻击入侵私有网络来破坏&#xff0c;防火…

kafka进阶_4.kafka扩展

文章目录 一、Controller选举二、Kafka集成2.1、大数据应用场景2.1.1、Flume集成2.1.2、Spark集成2.1.3、Flink集成 2.2、Java应用场景(SpringBoot集成) 三、Kafka常见问题3.1、Kafka都有哪些组件&#xff1f;3.2、分区副本AR, ISR, OSR的含义&#xff1f;3.3、Producer 消息重…

OpenAI 12Days 第二天 强化微调(RFT):推动语言模型在科学研究中的应用

OpenAI 12Days 第二天 强化微调&#xff08;RFT&#xff09;&#xff1a;推动语言模型在科学研究中的应用 文章目录 OpenAI 12Days 第二天 强化微调&#xff08;RFT&#xff09;&#xff1a;推动语言模型在科学研究中的应用RFT的工作原理与应用领域案例研究&#xff1a;基因突变…

Go mysql驱动源码分析

文章目录 前言注册驱动连接器创建连接交互协议读写数据读数据写数据 mysqlConncontext超时控制 查询发送查询请求读取查询响应 Exec发送exec请求读取响应 预编译客户端预编译服务端预编译生成prepareStmt执行查询操作执行Exec操作 事务读取响应query响应exec响应 总结 前言 go…