当前位置: 首页 > news >正文

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

前言

        上一章深入分析了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/StoreVK_ATTACHMENT_STORE_OP_STORE,VK_ATTACHMENT_LOAD_OP_DONT_CARE,   // stencilLoad/StoreVK_ATTACHMENT_STORE_OP_DONT_CARE,VK_IMAGE_LAYOUT_UNDEFINED,         // initialLayoutVK_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,              // pInputAttachments1, &colorAttachmentRef,  // pColorAttachmentsnullptr,                 // pResolveAttachmentsnullptr,                 // pDepthStencilAttachment0, nullptr,              // pPreserveAttachments};

       渲染通道创建信息:

    VkRenderPassCreateInfo renderPassInfo{VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,nullptr, 0,1, &colorAttachment,  // pAttachments1, &subpass,          // pSubpasses0, 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.mrgr.cn/news/97165.html

相关文章:

  • 【408--考研复习笔记】操作系统----知识点速览=
  • MySQL 知识点详解(索引、存储引擎、事务与隔离级别、MVCC、锁机制、优化)
  • Linux信号——信号的产生(1)
  • 浅谈AI落地 - 文章推荐 - 混合推荐模型
  • 【NLP 53、投机采样加速推理】
  • MySQL:库表操作
  • pat学习笔记
  • 【MySQL】01.MySQL环境安装
  • OpenVLA-OFT——微调VLA的三大关键设计:支持动作分块的并行解码、连续动作表示以及L1回归目标
  • 操作系统知识点(一)
  • [C++面试] new、delete相关面试点
  • 论文阅读笔记:Denoising Diffusion Implicit Models (4)
  • 从代码上深入学习GraphRag
  • YOLO 获取 COCO 指标终极指南 | 从标签转换到 COCOAPI 评估 (训练/验证) 全覆盖【B 站教程详解】
  • hi3516cv610通过menuconfig关闭的宏记录
  • 欧几里得算法求最大公约数、最小公倍数
  • UBUNTU编译datalink
  • 大模型学习四:‌DeepSeek Janus-Pro 多模态理解和生成模型 本地部署指南(折腾版)
  • 列表与列表项
  • 蓝桥杯 小明的背包1 小兰的神秘礼物 01背包问题 模板 C++