SwallowJoe的博客

Be a real go-getter,
NEVER SETTLE!

0%

Vulkan入门(3)-设置物理设备和逻辑设备

简述

本文主要是学习Vulkan Tutorial.pdf文档中的Physical devices and queue families(物理设备和队列系列)部分以及Logical device and queues(逻辑设备与队列)部分。

参考资料

  1. [Vulkan-文档]https://github.com/KhronosGroup/Vulkan-Docs
  2. [Vulkan-feature查询]https://vulkan.lunarg.com/doc/view/1.0.26.0/linux/vkspec.chunked/ch31s01.html

一. Physical devices and queue families(物理设备和队列系列)

1.1 选择物理显卡GPU

在通过VkInstance初始化Vulkan库之后,需要在系统中查找并选择支持我们所需功能的图形显卡。
事实上,我们可以选择任意数量的显卡并同时使用。但在这里,只使用第一个适合我们需求的显卡。
我们将添加一个函数pickPhysicalDevice并在initVulkan函数中添加对它的调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
void initVulkan() {
checkAvailableExtensions();
createInstance();
// 创建DEBUG消息回调
setupDebugMessenger();

// 选择物理设备
pickPhysicalDevice();
}

void pickPhysicalDevice() {

}

最终选择的图形卡将存储在VkPhysicalDevice句柄中,该句柄作为新的类成员添加。当VkInstance被销毁时,该对象将被隐式销毁,因此我们不需要在清理函数中做任何新的操作。

  1. VkPhysicalDevice对象不能被显式销毁。相反,当检索到它们的VkInstance对象被撤销时,它们将隐式撤销。
  2. 一旦所有由VkPhysicalDevice对象创建的VkDevice对象都被销毁,VkInstance对象就可以被销毁。
1
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;

列出物理显卡的过程和列出vulkan扩展的过程类似,首先是获取本机物理显卡的数量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void pickPhysicalDevice() {
uint32_t deviceCount = 0;
// 首先获取本机物理显卡数量
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);

// 当然没有GPU时,抛出异常
if (deviceCount == 0) {
throw std::runtime_error("failed to find GPUs with Vulkan support!");
}

std::vector<VkPhysicalDevice> devices(deviceCount);
vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());

// 遍历所有GPU, 选择合适的使用
for (const auto& device : devices) {
if (isDeviceSuitable(device)) {
physicalDevice = device;
break;
}
}
}

bool isDeviceSuitable(VkPhysicalDevice device) {
// 暂时没什么可以挑剔的,都可以吧
// 其实大部分的机器只会有一个显卡
return true;
}

1.2 基础设备适配性检查

通过查询细节来评估设备的适用性。
可以使用vkGetPhysicalDeviceProperties查询基本设备属性,如名称,类型和支持的Vulkan版本。

1
2
VkPhysicalDeviceProperties deviceProperties;
vkGetPhysicalDeviceProperties(device, &deviceProperties);

使用vkGetPhysicalDeviceFeatures查询对纹理压缩,64位浮点和多视口渲染(对VR有用)等可选功能的支持:

1
2
VkPhysicalDeviceFeatures deviceFeatures;
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);

基本操作就是:

  1. 通过vkGetPhysicalDeviceProperties获取本机设备的属性
  2. 查询vkGetPhysicalDeviceFeatures中可以被支持的feature

举个例子,假设我们的应用程序仅适用于支持几何着色器的专用显卡。 那么isDeviceSuitable函数将如下所示:

1
2
3
4
5
6
7
8
9
10
bool isDeviceSuitable(VkPhysicalDevice device) {
VkPhysicalDeviceProperties deviceProperties;
VkPhysicalDeviceFeatures deviceFeatures;

vkGetPhysicalDeviceProperties(device, &deviceProperties);
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);

return ((deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
&& deviceFeatures.geometryShader);
}

所有可支持的feature见附录。
根据Vulkan Tutorial文档,有推荐使用评分机制来选择最合适的GPU,这个就见仁见智,看个人喜好,这里就不赘述了。

1.3 Queue families

几乎所有Vulkan中的操作,从绘图到上传纹理,都需要将命令提交到队列中(这一点研究过hwui的童鞋肯定深有体会)。
存在来自不同队列系列的不同类型的队列,并且每个队列族仅允许命令的子集。
例如,可能存在仅允许处理计算命令的队列系列或仅允许与存储器传输相关的命令的队列系列。

所有我们需要检查本机设备支持哪些队列系列,以及哪一个支持我们要使用的命令。
添加一个新函数findQueueFamilies,用于查找我们需要的所有队列系列。
比如查找支持图形命令的队列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
struct QueueFamilyIndices {
// 别忘了添加头文件:including <optional>
// optional用途如其名,它可以容纳一个对象值或是为空。
// 典型的应用情景是函数调用时,如需根据条件返回一个对象(有效)或默认对象(无效)
// 若该对象构造成本很高(资源分配等),可用optional返回一个空对象,提高效率。
std::optional<uint32_t> graphicsFamily;

bool isComplete() {
return graphicsFamily.has_value();
}
};

QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) {
QueueFamilyIndices indices;

// 先检查数量
uint32_t queueFamilyCount = 0;
// 使用 vkGetPhysicalDeviceQueueFamilyProperties 检索队列系列是否正是我们需要的:
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);

// VkQueueFamilyProperties结构包含有关队列系列的一些详细信息
// 包括支持的操作类型以及可基于该系列创建的队列数
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());

// 比如我们找到一个支持VK_QUEUE_GRAPHICS_BIT的队列系列
int i = 0;
for (const auto& queueFamily : queueFamilies) {
if (queueFamily.queueCount > 0 &&
queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) {

indices.graphicsFamily = i;
}

if (indices.isComplete()) {
break;
}

i++;
}
return indices;
}

把这个检查加入isDeviceSuitable函数。
现在已经找到合适的物理设备了, 下一步是创建一个与之适配的逻辑设备。

二. Logical device and queues

选择要使用的物理设备后,就可以创建一个与之适配的逻辑设备。
逻辑设备创建过程类似于实例创建过程,还需要指定现在要创建的队列(已经查询了哪些队列系列可用)。
并且从同一物理设备可以创建多个逻辑设备。

存储逻辑设备类似物理设备,也是使用句柄:

1
VkDevice device;

2.1 指定要创建的队列

创建逻辑设备也是在结构体中指定一堆细节,其中第一个是VkDeviceQueueCreateInfo。
此结构描述了我们为单个队列系列所需的队列数。
比如创建具有图形功能的队列:

1
2
3
4
5
6
7
QueueFamilyIndices indices = findQueueFamilies(physicalDevice);

VkDeviceQueueCreateInfo queueCreateInfo = {};

queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = indices.graphicsFamily.value();
queueCreateInfo.queueCount = 1;

当前可用的驱动程序只允许为每个队列系列创建少量队列,实际上也不需要多个队列。
因为可以在多个线程上创建所有命令缓冲区,然后使用一个低开销调用在主线程上一次性提交。

Vulkan允许为队列分配优先级,以使用介于0.0和1.0之间的浮点数来影响命令缓冲区执行的调度。
即使只有一个队列,也是必需的

1
2
float queuePriority = 1.0f;
queueCreateInfo.pQueuePriorities = &queuePriority;

2.2 指定使用的设备功能(feature)

要指定的下一个信息是我们将要使用的一组设备feature。
这些是在[1.2]中使用vkGetPhysicalDeviceFeatures查询支持的功能,例如几何着色器。
如果不需要任何特殊的东西,可以简单地定义它并默认为VK_FALSE。
但一旦即将开始用Vulkan做更多有趣的事情,就需要设定这个结构了。

1
VkPhysicalDeviceFeatures deviceFeatures = {};

2.3 创建逻辑设备

在VkDeviceQueueCreateInfo和VkPhysicalDeviceFeatures创建完毕后,就可以根据这个创建逻辑设备实例了。

1
2
3
4
5
6
7
8
VkDeviceCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

// 首先指定VkDeviceQueueCreateInfo
createInfo.pQueueCreateInfos = &queueCreateInfo;
createInfo.queueCreateInfoCount = 1;
// 指定VkPhysicalDeviceFeatures
createInfo.pEnabledFeatures = &deviceFeatures;

其余信息与VkInstanceCreateInfo结构相似,并要求指定扩展(Extensions)和验证层(Validation Layers)。不同之处在于这次是逻辑设备的。
设备特定扩展的其中之一是VK_KHR_swapchain,它允许您将该设备的渲染图像呈现给窗口。
系统中可能存在缺乏此功能的Vulkan设备,比如因为它们仅支持计算操作。

Vulkan的先前实现区分了实例和设备特定的验证层,但现在不做区分了。
也就是说VkDeviceCreateInfo的enabledLayerCount和ppEnabledLayerNames字段在最新实现中可以忽略。

1
2
3
4
5
6
7
8
createInfo.enabledExtensionCount = 0;

if (enableValidationLayers) {
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
} else {
createInfo.enabledLayerCount = 0;
}

类似创建vulkan实例,这里使用 vkCreateDevice 函数创建逻辑设备:

1
2
3
4
// 调用 vkCreateDevice 创建逻辑设备,别忘了在cleanup函数中销毁
if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) {
throw std::runtime_error("failed to create logical device!");
}

2.4 检索队列句柄

队列是与逻辑设备一起自动创建的,现在创建与它们接口的句柄。
使用 VkQueue 来存储队列的句柄,如存储图形队列的句柄:

1
VkQueue graphicsQueue;

当设备被销毁时,会隐式清除设备队列,因此我们不需要在清理中执行任何操作(vkCreateXXX才需要主动释放哦)。

我们可以使用vkGetDeviceQueue函数来检索每个队列系列的队列句柄。
参数是逻辑设备,队列系列,队列索引和指向存储队列句柄的变量的指针。
因为我们只是从这个系列创建一个队列,所以我们只使用索引0。

1
vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue);

有了逻辑设备和队列句柄,我们现在可以开始使用显卡来做事了!
准备工作基本完成,后续我们可以设置资源并用窗口显示结果!
这次就不贴代码了。

附录

vulkan feature

vulkan feature

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// 定义在 vulkan_core.h 文件中
typedef struct VkPhysicalDeviceFeatures {
VkBool32 robustBufferAccess;
VkBool32 fullDrawIndexUint32;
VkBool32 imageCubeArray;
VkBool32 independentBlend;
VkBool32 geometryShader;
VkBool32 tessellationShader;
VkBool32 sampleRateShading;
VkBool32 dualSrcBlend;
VkBool32 logicOp;
VkBool32 multiDrawIndirect;
VkBool32 drawIndirectFirstInstance;
VkBool32 depthClamp;
VkBool32 depthBiasClamp;
VkBool32 fillModeNonSolid;
VkBool32 depthBounds;
VkBool32 wideLines;
VkBool32 largePoints;
VkBool32 alphaToOne;
VkBool32 multiViewport;
VkBool32 samplerAnisotropy;
VkBool32 textureCompressionETC2;
VkBool32 textureCompressionASTC_LDR;
VkBool32 textureCompressionBC;
VkBool32 occlusionQueryPrecise;
VkBool32 pipelineStatisticsQuery;
VkBool32 vertexPipelineStoresAndAtomics;
VkBool32 fragmentStoresAndAtomics;
VkBool32 shaderTessellationAndGeometryPointSize;
VkBool32 shaderImageGatherExtended;
VkBool32 shaderStorageImageExtendedFormats;
VkBool32 shaderStorageImageMultisample;
VkBool32 shaderStorageImageReadWithoutFormat;
VkBool32 shaderStorageImageWriteWithoutFormat;
VkBool32 shaderUniformBufferArrayDynamicIndexing;
VkBool32 shaderSampledImageArrayDynamicIndexing;
VkBool32 shaderStorageBufferArrayDynamicIndexing;
VkBool32 shaderStorageImageArrayDynamicIndexing;
VkBool32 shaderClipDistance;
VkBool32 shaderCullDistance;
VkBool32 shaderFloat64;
VkBool32 shaderInt64;
VkBool32 shaderInt16;
VkBool32 shaderResourceResidency;
VkBool32 shaderResourceMinLod;
VkBool32 sparseBinding;
VkBool32 sparseResidencyBuffer;
VkBool32 sparseResidencyImage2D;
VkBool32 sparseResidencyImage3D;
VkBool32 sparseResidency2Samples;
VkBool32 sparseResidency4Samples;
VkBool32 sparseResidency8Samples;
VkBool32 sparseResidency16Samples;
VkBool32 sparseResidencyAliased;
VkBool32 variableMultisampleRate;
VkBool32 inheritedQueries;
} VkPhysicalDeviceFeatures;

1. robustBufferAccess

指定对缓冲区的访问是根据缓冲区描述符的范围进行边界检查的(由VkDescriptorBufferInfo::range,VkBufferViewCreateInfo::range或缓冲区的大小确定)。
超出范围访问不得导致应用程序终止,并且着色器加载,存储和原子的效果必须符合与如下相关的行为:

  • 如果满足以下任何条件,则认为缓冲区访问超出范围:
    • 指针由OpImageTexelPointer形成,坐标小于零或大于或等于绑定范围内的整个元素的数量。
    • 指针不是由OpImageTexelPointer形成的,并且指向的对象并不完全包含在绑定范围内。这包括通过变量指针执行的访问,其中不能静态地确定被访问的缓冲区描述符。未初始化的指针和指向OpConstantNull的指针被视为指向零大小的对象,因此通过这些指针的所有访问都被视为超出范围。
      • 注意:如果SPIR-V OpLoad指令加载结构并且结构的尾端超出边界,则结构的所有成员都被视为超出边界,即使最终的成员未被静态使用。
    • 如果确定给定SPIR-V块中的任何缓冲区访问超出范围,则在同一SPIR-V块中访问小于16字节的地址的任何其他相同类型(加载,存储或原子)访问 远离界外地址也可能被认为是超出界限。
  • 超出范围的缓冲区加载将返回以下任何值:
    • 从绑定到缓冲区的内存范围内的任何位置开始的值(可能包括超出缓冲区末尾的内存字节,直到绑定范围的末尾)。
    • 向量读取的零值或(0,0,0,x)向量,其中x是向量组件类型中表示的有效值,可以是以下任意一种:
      • 有符号或无符号整数分量的0,1或最大可表示正整数值
      • 0.0或1.0,用于浮点组件
  • 越界写入可以修改绑定到缓冲区的内存范围内的值,但不能修改任何其他内存。
  • 越界原子可以修改绑定到缓冲区的内存范围内的值,但不能修改任何其他内存,并返回未定义的值。
  • 如果绑定顶点缓冲区范围中属性的偏移量加上属性的大小大于以下值,则顶点输入属性被视为超出边界。
      1. vertexBufferRangeSize, if bindingStride == 0; 或者
      1. (vertexBufferRangeSize - (vertexBufferRangeSize % bindingStride))
    • 其中vertexBufferRangeSize是绑定到顶点缓冲区绑定的内存范围的字节大小,bindingStride是相应顶点输入绑定的字节跨度。此外,如果使用特定顶点输入绑定的任何顶点输入属性超出边界,则使用该顶点着色器调用的顶点输入绑定的所有顶点输入属性被视为超出边界。
    • 一旦顶点输入属性超出范围,将为其分配以下值之一:
      • 来自绑定到缓冲区的内存范围内任何位置的值,根据属性的格式进行转换。
      • 零值,或(0,0,0,x)向量,格式根据属性的格式转换。
  • 如果未启用robustBufferAccess,则应用程序不得执行越界访问。而一般来讲,robustBufferAccess都是需要开启的。

2. fullDrawIndexUint32

指定当使用VKIndexType为VK_INDEX_TYPE_UINT32时,索引绘制调用支持完整的32位索引范围。
maxDrawIndexedIndexValue是可以使用的最大索引值(除了原始重启索引,当VkIndexType是VK_INDEX_TYPE_UINT32时,它总是2^32-1)。
如果支持此功能,则maxDrawIndexedIndexValue必须为2^32-1; 否则它必须不小于2^24-1。

3. imageCubeArray

指定是否可以创建VkImageViewType为VK_IMAGE_VIEW_TYPE_CUBE_ARRAY的图像视图,以及是否可以在着色器代码中使用相应的SampledCubeArray和ImageCubeArray SPIR-V功能。

4. independentBlend

指定是否每个附件独立控制VkPipelineColorBlendAttachmentState设置。
如果未启用此功能,则所有颜色附件的VkPipelineColorBlendAttachmentState设置必须相同。
如果启用,可以为每个绑定的颜色附件提供不同的VkPipelineColorBlendAttachmentState。

5. geometryShader

指定是否支持几何着色器。
如果未启用此功能,则不得使用VK_SHADER_STAGE_GEOMETRY_BIT和VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT枚举值。
这还指定着色器模块是否可以声明几何功能。

6. tessellationShader

指定是否支持曲面细分控制和评估着色器。
如果未启用此功能,则不得使用:

  • VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:指定曲面细分控制阶段
  • VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:指定曲面细分评估阶段
  • VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT:指定曲面细分控制着色器阶段
  • VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT:指定曲面细分评估着色器阶段
  • VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO

这还指定着色器模块是否可以声明Tessellation功能。

7. sampleRateShading

指定是否支持样本着色和多重采样插值。
如果未启用此功能,则必须将VkPipelineMultisampleStateCreateInfo结构的sampleShadingEnable成员设置为VK_FALSE,并忽略minSampleShading成员。
这还指定着色器模块是否可以声明SampleRateShading功能。

8. dualSrcBlend

指定是否支持采用两个源的混合操作。
如果未启用此功能,则不得将:

  • VK_BLEND_FACTOR_SRC1_COLOR:
  • VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR
  • VK_BLEND_FACTOR_SRC1_ALPHA
  • VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA

以上枚举值用作源或目标混合因子。详细信息参阅 vkspec.html: 26.1.2. Dual-Source Blending

9. logicOp

指定是否支持逻辑运算。 如果未启用此功能,则必须将VkPipelineColorBlendStateCreateInfo结构的logicOpEnable成员设置为VK_FALSE,并忽略logicOp成员。

10. multiDrawIndirect

指定是否支持多个draw间接。
如果未启用此功能,则vkCmdDrawIndirect和vkCmdDrawIndexedIndirect命令的drawCount参数必须为0或1.
如果不支持此功能,则VkPhysicalDeviceLimits结构的maxDrawIndirectCount(间接绘制调用支持的最大绘制计数)成员也必须为1。

11. drawIndirectFirstInstance

指定间接绘制调用是否支持firstInstance参数。
如果未启用此功能,则提供给vkCmdDrawIndirect和vkCmdDrawIndexedIndirect命令的所有VkDrawIndirectCommand和VkDrawIndexedIndirectCommand结构的firstInstance成员必须为0。

12. depthClamp

指定是否支持深度Clamp。
如果未启用此功能,则必须将VkPipelineRasterizationStateCreateInfo结构的depthClampEnable成员设置为VK_FALSE。
如果启用,将depthClampEnable设置为VK_TRUE将启用深度Clamp。

13. depthBiasClamp

指定是否支持深度偏置Clamp。
如果未启用此功能,则必须将VkPipelineRasterizationStateCreateInfo结构的depthBiasClamp成员设置为0.0,除非启用VK_DYNAMIC_STATE_DEPTH_BIAS动态状态,并且必须将vkCmdSetDepthBias的depthBiasClamp参数设置为0.0。

14. fillModeNonSolid

指定是否支持点和线框填充模式。
如果未启用此功能,则VkPipelineRasterizationStateCreateInfo::polygonMode不得使用:

  • VK_POLYGON_MODE_POINT:指定将多边形顶点绘制为点
  • VK_POLYGON_MODE_LINE:指定将多边形的边绘制为点

15. depthBounds

指定是否支持深度边界测试。
如果未启用此功能,则必须将VkPipelineDepthStencilStateCreateInfo结构的depthBoundsTestEnable成员设置为VK_FALSE。 当depthBoundsTestEnable设置为VK_FALSE时,将忽略VkPipelineDepthStencilStateCreateInfo结构的minDepthBounds和maxDepthBounds成员。

16. wideLines

指定是否支持宽度不是1.0的行。
如果未启用此功能,则必须将VkPipelineRasterizationStateCreateInfo结构的lineWidth成员设置为1.0,除非启用VK_DYNAMIC_STATE_LINE_WIDTH动态状态,并且必须将vWCmdSetLineWidth的lineWidth参数设置为1.0。
支持此功能时,支持的线宽的范围和粒度分别由VkPhysicalDeviceLimits结构的lineWidthRange和lineWidthGranularity成员指示。

17. largePoints

指定是否支持大小大于1.0的点。
如果未启用此功能,则仅支持着色器写入的点大小1.0。 支持的点大小的范围和粒度分别由VkPhysicalDeviceLimits结构的pointSizeRange和pointSizeGranularity成员指示。

18. alphaToOne

指定实现是否能够使用定点颜色的最大可表示alpha值或浮点颜色的1.0替换片段着色器中输出的颜色片段的alpha值。
如果未启用此功能,则必须将VkPipelineMultisampleStateCreateInfo结构的alphaToOneEnable成员设置为VK_FALSE。
否则,将alphaToOneEnable设置为VK_TRUE将启用alpha-to-one行为。

19. multiViewport

指定是否支持多个Viewport。 如果未启用此功能:

  • 必须将VkPipelineViewportStateCreateInfo结构的viewportCount和scissorCount成员设置为1。
  • vkCmdSetViewport命令的firstViewport和viewportCount参数必须分别设置为0和1。
  • vkCmdSetScissor命令的firstScissor和scissorCount参数必须分别设置为0和1。

20. samplerAnisotropy

指定是否支持各向异性过滤。
如果未启用此功能,则VkSamplerCreateInfo结构的anisotropyEnable成员必须为VK_FALSE。

21. textureCompressionETC2

指定是否支持所有ETC2和EAC压缩纹理格式。
如果启用此功能,则OptimalTilingFeatures中必须支持:

  • VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT:指定可以从中采样图像视图

  • VK_FORMAT_FEATURE_BLIT_SRC_BIT:指定图像可用作vkCmdBlitImage命令的srcImage

  • VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT:图像视图可以与采样器一起使用(详细信息 vkspec.html:VkFormatFeatureFlagBits)

    以上格式的功能:

    • VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK
    • VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK
    • VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK
    • VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK
    • VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK
    • VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK
    • VK_FORMAT_EAC_R11_UNORM_BLOCK
    • VK_FORMAT_EAC_R11_SNORM_BLOCK
    • VK_FORMAT_EAC_R11G11_UNORM_BLOCK
    • VK_FORMAT_EAC_R11G11_SNORM_BLOCK

要查询其他属性,或者未启用该功能,可以使用vkGetPhysicalDeviceFormatProperties和vkGetPhysicalDeviceImageFormatProperties来检查各个格式的支持属性。

22. textureCompressionASTC_LDR

指定是否支持所有ASTC LDR压缩纹理格式。
如果启用此功能,则OptimalTilingFeatures中必须支持:

  • VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT

  • VK_FORMAT_FEATURE_BLIT_SRC_BIT和VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT

    以上格式的功能:

    • VK_FORMAT_ASTC_4x4_UNORM_BLOCK
    • VK_FORMAT_ASTC_4x4_SRGB_BLOCK
    • VK_FORMAT_ASTC_5x4_UNORM_BLOCK
    • VK_FORMAT_ASTC_5x4_SRGB_BLOCK
    • VK_FORMAT_ASTC_5x5_UNORM_BLOCK
    • VK_FORMAT_ASTC_5x5_SRGB_BLOCK
    • VK_FORMAT_ASTC_6x5_UNORM_BLOCK
    • VK_FORMAT_ASTC_6x5_SRGB_BLOCK
    • VK_FORMAT_ASTC_6x6_UNORM_BLOCK
    • VK_FORMAT_ASTC_6x6_SRGB_BLOCK
    • VK_FORMAT_ASTC_8x5_UNORM_BLOCK
    • VK_FORMAT_ASTC_8x5_SRGB_BLOCK
    • VK_FORMAT_ASTC_8x6_UNORM_BLOCK
    • VK_FORMAT_ASTC_8x6_SRGB_BLOCK
    • VK_FORMAT_ASTC_8x8_UNORM_BLOCK
    • VK_FORMAT_ASTC_8x8_SRGB_BLOCK
    • VK_FORMAT_ASTC_10x5_UNORM_BLOCK
    • VK_FORMAT_ASTC_10x5_SRGB_BLOCK
    • VK_FORMAT_ASTC_10x6_UNORM_BLOCK
    • VK_FORMAT_ASTC_10x6_SRGB_BLOCK
    • VK_FORMAT_ASTC_10x8_UNORM_BLOCK
    • VK_FORMAT_ASTC_10x8_SRGB_BLOCK
    • VK_FORMAT_ASTC_10x10_UNORM_BLOCK
    • VK_FORMAT_ASTC_10x10_SRGB_BLOCK
    • VK_FORMAT_ASTC_12x10_UNORM_BLOCK
    • VK_FORMAT_ASTC_12x10_SRGB_BLOCK
    • VK_FORMAT_ASTC_12x12_UNORM_BLOCK
    • VK_FORMAT_ASTC_12x12_SRGB_BLOCK

要查询其他属性,或者未启用该功能,可以使用vkGetPhysicalDeviceFormatProperties和vkGetPhysicalDeviceImageFormatProperties来检查各个格式的支持属性。

23. textureCompressionBC

指定是否支持所有BC压缩纹理格式。
如果启用此功能,则OptimalTilingFeatures中必须支持:

  • VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT

  • VK_FORMAT_FEATURE_BLIT_SRC_BIT

  • VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT

    以上格式的功能:

    • VK_FORMAT_BC1_RGB_UNORM_BLOCK
    • VK_FORMAT_BC1_RGB_SRGB_BLOCK
    • VK_FORMAT_BC1_RGBA_UNORM_BLOCK
    • VK_FORMAT_BC1_RGBA_SRGB_BLOCK
    • VK_FORMAT_BC2_UNORM_BLOCK
    • VK_FORMAT_BC2_SRGB_BLOCK
    • VK_FORMAT_BC3_UNORM_BLOCK
    • VK_FORMAT_BC3_SRGB_BLOCK
    • VK_FORMAT_BC4_UNORM_BLOCK
    • VK_FORMAT_BC4_SNORM_BLOCK
    • VK_FORMAT_BC5_UNORM_BLOCK
    • VK_FORMAT_BC5_SNORM_BLOCK
    • VK_FORMAT_BC6H_UFLOAT_BLOCK
    • VK_FORMAT_BC6H_SFLOAT_BLOCK
    • VK_FORMAT_BC7_UNORM_BLOCK
    • VK_FORMAT_BC7_SRGB_BLOCK

要查询其他属性,或者未启用该功能,可以使用vkGetPhysicalDeviceFormatProperties和vkGetPhysicalDeviceImageFormatProperties来检查各个格式的支持属性。

24. occlusionQueryPrecise

指定是否支持返回实际样本计数的遮挡查询。
通过在VkQueryPoolCreateInfo结构中指定VK_QUERY_TYPE_OCCLUSION的queryType并将其传递给vkCreateQueryPool,可以在VkQueryPool中创建遮挡查询。
如果启用此功能,则此类查询可以将flags参数中的VK_QUERY_CONTROL_PRECISE_BIT启用为vkCmdBeginQuery。
如果不支持此功能,则实现仅支持布尔遮挡查询。传递任何样本时,布尔查询将返回非零结果值,否则返回结果值为零。
启用此功能并设置VK_QUERY_CONTROL_PRECISE_BIT后,遮挡查询将报告传递的实际样本数。

25. pipelineStatisticsQuery

指定是否支持管道统计信息查询。
如果未启用此功能,则无法创建类型为VK_QUERY_TYPE_PIPELINE_STATISTICS的查询,并且无法在VkQueryPoolCreateInfo结构的pipelineStatistics成员中设置任何VkQueryPipelineStatisticFlagBits位。

26. vertexPipelineStoresAndAtomics

指定存储缓冲区和图像是否支持顶点,曲面细分和几何着色器阶段中的存储和原子操作。
如果未启用此功能,则着色器模块中这些阶段使用的所有存储器映像,存储纹理缓冲区缓冲区和存储缓冲区变量必须使用NonWritable修饰(或GLSL中的只读内存限定符)进行修饰。

27. fragmentStoresAndAtomics

指定存储缓冲区和图像是否支持片段着色器阶段中的存储和原子操作。
如果未启用此功能,则着色器模块中片段阶段使用的所有存储器映像,存储纹理缓冲区缓冲区和存储缓冲区变量必须使用NonWritable修饰(或GLSL中的只读内存限定符)进行修饰。

28. shaderTessellationAndGeometryPointSize

指定曲面细分控件,曲面细分评估和几何着色器阶段中是否提供PointSize内置修饰。
如果未启用此功能,则不得读取或写入使用PointSize内置修饰的成员,并且从曲面细分或几何着色器写入的所有点的大小均为1.0。
这还指定着色器模块是否可以为曲面细分控制和评估着色器声明TessellationPointSize功能,或者着色器模块是否可以为几何着色器声明GeometryPointSize功能。
支持此功能的实现还必须支持tessellationShader或geometryShader功能中的一个或两个

29. shaderImageGatherExtended

指定着色器代码中是否可以使用扩展的图像收集指令集。
如果未启用此功能,则OpImage * Gather指令不支持Offset和ConstOffsets操作数。 这还指定着色器模块是否可以声明ImageGatherExtended功能。

30. shaderStorageImageExtendedFormats

指定着色器代码中是否所有扩展存储器图像格式都可用。
如果启用此功能,则必须在所有扩展格式的optimalTilingFeatures中支持VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT功能。
要查询其他属性,或者未启用该功能,可以使用vkGetPhysicalDeviceFormatProperties和vkGetPhysicalDeviceImageFormatProperties来检查各个格式的支持属性。

31. shaderStorageImageMultisample

指定是否支持多重采样存储映像。
如果未启用此功能,则必须使用等于VK_SAMPLE_COUNT_1_BIT的样本创建使用包含VK_IMAGE_USAGE_STORAGE_BIT的用法创建的图像。
这还指定着色器模块是否可以声明StorageImageMultisample功能。

32. shaderStorageImageReadWithoutFormat

指定存储图像是否需要在从存储器映像读取时指定格式限定符。
如果未启用此功能,则OpImageRead指令的OpTypeImage不得为Unknown。
这还指定着色器模块是否可以声明StorageImageReadWithoutFormat功能。

33. shaderStorageImageWriteWithoutFormat

指定存储图像是否需要在写入存储图像时指定格式限定符。
如果未启用此功能,则OpImageWrite指令的OpTypeImage不得为Unknown。
这还指定着色器模块是否可以声明StorageImageWriteWithoutFormat功能。

34. shaderUniformBufferArrayDynamicIndexing

指定是否可以通过着色器代码中的动态统一整数表达式对统一缓冲区的数组建立索引。
如果未启用此功能,则在着色器代码中聚合到数组中时,描述符类型为VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER或VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC的资源必须仅由常量整数表达式编制索引。
这还指定着色器模块是否可以声明UniformBufferArrayDynamicIndexing功能。

35. shaderSampledImageArrayDynamicIndexing

指定采样器阵列或采样图像是否可以通过着色器代码中的动态统一整数表达式进行索引。
如果未启用此功能,则在着色器代码中聚合到数组中时,描述符类型为VK_DESCRIPTOR_TYPE_SAMPLER,VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER或VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE的资源必须仅由常量整数表达式编制索引。
这还指定着色器模块是否可以声明SampledImageArrayDynamicIndexing功能。

36. shaderStorageBufferArrayDynamicIndexing

指定是否可以通过着色器代码中的动态统一整数表达式索引存储缓冲区的数组。
如果未启用此功能,则在着色器代码中聚合到数组中时,描述符类型为VK_DESCRIPTOR_TYPE_STORAGE_BUFFER或VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC的资源必须仅由常量整数表达式编制索引。
这还指定着色器模块是否可以声明StorageBufferArrayDynamicIndexing功能。

37. shaderStorageImageArrayDynamicIndexing

指定是否可以通过着色器代码中的动态统一整数表达式索引存储器图像数组。
如果未启用此功能,则在着色器代码中聚合到数组中时,描述符类型为VK_DESCRIPTOR_TYPE_STORAGE_IMAGE的资源必须仅通过常量整数表达式编制索引。
这还指定着色器模块是否可以声明StorageImageArrayDynamicIndexing功能。

38. shaderClipDistance

指定着色器代码中是否支持ClipDistance。
如果未启用此功能,则不得在着色器模块中读取或写入使用ClipDistance内置装饰的任何成员。
这还指定着色器模块是否可以声明ClipDistance功能。

39. shaderCullDistance

指定着色器代码中是否支持CullDistance。
如果未启用此功能,则不得在着色器模块中读取或写入使用CullDistance内置装饰的任何成员。
这还指定着色器模块是否可以声明CullDistance功能。

40. shaderFloat64

指定着色器代码中是否支持64位浮点(双精度)。
如果未启用此功能,则不得在着色器代码中使用64位浮点类型。
这还指定着色器模块是否可以声明Float64功能。

41. shaderInt64

指定着色器代码中是否支持64位整数(有符号和无符号)。
如果未启用此功能,则不得在着色器代码中使用64位整数类型。
这还指定着色器模块是否可以声明Int64功能。

42. shaderInt16

指定着色器代码中是否支持16位整数(有符号和无符号)。
如果未启用此功能,则不得在着色器代码中使用16位整数类型。
这还指定着色器模块是否可以声明Int16功能。

43. shaderResourceResidency

指定着色器代码是否支持返回资源驻留信息的图像操作。
如果未启用此功能,则不得在着色器代码中使用OpImageSparse *指令。
这还指定着色器模块是否可以声明SparseResidency功能。
该功能至少需要支持一个sparseResidency *功能。

44. shaderResourceMinLod

指定着色器代码中是否支持指定最小资源LOD的图像操作。
如果未启用此功能,则不得在着色器代码中使用MinLod图像操作数。
这还指定着色器模块是否可以声明MinLod功能。

45. sparseBinding

指定是否可以在不透明的稀疏块级别而不是在对象级别管理资源内存。
如果未启用此功能,则必须使用vkBindBufferMemory和vkBindImageMemory命令仅基于每个对象绑定资源内存。 在这种情况下,不能分别使用VkBufferCreateInfo和VkImageCreateInfo结构的flags成员中设置的VK_BUFFER_CREATE_SPARSE_BINDING_BIT和VK_IMAGE_CREATE_SPARSE_BINDING_BIT创建缓冲区和映像。 否则,可以按稀疏资源特征中的描述管理资源存储器。

46. sparseResidencyBuffer

指定设备是否可以访问部分驻留缓冲区。
如果未启用此功能,则不能使用VkBufferCreateInfo结构的flags成员中设置的VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT创建缓冲区。

47. sparseResidencyImage2D

指定设备是否可以访问每个像素1个样本的部分驻留的2D图像。
如果未启用此功能,则不得使用VkImageCreateInfo结构的flags成员中设置的VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT创建imageType为VK_IMAGE_TYPE_2D且样本设置为VK_SAMPLE_COUNT_1_BIT的图像。

48. sparseResidencyImage3D

指定设备是否可以访问部分驻留的3D图像。
如果未启用此功能,则不得使用VkImageCreateInfo结构的flags成员中设置的VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT创建imageType为VK_IMAGE_TYPE_3D的映像。

49. sparseResidency2Samples

指定物理设备是否可以访问具有每像素2个样本的部分驻留的2D图像。
如果未启用此功能,则不得使用VkImageCreateInfo结构的flags成员中设置的VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT创建imageType为VK_IMAGE_TYPE_2D且样本设置为VK_SAMPLE_COUNT_2_BIT的图像。

50. sparseResidency4Samples

指定物理设备是否可以访问每个像素有4个样本的部分驻留的2D图像。
如果未启用此功能,则不得使用VkImageCreateInfo结构的flags成员中设置的VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT创建imageType为VK_IMAGE_TYPE_2D且样本设置为VK_SAMPLE_COUNT_4_BIT的图像。

51. sparseResidency8Samples

指定物理设备是否可以访问具有每像素8个样本的部分驻留的2D图像。
如果未启用此功能,则不得使用VkImageCreateInfo结构的flags成员中设置的VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT创建imageType为VK_IMAGE_TYPE_2D且样本设置为VK_SAMPLE_COUNT_8_BIT的图像。

52. sparseResidency16Samples

指定物理设备是否可以访问每个像素16个样本的部分驻留的2D图像。
如果未启用此功能,则不得使用VkImageCreateInfo结构的flags成员中设置的VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT创建imageType为VK_IMAGE_TYPE_2D且样本设置为VK_SAMPLE_COUNT_16_BIT的图像。

53. sparseResidencyAliased

指定物理设备是否可以正确访问别名到多个位置的数据。
如果未启用此功能,则不得分别在VkBufferCreateInfo和VkImageCreateInfo结构的flags成员中使用VK_BUFFER_CREATE_SPARSE_ALIASED_BIT和VK_IMAGE_CREATE_SPARSE_ALIASED_BIT枚举值。

54. variableMultisampleRate

指定在没有附件的子通行期间将绑定到命令缓冲区的所有管道是否必须具有VkPipelineMultisampleStateCreateInfo::rasterizationSamples的相同值。
如果设置为VK_TRUE,则实现支持不带附件的子通道中的可变多重采样率。
如果设置为VK_FALSE,则绑定在此子通道中的所有管道必须具有相同的多采样率。 但这在子通道使用任何附件的情况下无效。

55. inheritedQueries

指定在查询处于活动状态时是否可以执行辅助命令缓冲区。

说明:vkspec.html(2019/05/03)是从官方文档 https://github.com/KhronosGroup/Vulkan-Docs/ 中制作生成的。可以自行下载最新代码制作,也可以直接下载:

  1. csdn(需要5积分,不知道怎么去掉这个):https://download.csdn.net/download/u014535072/11158246
  2. 百度网盘:链接: https://pan.baidu.com/s/1IyPnb-2ti1SjU0puFKwYUQ 提取码: f2c2

欢迎关注我的其它发布渠道