vulkanscenegraph显示倾斜模型(5.6)-vsg::RenderGraph的创建

news2025/7/18 12:46:23

前言

        上一章深入分析了vsg::CommandGraph的创建过程及其通过子场景遍历实现Vulkan命令录制的机制。本章将在该基础上,进一步探讨Vulkan命令录制中的核心封装——vsg::RenderGraph。作为渲染流程的关键组件,RenderGraph封装了vkCmdBeginRenderPass和vkCmdEndRenderPass的核心功能,RecordTraversal会在这两个关键调用之间遍历并处理其子节点。同时本章内容将涵盖vsg::FrameBuffer(封装VkFramebuffer)、vsg::RenderPass(封装VkRenderPass)和vsg::ImageView(封装VkImageView)等重要概念。


目录

  • 1 vsg::RenderPass
  • 2 vsg::FrameBuffer
  • 3 vsg::RenderGraph

1 vsg::RenderPass

       vsg::RenderPass 是 VulkanSceneGraph (VSG) 框架中的核心类,它封装了 Vulkan 的渲染通道(Render Pass),用于定义渲染过程中帧缓冲区附件的结构和组织方式。

1.1 VkRenderPass的创建

       颜色附件描述:

    VkAttachmentDescription colorAttachment
    {
        0, VK_FORMAT_B8G8R8A8_SRGB,
        VK_SAMPLE_COUNT_1_BIT,
        VK_ATTACHMENT_LOAD_OP_CLEAR,       // Load/Store
        VK_ATTACHMENT_STORE_OP_STORE,
        VK_ATTACHMENT_LOAD_OP_DONT_CARE,   // stencilLoad/Store
        VK_ATTACHMENT_STORE_OP_DONT_CARE,
        VK_IMAGE_LAYOUT_UNDEFINED,         // initialLayout
        VK_IMAGE_LAYOUT_PRESENT_SRC_KHR    // finalLayout
    };

    VkAttachmentReference colorAttachmentRef
    {
        0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
    };

       子通道描述:

    VkSubpassDescription subpass
    {
        0, VK_PIPELINE_BIND_POINT_GRAPHICS,
        0, nullptr,              // pInputAttachments
        1, &colorAttachmentRef,  // pColorAttachments
        nullptr,                 // pResolveAttachments
        nullptr,                 // pDepthStencilAttachment
        0, nullptr,              // pPreserveAttachments
    };

       渲染通道创建信息:

    VkRenderPassCreateInfo renderPassInfo
    {
        VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
        nullptr, 0,
        1, &colorAttachment,  // pAttachments
        1, &subpass,          // pSubpasses
        0, nullptr            // pDependencies
    };

       创建渲染通道:

    VkRenderPass renderPass = nullptr;
    VkResult result = vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass);
    if (result != VK_SUCCESS)
    {
        printf("Failed to create render-pass.\n");
        return 1;
    }

1.2 vsg::RenderPass的创建

       在5.1章(vulkanscenegraph显示倾斜模型(5.1)-窗口创建-CSDN博客)中深入探讨了窗口的创建过程,vsg中窗口相关的基类为vsg::Window,RenderPass的创建与窗口密切相关,如下为vsg::Window中初始化vsg::RenderPass相关代码:

void Window::_initRenderPass()
{
    if (!_device) _initDevice();

    bool requiresDepthRead = (_traits->depthImageUsage & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) != 0;

    if (_framebufferSamples == VK_SAMPLE_COUNT_1_BIT)
    {
        _renderPass = vsg::createRenderPass(_device, _imageFormat.format, _depthFormat, requiresDepthRead);
    }
    else
    {
        _renderPass = vsg::createMultisampledRenderPass(_device, _imageFormat.format, _depthFormat, _framebufferSamples, requiresDepthRead);
    }
}

       在场景创建的过程中,vsg::RenderGraph 在初始化时会获取或创建 vsg::RenderPass 对象,vsg::RenderPass有三个来源,示例代码如下:

RenderPass* RenderGraph::getRenderPass()
{
    if (renderPass)
    {
        return renderPass;
    }
    else if (framebuffer)
    {
        return framebuffer->getRenderPass();
    }
    else if (window)
    {
        return window->getOrCreateRenderPass();
    }
    return nullptr;
}

2 vsg::FrameBuffer

       vsg::FrameBuffer​封装了VkFramebuffer,用作与窗口关联的渲染目标或用于渲染到纹理。

2.1 VkFrameBuffer的创建

       VkFrameBuffer的创建分为VkImageView的创建与VkFrameBuffer的创建两个过程。

       获取所有图像:从VkSwapChain中获取VkImage分两步调用vkGetSwapchainImagesKHR函数:首先传入nullptr作为第四个参数以获取交换链中的图像数量,然后再次调用该函数来实际获取所有VkImage对象。

    uint32_t imageCount = 0;
    vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr);

    std::vector<VkImage> swapChainImages(imageCount);
    vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data());

       创建图像视图:在vulkan中,图像视图提供了对图像的访问接口,图像视图的创建示例代码如下:

    VkImageViewCreateInfo createInfo
    {
        VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
        nullptr, 0,
        nullptr, VK_IMAGE_VIEW_TYPE_2D,
        VK_FORMAT_B8G8R8A8_SRGB,
        { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
          VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY },
        { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
    };

    std::vector<VkImageView> swapchainImageViews(swapChainImages.size());
    for (size_t i = 0; i < swapchainImageViews.size(); ++i)
    {
        createInfo.image = swapChainImages[i];
        VkResult result = vkCreateImageView(
            app.getDevice(), &createInfo, nullptr, &swapchainImageViews[i]);
        if (result != VK_SUCCESS)
        {
            printf("Failed to create image view: %zd.\n", i);
            return 1;
        }
    }

       创建VkFramebuffer:下述代码表示为交换链(Swapchain)的每个图像视图(VkImageView)创建一个帧缓冲(VkFramebuffer),并建立它们与渲染流程(VkRenderPass)的关联,其中1024和768分别表示对应影像的宽高。VkRenderPass 定义了渲染流程的附件结构和子流程(Subpass),但不绑定具体图像,VkFramebuffer 将 VkRenderPass 的抽象附件绑定到具体的 VkImageView,使渲染操作可以实际写入图像。

    std::vector<VkFramebuffer> framebuffers(swapchainImageViews.size());
    for (size_t i = 0; i < framebuffers.size(); ++i)
    {
        VkImageView attachments[] = { swapchainImageViews[i] };
        VkFramebufferCreateInfo framebufferInfo
        {
            VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
            nullptr, 0,
            renderPass,
            1, attachments,
            1024, 768, 1
        };
        vkCreateFramebuffer(device, &framebufferInfo, nullptr, &framebuffers[i]);
    }

2.2 vsg::FrameBuffer的封装

       在5.2章(vulkanscenegraph显示倾斜模型(5.2)-交换链-CSDN博客)中深入探讨了交换链的创建过程,与交换链创建紧密相关的有VkImageView与VkFramebuffer的创建。 

      vsg中Window.cpp文件中372-339行代码如下,为Window::buildSwapchain()函数中,创建vsg::ImageView与vsg::Framebuffer的部分。

auto& imageViews = _swapchain->getImageViews();

_availableSemaphore = vsg::Semaphore::create(_device, _traits->imageAvailableSemaphoreWaitFlag);

size_t initial_indexValue = imageViews.size();
for (size_t i = 0; i < imageViews.size(); ++i)
{
    vsg::ImageViews attachments;
    if (_multisampleImageView)
    {
        attachments.push_back(_multisampleImageView);
    }
    attachments.push_back(imageViews[i]);

    if (_multisampleDepthImageView)
    {
        attachments.push_back(_multisampleDepthImageView);
    }
    attachments.push_back(_depthImageView);

    ref_ptr<Framebuffer> fb = Framebuffer::create(_renderPass, attachments, _extent2D.width, _extent2D.height, 1);

    ref_ptr<Semaphore> ias = vsg::Semaphore::create(_device, _traits->imageAvailableSemaphoreWaitFlag);

    //_frames.push_back({multisampling ? _multisampleImageView : imageViews[i], fb, ias});
    _frames.push_back({imageViews[i], fb, ias});
    _indices.push_back(initial_indexValue);
}

       如下代码为vsg中Framebuffer的构造函数,在构造函数中实现了VkFramebuffer的创建。

Framebuffer::Framebuffer(ref_ptr<RenderPass> renderPass, const ImageViews& attachments, uint32_t width, uint32_t height, uint32_t layers) :
    _device(renderPass->device),
    _renderPass(renderPass),
    _attachments(attachments),
    _width(width),
    _height(height),
    _layers(layers)
{
    auto deviceID = _device->deviceID;

    std::vector<VkImageView> vk_attachments;
    for (auto& attachment : attachments)
    {
        vk_attachments.push_back(attachment->vk(deviceID));
    }

    VkFramebufferCreateInfo framebufferInfo = {};
    framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
    framebufferInfo.flags = 0;
    framebufferInfo.renderPass = *_renderPass;
    framebufferInfo.attachmentCount = static_cast<uint32_t>(vk_attachments.size());
    framebufferInfo.pAttachments = vk_attachments.data();
    framebufferInfo.width = width;
    framebufferInfo.height = height;
    framebufferInfo.layers = layers;

    if (VkResult result = vkCreateFramebuffer(*_device, &framebufferInfo, nullptr, &_framebuffer); result != VK_SUCCESS)
    {
        throw Exception{"Error: vsg::Framebuffer::create(...) Failed to create VkFramebuffer.", result};
    }
}

3 vsg::RenderGraph

      本章在上章(vulkanscenegraph显示倾斜模型(5.5)-CommandGraph的创建-CSDN博客)场景图构建基础上,继续深入vsg::RenderGraph的创建:

       vsg::RenderGraph中通过访问者模式(accept函数)实现场景的遍历,进而实现命令的录制,其核心过程如下(RenderGraph.cpp中146-151行代码):

    vkCmdBeginRenderPass(vk_commandBuffer, &renderPassInfo, contents);

    // traverse the subgraph to place commands into the command buffer.
    traverse(recordTraversal);

    vkCmdEndRenderPass(vk_commandBuffer);

文末:本章在上一篇文章的基础上,继续深入vsg场景图中另一关键的节点vsg::RenderGraph,RecordTraversal遍历场景图过程中,RenderGraph的子节点会在vkCmdBeginRenderPass和vkCmdEndRenderPass之间被遍历访问。同时本章介绍了vsg::FrameBuffer(封装VkFramebuffer)、vsg::RenderPass(封装VkRenderPass)和vsg::ImageView(封装VkImageView)三个关键概念,vsg::RenderPass定义渲染流程,vsg::ImageView提供图像资源访问接口,vsg::FrameBuffer将二者绑定为具体渲染目标。下章将介绍vulkan图形渲染过程中另一关键对象VkPipeline,以及vsg对其的封装vsg::GraphicsPipeline。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于阿里云可观测产品构建企业级告警体系的通用路径与最佳实践

前言 1.1 日常生活中的告警 任何连续稳定运行的生产系统都离不开有效的监控与报警机制。通过监控&#xff0c;我们可以实时掌握系统和业务的运行状态&#xff1b;而报警则帮助我们及时发现并响应监控指标及业务中的异常情况。 在日常生活中&#xff0c;我们也经常遇到各种各样…

二叉树的ACM板子(自用)

package 二叉树的中序遍历;import java.util.*;// 定义二叉树节点 class TreeNode {int val; // 节点值TreeNode left; // 左子节点TreeNode right; // 右子节点// 构造函数TreeNode(int x) {val x;} }public class DMain {// 构建二叉树&#xff08;层序遍历方式&…

架构思维:查询分离 - 表数据量大查询缓慢的优化方案

文章目录 Pre引言案例何谓查询分离&#xff1f;何种场景下使用查询分离&#xff1f;查询分离实现思路1. 如何触发查询分离&#xff1f;方式一&#xff1a; 修改业务代码&#xff1a;在写入常规数据后&#xff0c;同步建立查询数据。方式二&#xff1a;修改业务代码&#xff1a;…

Qt进阶开发:QFileSystemModel的使用

文章目录 一、QFileSystemModel的基本介绍二、QFileSystemModel的基本使用2.1 在 QTreeView 中使用2.2 在 QListView 中使用2.3 在 QTableView 中使用 三、QFileSystemModel的常用API3.1 设置根目录3.2 过滤文件3.2.1 仅显示文件3.2.2 只显示特定后缀的文件3.2.3 只显示目录 四…

【C语言】字符串处理函数:strtok和strerror

在C语言中&#xff0c;字符串处理是编程的基础之一。本文将详细讲解两个重要的字符串处理函数&#xff1a;strtok和strerror 一、strtok函数 strtok函数用于将字符串分割成多个子串&#xff0c;这些子串由指定的分隔符分隔。其原型定义如下&#xff1a; char *strtok(char *s…

go语言:开发一个最简单的用户登录界面

1.用deepseek生成前端页面&#xff1a; 1.提问&#xff1a;请你用html帮我设计一个用户登录页面&#xff0c;要求特效采用科技感的背景渲染加粒子流动&#xff0c;用css、div、span标签&#xff0c;并给出最终合并后的代码。 生成的完整代码如下&#xff1a; <!DOCTYPE h…

《Maven高级应用:继承聚合设计与私服Nexus实战指南》

一、 Maven的继承和聚合 1.什么是继承 Maven 的依赖传递机制可以一定程度上简化 POM 的配置&#xff0c;但这仅限于存在依赖关系的项目或模块中。当一个项目的多个模块都依赖于相同 jar 包的相同版本&#xff0c;且这些模块之间不存在依赖关系&#xff0c;这就导致同一个依赖…

C语言数字分隔题目

一、题目引入 编写一个程序,打印出从用户输入的数字开始,递减到1的序列。要求每次打印一行,数字之间用逗号分隔,最后一个数字后面没有逗号。 二、代码展示 三、运行结果 四、思路分析 1.先用一个for循环对输入的数字进行递减 2.再对for循环里面的数字进行筛选 如果大于1 …

ARM-外部中断,ADC模数转换器

根据您提供的图片&#xff0c;我们可以看到一个S3C2440微控制器的中断处理流程图。这个流程图展示了从中断请求源到CPU的整个中断处理过程。以下是流程图中各个部分与您提供的寄存器之间的关系&#xff1a; 请求源&#xff08;带sub寄存器&#xff09;&#xff1a; 这些是具体的…

git克隆数据失败

场景&#xff1a;当新到一家公司&#xff0c;然后接手了上一个同时的电脑&#xff0c;使用git克隆代码一直提示无法访问&#xff0c;如图 原因&#xff1a;即使配置的新的用户信息。但是window记录了上一个同事的登录信息&#xff0c;上一个同事已经被剔除权限&#xff0c;再拉…

自动化备份全网服务器数据平台

自动化备份全网服务器数据平台 项目背景知识 总体需求 某企业里有一台Web服务器&#xff0c;里面的数据很重要&#xff0c;但是如果硬盘坏了数据就会丢失&#xff0c;现在领导要求把数据做备份&#xff0c;这样Web服务器数据丢失在可以进行恢复。要求如下&#xff1a;1.每天0…

AI Agent系列(八) -基于ReAct架构的前端开发助手(DeepSeek)

AI Agent系列【八】 项目目标一、核心功能设计二、技术栈选择三、Python实现3.1 设置基础环境3.2 定义AI前端生成的类3.4 实例化3.5 Flask路由3.6 主程序执行 四、 功能测试 项目目标 开发一个能够协助HTMLJSCSS前端设计的AI Agent&#xff0c;通过在网页中输入相应的问题&am…

一文学会云服务器配置Milvus向量数据库

服务器准备 首先&#xff0c;我们需要进行服务器的准备&#xff0c;这里准备的是RTX-4090服务器 连接我们已经创建好的服务器&#xff0c;这里可使用MobaXterm进行ssh连接 ssh funhpcIP地址 一键完成Docker配置 注&#xff1a;docker的旧版本不一定被称为docker&#xff0c;doc…

19685 握手问题

19685 握手问题 ⭐️难度&#xff1a;简单 &#x1f31f;考点&#xff1a;2024、省赛、数学 &#x1f4d6; &#x1f4da; package test ;import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner scanner new Scanner(System.in);…

【MySQL数据库】锁机制

概述 锁&#xff1a;是计算机协调多个进程或者线程并发访问某一资源的机制。在数据库中&#xff0c;除了传统的计算资源&#xff08;CPU、RAM、IO&#xff09;的争用以外。数据也是一种供多用户共享的资源。如何保证数据的并发访问的一致性、有效性是所有数据库必须解决的一个…

react redux的学习,单个reducer

redux系列文章目录 一 什么redux&#xff1f; redux是一个专门用于做状态管理的JS库(不是react插件库)。它可以用在react, angular, vue等项目中, 但基本与react配合使用。集中式管理react应用中多个组件共享的状 简单来说&#xff0c;就是存储页面的状态值的一个库&#xf…

分布式控制技术赋能智慧工厂精准控制研究

摘要&#xff1a;本文聚焦于分布式控制技术在智慧工厂精准控制中的应用。详细阐述了分布式控制系统&#xff08;DCS&#xff09;、边缘计算机、边边协同技术以及分布式计算等关键要素在实现精准控制中的作用机制。同时&#xff0c;分析了云边协同模式存在占用带宽、单点故障、数…

清明节里清明菜:软萩(拟人版介绍)

好像人们无论过任何节&#xff0c;总是离不开吃 清明节里吃清明菜&#xff0c;你采摘了吗&#xff1f; 姓名 软萩&#xff0c;也叫鼠麴草、清明菜、软雀&#xff0c;学名鼠曲草。 一些地方性小名&#xff08;防止大家找不到组织&#xff0c;已知的都附上&#xff09;&#xf…

JavaWeb学习--MyBatis-Plus整合SpringBoot的ServiceImpl方法(增加,修改与删除部分)

接下来是常用的增加&#xff0c;修改以及删除部分 首先是增加部分&#xff0c;增加一个新的数据 Testpublic void testInsert() {// 添加一个新用户记录Student s new Student();s.setName("NewStudent");s.setAge(25);boolean saved studentService.save(s);//可以…

AiCube 试用 - 创建流水灯工程

AiCube 试用 - 创建流水灯工程 本文介绍了 Aiapp-ISP 仿真调试平台软件的 AiCube 工具&#xff0c;实现流水灯工程的快速创建的主要流程。 下载运行 下载 最新版 AIapp-ISP 软件&#xff1b; 解压并打开该软件&#xff0c;右侧操作界面选择并进入 Keil 仿真设置 标签项&…