当前位置:网站首页>Vulkan-实践第一弹
Vulkan-实践第一弹
2022-07-02 23:37:00 【很久没安静的回忆了】
上一篇文章中,我们浅析了Vulkan对传统图形API的优势,主要就是在其性能和精细化操控GPU上,具体可参考Vulkan-性能及精细化
今天我们就来用个简单的例子,亲身感受下Vulkan的开发“魅力”。
#include <iostream>
#include <chrono>
#include <cstring>
#include <glm/mat4x4.hpp>
#include <glm/gtx/transform.hpp>
#include "VK_UniformBuffer.h"
#include "VK_Context.h"
#include "VK_Pipeline.h"
#include "VK_DynamicState.h"
using namespace std;
const std::vector<uint32_t> indices = {
0, 1, 2
};
const std::vector<float> vertices = {
0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f,
0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.5f,
-0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 0.5
};
VK_Context *context = nullptr;
VK_Pipeline *pipeline = nullptr;
// 窗口大小改变时通过onFrameSizeChanged更新窗口大小
void onFrameSizeChanged(int width, int height)
{
pipeline->getDynamicState()->applyDynamicViewport({0, 0, (float)width, (float)height, 0, 1});
}
//实时更新uniform值
uint32_t updateUniformBufferData(char *&data, uint32_t size)
{
static auto start = std::chrono::high_resolution_clock::now();
auto current = std::chrono::high_resolution_clock::now();
float time = std::chrono::duration<float, std::chrono::seconds::period>
(current - start).count();
glm::mat4 model = glm::rotate(glm::mat4(1.0f), time * glm::radians(30.0f), glm::vec3(0.0f, 0.0f,
1.0f));
memcpy(data, &model[0][0], size);
return sizeof(model);
}
int main()
{
VK_ContextConfig config;
config.debug = true;
config.name = "Uniform Demo";
context = createVkContext(config);
context->createWindow(640, 640, true);
context->setOnFrameSizeChanged(onFrameSizeChanged);
VK_Context::VK_Config vkConfig;
context->initVulkanDevice(vkConfig);
auto shaderSet = context->createShaderSet();
shaderSet->addShader("../jianghuxiuxing/shader/mvp/vertex.spv", VK_SHADER_STAGE_VERTEX_BIT);
shaderSet->addShader("../jianghuxiuxing/shader/mvp/fragmeng.spv", VK_SHADER_STAGE_FRAGMENT_BIT);
shaderSet->appendAttributeDescription(0, sizeof (float) * 3, VK_FORMAT_R32G32B32_SFLOAT, 0);
shaderSet->appendAttributeDescription(1, sizeof (float) * 4, VK_FORMAT_R32G32B32A32_SFLOAT,
sizeof(float) * 3);
shaderSet->appendVertexInputBindingDescription(7 * sizeof(float), 0, VK_VERTEX_INPUT_RATE_VERTEX);
VkDescriptorSetLayoutBinding uniformBinding = VK_ShaderSet::createDescriptorSetLayoutBinding(0,
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT);
shaderSet->addDescriptorSetLayoutBinding(uniformBinding);
if (!shaderSet->isValid()) {
std::cerr << "invalid shaderSet" << std::endl;
shaderSet->release();
context->release();
return -1;
}
auto ubo = shaderSet->addUniformBuffer(0, sizeof(float) * 16);
ubo->setWriteDataCallback(updateUniformBufferData);
context->initVulkanContext();
pipeline = context->createPipeline(shaderSet);
pipeline->getDynamicState()->addDynamicState(VK_DYNAMIC_STATE_VIEWPORT);
pipeline->create();
pipeline->getDynamicState()->applyDynamicViewport({0, 0, 480, 480, 0, 1});
auto buffer = context->createVertexBuffer(vertices, 3 + 4, indices);
pipeline->addRenderBuffer(buffer);
context->createCommandBuffers();
context->run();
context->release();
return 0;
}
Vertex Shader
#version 450
layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;
layout(location = 0) out vec4 fragColor;
layout(binding = 0) uniform UniformBufferObject {
mat4 model;
} mvp;
void main() {
gl_Position = mvp.model * vec4(position, 1.0);
fragColor = color;
}
Fragment Shader
#version 450
layout(location = 0) in vec4 fragColor;
layout(location = 0) out vec4 outColor;
void main() {
outColor = fragColor;
}
效果:
从上面的代码实现可以看出Vulkan在加载spv字节码,显示指定shader各属性方面都做了更繁琐的限制,开发者需要关注的程序控制和执行时机也变的更多了,这也印证了我们上一篇文章里说的Vulkan摒弃了传统图形API的大包大揽,而将更多的校验和权利下放给了程序设计者。
Vulkan的渲染流程
- 创建程序窗口
- 初始化Vulkan实例 - vulkan库的初始化
- 初始化输出表面 - 指明渲染显示目的地
- 选择满足要求的物理设备(通常多个,对于渲染程序,通常需要物理设备支持图形队列以及表面呈现队列)
- 创建逻辑设备 - 根据指定物理设备即可创建逻辑设备(逻辑设备和物理设备相对应,但并不唯一)
- 创建指令池对象 - vulkan中指令提交和传输需要通过指令缓冲来操作,对于指令缓冲需要构建指令池对象
- 创建交换链 - vulkan中不存在默认帧缓冲的概念,需要一个缓存渲染缓冲的组件,这就是交换链。交换链本质上一个包含了若干等待呈现的图像的队列
- 创建交换队列图像视图 - 有了交换链还不够,需要一组图形来保存渲染数据
- 创建渲染通道 - 渲染通道用于表示帧缓冲,其是子通道以及子通道关系的集合。深度模板附件、颜色附件、帧附件都是在此阶段被创建的
- 创建描述符布局 - 描述符是一个特殊的不透明的着色器变量,着色器使用它以间接的方式访问缓冲区和图像资源。描述符集合是描述一个管线使用到的描述符集合。描述符布局则用于刻画其布局。
- 创建管线布局 - 管线布局包含一个描述符集合布局的列表
- 创建帧缓冲 - 作为附件的图像依赖交换链用于呈现时返回的图像。这意味着我们必须为交换链中的所有图像创建一个帧缓冲区,并在绘制的时候使用对应的图像。其附件必须和渲染通道中使用的附件相匹配。
- 创建描述符池 -描述符需要从池中分配,不能直接创建
- 创建描述符集 - 描述符池是根据交换链帧个数以及Shader中描述符数量和数据来创建的,Shader属性类型和其中涉及的uninform、location等信息是在这个阶段被传入的
- 分配和更行描述符集 - 交换链帧个数、uniform数据以及图形视图是在这个阶段被处理的
- 创建管线 - 根据Shader、管线布局、渲染通道以及其他相关信息即可构造管线(需要设置各种属性关联的Shader,顶点输入格式 ,视口状态,光栅化,多重采样可选等)
- 创建命令缓冲 - 根据命令池、渲染通道、交换链帧个数即可分配并使用命令缓冲,其中对管线的绑定、描述符集的绑定以及开始和结束渲染通道是在这个阶段完成的。
- 渲染循环-从交换链中取图像(利用 vkAcquireNextImageKHR),更新uniform数据- vkMapMemory、vkUnmapMemory,提交指令缓冲 (利用vkQueueSubmit),图像回传交换链作呈现。(这个过程非常复杂,由于Vulkan的多线程需要保证同步等)
- 管线重建-管线并不始终有效,如果渲染呈现丢失或者窗口大小发生变化或者管线配置发生变化时都需要重新构造交换链和管线。(相关的节点也需要重建,比如交换链,渲染通道,缓冲池等)
边栏推荐
- Multiprocess programming (V): semaphores
- Which software can translate an English paper in its entirety?
- UART、RS232、RS485、I2C和SPI的介绍
- NC50965 Largest Rectangle in a Histogram
- [shutter] Introduction to the official example of shutter Gallery (learning example | email application | retail application | wealth management application | travel application | news application | a
- Multiprocess programming (4): shared memory
- Multi process programming (III): message queue
- NC24325 [USACO 2012 Mar S]Flowerpot
- Multiprocess programming (I): basic concepts
- Pageoffice - bug modification journey
猜你喜欢
University of Oslo: Li Meng | deep reinforcement learning based on swing transformer
How SQLSEVER removes data with duplicate IDS
mm中的GAN模型架构
AttributeError: ‘tuple‘ object has no attribute ‘layer‘问题解决
Shell implements basic file operations (cutting, sorting, and de duplication)
多进程编程(二):管道
What are the recommended thesis translation software?
Pageoffice - bug modification journey
MySQL 23道经典面试吊打面试官
An excellent orm in dotnet circle -- FreeSQL
随机推荐
Use Jenkins II job
Form form instantiation
JSON conversion tool class
【luogu P4320】道路相遇(圆方树)
Linux Software: how to install redis service
[shutter] image component (the placeholder | transparent_image transparent image plug-in is loaded into the memory)
Explain in detail the significance of the contour topology matrix obtained by using the contour detection function findcontours() of OpenCV, and how to draw the contour topology map with the contour t
Where can I check the foreign literature of economics?
Detailed explanation of pod life cycle
Which software can translate an English paper in its entirety?
Question e: merged fruit -noip2004tgt2
Nc50528 sliding window
Program analysis and Optimization - 9 appendix XLA buffer assignment
Two common methods and steps of character device registration
Centos7 one click compilation to build MySQL script
CMake基本使用
Maya fishing house modeling
Multiprocess programming (II): Pipeline
Go custom sort
FAQ | FAQ for building applications for large screen devices