操作系统:Windows8.1

显卡:Nivida GTX965M

开发工具:Visual Studio 2017


General structure

在上一节中,我们创建了一个正确配置、可运行的的Vulkan应用程序,并使用测试代码进行了测试。本节中我们从头开始,使用如下代码构建一个基于GLFW的Vulkan应用程序原型框架的雏形。

#include <vulkan/vulkan.h>

#include <iostream>
#include <stdexcept>
#include <functional> class HelloTriangleApplication {
public:
void run() {
initVulkan();
mainLoop();
cleanup();
} private:
void initVulkan() { } void mainLoop() { } void cleanup() { }
}; int main() {
HelloTriangleApplication app; try {
app.run();
} catch (const std::runtime_error& e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
} return EXIT_SUCCESS;
}

首先从LunarG SDK中添加Vulkan头文件,它提供了购机爱你Vulkan应用程序需要的函数、结构体、和枚举。我们包含stdexceptiostream头文件用于抛出异常信息,而functional头文件用于资源管理部分支持lambda表达式。

程序被封装到一个类中,该类结构将会存储Vulkan私有成员对象,并添加基本的函数来初始化他们。首先会从initVulkan函数开始调用。当一切准备好,我们进入主循环开始渲染帧。我们将会加入mainLoop函数包含loop循环调用,该循环调用直到GLFW窗体管理才会停止。当窗体关闭并且mainLoop返回时,我们需要释放我们已经申请过的任何资源,该清理逻辑在cleanup函数中去定义。

程序运行期间,如果发生了任何严重的错误异常,我们会抛出std::runtime_error 并注明异常描述信息,这个异常信息会被main函数捕获及打印提示。很快你将会遇到一个抛出error的例子,是关于Vulkan应用程序不支持某个必要的扩展功能。

基本上在之后的每一个小节中都会从initVulkan函数中增加一个新的Vulkan函数调用,增加的函数会产生Vulkan objects 并保存为类的私有成员,请记得在cleanup中进行资源的清理和释放。

Resource management


我们知道通过malloc分配的每一个内存快在使用完之后都需要free内存资源,每一个我们创建的Vulkan object不在使用时都需要明确的销毁。在C++中可以利用<memory> 完成 auto 资源管理,但是在本节中,选择明确编写所有的内存的分配和释放操作,其主要原因是Vulkan的设计理念就是明确每一步操作,清楚每一个对象的生命周期,避免可能存在的未知代码造成的异常。

当然在本节之后,我们可以通过重载std::shared_ptr来实现auto 资源管理。对于更大体量的Vulkan程序,建议遵循RAII的原则维护资源的管理。

Vulkan对象可以直接使用vkCreateXXX系函数创建,也可以通过具有vkAllocateXXX等功能的一个对象进行分配。确保每一个对象在不使用的时候调用vkDestroyXXXvkFreeXXX销毁、释放对应的资源。这些函数的参数通常因不同类型的对象而不同,但是他们共享一个参数:pAllocator。这是一个可选的参数,Vulkan允许我们自定义内存分配器。我们将在本教程忽略此参数,始终以nullptr作为参数。

Integrating GLFW


如果我们开发一些不需要基于屏幕显示的程序,那么纯粹的Vulkan本身可以完美的支持开发。但是如果创建一些让人兴奋的可视化的内容,我们就需要引入窗体系统GLFW,并将#include <vulkan/vulkan.h> 进行相应的替换。

#define GLFW_INCLUDE_VULKAN
#include <GLFW/glfw3.h>

在新版本的GLFW中已经提供了Vulkan相关的支持,详细的使用建议参阅官方资料。

通过替换,将会使用GLFW对Vulkan的支持,并自动加载Vulkan的头文件。在run函数中添加一个initWindow函数调用,并确保在其他函数调用前优先调用。我们将会通过该函数完成GLFW的窗体初始化工作。

void run() {
initWindow();
initVulkan();
mainLoop();
cleanup();
} private:
void initWindow() { }

initWindow中的第一个调用是glfwInit(),它会初始化GLFW库。因为最初GLFW是为OpenGL创建上下文,所以在这里我们需要告诉它不要调用OpenGL相关的初始化操作。

glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

特别注意窗口大小的设置,稍后我们会调用,现在使用另一个窗口提示来仅用它。

glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

现在剩下的就是创建实际的窗体。添加一个GLFWwindow*窗体,私有类成员存储其引用并初始化窗体:

window = glfwCreateWindow(, , "Vulkan", nullptr, nullptr);

前三个参数定义窗体的宽度、高度和Title。第四个参数允许制定一个监听器来打开窗体,最后一个参数与OpenGL有关,我们选择nullptr。

使用常量代替硬编码宽度和高度,因为我们在后续的内容中会引用该数值多次。在HelloTriangleApplication类定义之上添加以下几行:

const int WIDTH = ;
const int HEIGHT = ;

并替换窗体创建的代码语句为:

window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);

你现在应该有一个如下所示的initWindow函数:

void initWindow() {
glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr);
}

保持程序运行,直到发生错误或者窗体关闭,我们需要向mainLoop函数添加事件循环,如下所示:

void mainLoop() {
while (!glfwWindowShouldClose(window)) {
glfwPollEvents();
}
}

这段代码应该很容易看懂。它循环并检查GLFW事件,直到按下X按钮,或者关闭窗体。该循环结构稍后会调用渲染函数。

一旦窗体关闭,我们需要通过cleanup函数清理资源、结束GLFW本身。

void cleanup() {
glfwDestroyWindow(window); glfwTerminate();
}

运行程序,我们应该会看到一个名为Vulkan的白色窗体,直到关闭窗体终止应用程序。

ok,到现在我们已经完成了一个Vulkan程序的骨架原型,在下一小节我们会创建第一个Vulkan Object!

获取工程代码 GitHubcheckout

Vulkan Tutorial 02 编写Vulkan应用程序框架原型的更多相关文章

  1. MFC应用程序框架入门(转)

    1 MFC概述 顾名思意,MFC应用程序框架是以MFC作为框架基础的,以此程序框架模式搭建起来的应用程序在程序结构组织上是完全不同于以前的Win32 SDK编程方式的.自20世纪90年代初问世以来,M ...

  2. [译]Vulkan教程(02)概况

    [译]Vulkan教程(02)概况 这是我翻译(https://vulkan-tutorial.com)上的Vulkan教程的第2篇. This chapter will start off with ...

  3. 从零开始编写自己的C#框架(25)——网站部署

    导航 1.关掉访问保护 2.发布网站 3.复制网站到服务器 4.添加新网站 5.设置网站访问权限 6.设置文件夹访问权限 7.控制可更新文件夹执行权限 8.设置“应用程序池”.net版本与模式 9.附 ...

  4. 从零开始编写自己的C#框架(20)——框架异常处理及日志记录

    最近很忙,杂事也多,所以开发本框架也是断断续续的,终于在前两天将前面设定的功能都基本完成了,剩下一些小功能遗漏的以后发现再补上.接下来的章节主要都是讲解在本框架的基础上进行开发的小巧. 本框架主要有四 ...

  5. 从零开始编写自己的C#框架(17)——Web层后端首页

    后端首页是管理员登陆后进入的第一个页面,主要是显示当前登陆用户信息.在线人数.菜单树列表.相关功能按键和系统介绍.让管理员能更方便的找到息想要的内容. 根据不同系统的需要,首页会显示不同的内容,比如显 ...

  6. [Hadoop in Action] 第4章 编写MapReduce基础程序

    基于hadoop的专利数据处理示例 MapReduce程序框架 用于计数统计的MapReduce基础程序 支持用脚本语言编写MapReduce程序的hadoop流式API 用于提升性能的Combine ...

  7. 应用程序框架实战三十六:CRUD实战演练介绍

    从本篇开始,本系列将进入实战演练阶段. 前面主要介绍了一些应用程序框架的概念和基类,本来想把所有概念介绍完,再把框架内部实现都讲完了,再进入实战,这样可以让初学者基础牢靠.不过我的精力很有限,文章进度 ...

  8. 应用程序框架实战三十四:数据传输对象(DTO)介绍及各类型实体比较

    本文将介绍DDD分层架构中广泛使用的数据传输对象Dto,并且与领域实体Entity,查询实体QueryObject,视图实体ViewModel等几种实体进行比较. 领域实体为何不能一统江湖? 当你阅读 ...

  9. 应用程序框架实战三十三:表现层及ASP.NET MVC介绍(二)

    最近的更新速度越来越慢,主要是项目上比较忙,封装EasyUi也要花很多时间.不过大家请放心,本系列不会半途夭折,并且代码干货也会持续更新.本文继续介绍表现层和Asp.net Mvc,我将在本篇讨论一些 ...

随机推荐

  1. QTP自动化测试培训:描述编程之WebElement

    QTP自动化测试培训:描述编程之WebElement   通过描述性编程技术,来描述出来输入框: set po=browser("creationtime:=0").page(&q ...

  2. CF #405 (Div. 2) B. Bear ad Friendship Condition (dfs+完全图)

    题意:如果1认识2,2认识3,必须要求有:1认识3.如果满足上述条件,输出YES,否则输出NO. 思路:显然如果是一个完全图就输出YES,否则就输出NO,如果是无向完全图则一定有我们可以用dfs来书边 ...

  3. Python爬虫 URLError异常处理

    1.URLError 首先解释下URLError可能产生的原因: 网络无连接,即本机无法上网 连接不到特定的服务器 服务器不存在 在代码中,我们需要用try-except语句来包围并捕获相应的异常.下 ...

  4. Activity栈与任务管理探究1——栈与任务的概述

    Activity栈与任务管理探究1--栈与任务的概述 内容概览 1. 前言 2. Activity中的Stack 3. Activity中的Task 4. Activity栈与任务管理基本原则 1. ...

  5. 读书笔记 effective c++ Item 47 使用traits class表示类型信息

    STL主要由为容器,迭代器和算法创建的模板组成,但是也有一些功能模板.其中之一叫做advance.Advance将一个指定的迭代器移动指定的距离: template<typename IterT ...

  6. WebGIS中使用ZRender实现前端动态播放轨迹特效的方案

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 项目中需要在地图上以时间轴方式播放人员.车辆在地图上的历史行进 ...

  7. 【zzulioj 2127】 tmk射气球

    比较简单的题,直接求空间中一个点到直线的距离而已,这道题说了直线和水平的平面 平行,我们可以先求投影到直线的距离,然后再算当前点到直线的距离. Description 有一天TMK在做一个飞艇环游世界 ...

  8. MySQL最常用字符串函数

    字符串函数 是最常用的的一种函数,在一个具体应用中通常会综合几个甚至几类函数来实现相应的应用: 1.LOWER(column|str):将字符串参数值转换为全小写字母后返回 mysql> sel ...

  9. app测试特点

    一.安装与卸载1.软件安装后是否可以正常运行:2.安装过程中是否可以中断3.安装空间不足时是否有相应的提示4.是否可以卸载应用(桌面卸载和应用卸载)二.权限测试1.扣费风险:包括发送短信.拨打电话.连 ...

  10. NGINX中的proxy_pass和rewrite

    文章作者:luxianghao 文章来源:http://www.cnblogs.com/luxianghao/p/6807081.html 转载请注明,谢谢合作. 免责声明:文章内容仅代表个人观点,如 ...