4.1:
环境配置时注意平台,不能像vulkan tutorial中那样直接选择所有平台,x86平台link vulkan sdk的lib32,x64平台link lib,否则可能会出现链接错误
6.2:
书上并没有给出检测请求的拓展是否支持的代码,在7.2节才发现给出了类似的,于是当时自己写了一段,其实可以直接copy7.2节(这里有个小坑就是VkExtensionProperties::extensionName是一个char指针而不是string,所以比较得使用strcmp而不是==)
mycode:(感觉比书上的太c化了,这么点查找量没必要用c)
unsigned int glfwExtensionCount = 0, allExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &allExtensionCount, nullptr);
std::vector<VkExtensionProperties> extensionsTable(allExtensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &allExtensionCount, extensionsTable.data());
std::cout << "available extensions:" << std::endl;
for (const VkExtensionProperties& extension : extensionsTable)
{
std::cout << "\t" << extension.extensionName << std::endl;
}
for (int i = 0; i < glfwExtensionCount; ++i)
{
std::cout << glfwExtensions[i] << std::endl;
if (std::find_if(extensionsTable.begin(), extensionsTable.end(),
[&glfwExtensions, &i](const VkExtensionProperties& t) {return (strcmp(t.extensionName, glfwExtensions[i]) == 0) ? 1 : 0; })
== extensionsTable.end())
{
throw std::runtime_error("Extension was not supported!");
}
}
7.2:
这里我使用的vulkan sdk版本是1.3.204.1,新版sdk中标准校验层VK_LAYER_LUNARG_standard_validation将被VK_LAYER_KHRONOS_validation取代。(据说是重构了,具有更小的开销)所以如果出现异常,把标准校验层名改为后者
7.3:
我的选择是继续用char**,只需要加上一句:
if (enableValidationLayers)
{
glfwExtensions[glfwExtensionCount] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
++glfwExtensionCount;
}
ps:
std : : vector<const char*> extensions ( glfwExtensions ,glfwExtensions + glfwExtensionCount ) ;
// 原来指针也能初始化vector
以下是汇编相关:
VKAPI_ATTR和VKAPI_CALL这两个宏是用来跨平台的,VKAPI_ATTR用来兼容arm架构的要求(由于本人对移动端不感兴趣所以不想深入),VKAPI_CALL是函数调用方式,windows下是_stdcall,即被调函数自己负责栈平衡,即被调函数使用带整数版本的ret指令(把栈顶储存的地址给ip后,再将栈顶向栈底移动该整数个字节),详细解释看link,进一步理解call就是把当前函数的下一条指令地址压栈,然后查函数-地址表,将函数地址赋给ip。
关于回调函数的参数可以查看定义,如第一个参数消息等级,该类型为:
typedef enum VkDebugUtilsMessageSeverityFlagBitsEXT {
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT = 0x00000001,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT = 0x00000010,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT = 0x00000100,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT = 0x00001000,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT = 0x7FFFFFFF
} VkDebugUtilsMessageSeverityFlagBitsEXT;
由此可以知道等级高低,以及他们的工作方式,即位运算,每个十六进制位代表一个等级(因为等级不多,所以3个二进制位其实都没用。。)比书中多出来的一个枚举值是01…1,即最大正数
//我们设置回调函数处理除了 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT
//外的所有级别的消息:
createInfo.messageSeverity =
VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
这印证了我们的猜想,即每个十六进制位代表一个等级,为1时表示该等级受理,所以,想开启某个类型的消息受理,就或上该类型的枚举值,禁用就是& ~该类型枚举值
//动态加载返回后所转类型PFN_vkCreateDebugUtilsMessengerEXT的定义:
typedef VkResult (VKAPI_PTR *PFN_vkCreateDebugUtilsMessengerEXT)(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pMessenger);
这是一个函数指针。所以在vk中加载扩展函数就是用vkGetInstanceProcAddr(vk实例,待加载函数名),然后将返回值转为对应函数的指针,对应类型名就是PFN_待加载函数名。(pfn意思就是pointer function)
没加载清理vkDebugUtilsMessengerEXT的函数会报错,这里的报错信息可能会和书上展示的不一样,没有关系,接着往下做就行了,加载了就不报错了
8.2:
打分策略:是独显,+1000分,再加上VkPhysicalDeviceProperties.VkPhysicalDeviceLimits.maxImageDimension2D
这是设备允许创建的2d纹理的最大size(长*宽),会影响到图像质量,越大越好
不支持几何渲染器,直接0分
8.3:
队列族属性中的queueFlags描述了该队列族拥有的功能,同样也是位运算管理。将其与上VK_QUEUE_功能(图形,计算等等)_BIT即可检测该队列族是否拥有该属性的队列
10.1:
glfw封装了窗口表面的创建,前面一段即是glfw在windows系统中封装的代码,不用搬。
销毁仅一个函数即可,glfw没封装。
part1小结:
持续更新ing