holy
This commit is contained in:
parent
68bea8a225
commit
ee79b4c195
2
test3/.gitignore
vendored
Normal file
2
test3/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.o
|
||||||
|
test3
|
22
test3/Makefile
Normal file
22
test3/Makefile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
CC = gcc
|
||||||
|
LD = gcc
|
||||||
|
CFLAGS = -Wall -Wextra -pedantic -std=c11 -g -fPIC
|
||||||
|
# link kompute as a static library and the rest as dynamic
|
||||||
|
STATIC_LIBS =
|
||||||
|
DYNAMIC_LIBS = -lvulkan
|
||||||
|
LDFLAGS = -L/usr/local/lib \
|
||||||
|
-Wl,-Bstatic ${STATIC_LIBS} \
|
||||||
|
-Wl,-Bdynamic ${DYNAMIC_LIBS} \
|
||||||
|
-Wl,--as-needed
|
||||||
|
|
||||||
|
test3: main.o vk_result_to_str.o
|
||||||
|
$(LD) main.o vk_result_to_str.o -o test3 ${LDFLAGS}
|
||||||
|
|
||||||
|
vk_result_to_str.o: vk_result_to_str.c
|
||||||
|
$(CC) ${CFLAGS} -c vk_result_to_str.c
|
||||||
|
|
||||||
|
main.o: main.c
|
||||||
|
$(CC) ${CFLAGS} -c main.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f test3 main.o vk_result_to_str.o
|
1
test3/README
Normal file
1
test3/README
Normal file
@ -0,0 +1 @@
|
|||||||
|
Trying to implement test2 with just vulkan and in C
|
328
test3/main.c
Normal file
328
test3/main.c
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
// check for half precision floating point support, for x86 this is equivalent to
|
||||||
|
// checking for SSE2
|
||||||
|
#define SUPPORTS_NATIVE_FP16 (__x86_64__ == 1 && __SSE2__ == 1)
|
||||||
|
// print debug messages
|
||||||
|
#define DEBUG 1
|
||||||
|
#define VERBOSE 0
|
||||||
|
|
||||||
|
// define half precision floating point
|
||||||
|
#if SUPPORTS_NATIVE_FP16
|
||||||
|
// extension is needed due to -pedantic
|
||||||
|
__extension__ typedef _Float16 half;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *vk_validation_layer[] = {"VK_LAYER_KHRONOS_validation"};
|
||||||
|
const uint32_t vk_validation_layer_no = 1;
|
||||||
|
|
||||||
|
// FIXME: including vulkan/vk_enum_string_helper.h does not compile
|
||||||
|
extern const char *vk_Result_to_str(VkResult input);
|
||||||
|
|
||||||
|
// like printf but on stderr
|
||||||
|
int err(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
int ret = vfprintf(stderr, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print out all the instance extensions
|
||||||
|
// NOTE: these are different from device and shader extensions
|
||||||
|
int vk_enumerate_instance_extensions(void)
|
||||||
|
{
|
||||||
|
uint32_t ex_no = 0;
|
||||||
|
#if VERBOSE > 0
|
||||||
|
vkEnumerateInstanceExtensionProperties(NULL, &ex_no, NULL);
|
||||||
|
VkExtensionProperties *ex_arr =
|
||||||
|
malloc(sizeof(VkExtensionProperties) * ex_no);
|
||||||
|
if (ex_arr == NULL) {
|
||||||
|
err("ERROR: in %s: %s\n", __func__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
vkEnumerateInstanceExtensionProperties(NULL, &ex_no, ex_arr);
|
||||||
|
printf("Available Properties: \n");
|
||||||
|
for (uint32_t i = 0; i < ex_no; i++) {
|
||||||
|
printf("\t%s\n", ex_arr[i].extensionName);
|
||||||
|
}
|
||||||
|
free(ex_arr);
|
||||||
|
#endif
|
||||||
|
return ex_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on debug check for support of validation layers and activate one, a validation
|
||||||
|
// layer is useful to do more error checking at runtime like ckecking for invalid
|
||||||
|
// arguments, validation layers are available only if vulkan-sdk is installed
|
||||||
|
// (vulkan-devel on arch)
|
||||||
|
int vk_activate_validation_layer(VkInstanceCreateInfo *cinfo)
|
||||||
|
{
|
||||||
|
uint32_t prop_no = 0;
|
||||||
|
#if DEBUG > 0
|
||||||
|
vkEnumerateInstanceLayerProperties(&prop_no, NULL);
|
||||||
|
|
||||||
|
VkLayerProperties *prop_arr = malloc(sizeof(VkLayerProperties) * prop_no);
|
||||||
|
if (prop_arr == NULL) {
|
||||||
|
err("ERROR: in %s: %s\n", __func__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
vkEnumerateInstanceLayerProperties(&prop_no, prop_arr);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < prop_no; i++) {
|
||||||
|
if (strcmp(prop_arr[i].layerName, vk_validation_layer[0]) == 0) {
|
||||||
|
cinfo->enabledLayerCount = vk_validation_layer_no;
|
||||||
|
cinfo->ppEnabledLayerNames = vk_validation_layer;
|
||||||
|
free(prop_arr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(prop_arr);
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkInstance vk_init(void)
|
||||||
|
{
|
||||||
|
// create a vulkan instance and fill it with the application data
|
||||||
|
VkResult res;
|
||||||
|
VkInstance vk_instance = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkApplicationInfo vk_appinfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
|
.pNext = NULL,
|
||||||
|
.pApplicationName = __FILE__,
|
||||||
|
.applicationVersion = VK_MAKE_VERSION(0, 1, 0),
|
||||||
|
.pEngineName = "no engine",
|
||||||
|
.engineVersion = VK_MAKE_VERSION(0, 0, 0),
|
||||||
|
.apiVersion = VK_API_VERSION_1_3,
|
||||||
|
};
|
||||||
|
|
||||||
|
vk_enumerate_instance_extensions();
|
||||||
|
|
||||||
|
// TODO: check for extension availability
|
||||||
|
// TODO: does the lifetime of VkInstanceCreateInfo has to be the same as the
|
||||||
|
// lifetime of VkInstance?
|
||||||
|
const char *vk_instance_extensions[] = {
|
||||||
|
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
|
||||||
|
};
|
||||||
|
const uint32_t vk_instance_extensions_no =
|
||||||
|
(uint32_t)(sizeof(vk_instance_extensions) / sizeof(char *));
|
||||||
|
|
||||||
|
VkInstanceCreateInfo vk_instanceinfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
.pApplicationInfo = &vk_appinfo,
|
||||||
|
.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR,
|
||||||
|
.enabledExtensionCount = vk_instance_extensions_no,
|
||||||
|
.ppEnabledExtensionNames = vk_instance_extensions,
|
||||||
|
.enabledLayerCount = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
int e = 0;
|
||||||
|
if ((e = vk_activate_validation_layer(&vk_instanceinfo))) {
|
||||||
|
err("Could not activate validation layers%s\n",
|
||||||
|
e > 0 ? ": No validation layers found" : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
res = vkCreateInstance(&vk_instanceinfo, NULL, &vk_instance);
|
||||||
|
if (res != VK_SUCCESS) {
|
||||||
|
err("ERROR: Could not create vulkan instance %s",
|
||||||
|
vk_Result_to_str(res));
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
} else {
|
||||||
|
#if VERBOSE > 0
|
||||||
|
printf("Created vulkan instance\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return vk_instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vk_destroy(VkInstance vk_instance)
|
||||||
|
{
|
||||||
|
// ...
|
||||||
|
vkDestroyInstance(vk_instance, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPhysicalDevice vk_physical_device_get(VkInstance vk_instance)
|
||||||
|
{
|
||||||
|
VkPhysicalDevice vk_phydev = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
uint32_t vk_phydevs_no = 0;
|
||||||
|
VkPhysicalDevice *vk_phydevs;
|
||||||
|
vkEnumeratePhysicalDevices(vk_instance, &vk_phydevs_no, NULL);
|
||||||
|
|
||||||
|
if (vk_phydevs_no == 0) {
|
||||||
|
return vk_phydev;
|
||||||
|
}
|
||||||
|
|
||||||
|
vk_phydevs = malloc(sizeof(VkPhysicalDevice) * vk_phydevs_no);
|
||||||
|
if (vk_phydevs == NULL) {
|
||||||
|
err("ERROR: in %s: %s\n", __func__, strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
vkEnumeratePhysicalDevices(vk_instance, &vk_phydevs_no, vk_phydevs);
|
||||||
|
|
||||||
|
printf("Available Physical Devices: \n");
|
||||||
|
for (uint32_t i = 0; i < vk_phydevs_no; i++) {
|
||||||
|
VkPhysicalDevice device = vk_phydevs[i];
|
||||||
|
VkPhysicalDeviceProperties device_properties;
|
||||||
|
VkPhysicalDeviceFeatures device_features;
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceProperties(device, &device_properties);
|
||||||
|
vkGetPhysicalDeviceFeatures(device, &device_features);
|
||||||
|
|
||||||
|
printf(
|
||||||
|
"\tDevice %d: %s, Discrete: %s\n",
|
||||||
|
i,
|
||||||
|
device_properties.deviceName,
|
||||||
|
device_properties.deviceType ==
|
||||||
|
VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
||||||
|
? "true"
|
||||||
|
: "false"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: find the most suitable physical device, but for now every vulkan
|
||||||
|
// device has to be compatible with compute shaders
|
||||||
|
vk_phydev = vk_phydevs[0];
|
||||||
|
|
||||||
|
free(vk_phydevs);
|
||||||
|
return vk_phydev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vk_physical_device_destroy(VkPhysicalDevice vk_phydev)
|
||||||
|
{
|
||||||
|
if (vk_phydev != VK_NULL_HANDLE) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the index of the first queue family that supports compute on the device,
|
||||||
|
// returns a negative index on error
|
||||||
|
int vk_device_compute_queue_index(VkPhysicalDevice vk_phydev)
|
||||||
|
{
|
||||||
|
uint32_t vk_qfamilies_no = 0;
|
||||||
|
VkQueueFamilyProperties *vk_qfamilies;
|
||||||
|
int supports = -1;
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(vk_phydev, &vk_qfamilies_no, NULL);
|
||||||
|
|
||||||
|
vk_qfamilies = malloc(sizeof(VkQueueFamilyProperties) * vk_qfamilies_no);
|
||||||
|
if (vk_qfamilies == NULL) {
|
||||||
|
err("ERROR: in %s: %s\n", __func__, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(
|
||||||
|
vk_phydev, &vk_qfamilies_no, vk_qfamilies
|
||||||
|
);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < vk_qfamilies_no; i++) {
|
||||||
|
if (vk_qfamilies[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
|
||||||
|
supports = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(vk_qfamilies);
|
||||||
|
return supports;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDevice vk_logical_device_create(VkPhysicalDevice vk_phydev, int qfamily_idx)
|
||||||
|
{
|
||||||
|
VkResult res;
|
||||||
|
VkDevice vk_logdev = VK_NULL_HANDLE;
|
||||||
|
float vk_queue_priority = 1.0f;
|
||||||
|
|
||||||
|
// specify which command queues to use for the physical device
|
||||||
|
VkDeviceQueueCreateInfo vk_queueinfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||||
|
.pNext = NULL,
|
||||||
|
.flags = 0,
|
||||||
|
.queueFamilyIndex = qfamily_idx,
|
||||||
|
.queueCount = 1,
|
||||||
|
.pQueuePriorities = &vk_queue_priority,
|
||||||
|
};
|
||||||
|
|
||||||
|
// specify which device features to use
|
||||||
|
// TODO: this
|
||||||
|
VkPhysicalDeviceFeatures vk_phydev_features = {0};
|
||||||
|
|
||||||
|
// actually create the logical device
|
||||||
|
// TODO: figure out what device extensions are
|
||||||
|
// FIXME: here validation layers are ignored but it is still better to define
|
||||||
|
// them for compatibility
|
||||||
|
VkDeviceCreateInfo vk_createinfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
|
.pQueueCreateInfos = &vk_queueinfo,
|
||||||
|
.queueCreateInfoCount = 1,
|
||||||
|
.pEnabledFeatures = &vk_phydev_features,
|
||||||
|
.ppEnabledExtensionNames = NULL,
|
||||||
|
.enabledExtensionCount = 0,
|
||||||
|
.ppEnabledLayerNames = NULL,
|
||||||
|
.enabledLayerCount = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
res = vkCreateDevice(vk_phydev, &vk_createinfo, NULL, &vk_logdev);
|
||||||
|
if (res != VK_SUCCESS) {
|
||||||
|
err("ERROR: Could not create vulkan logical device %s",
|
||||||
|
vk_Result_to_str(res));
|
||||||
|
return VK_NULL_HANDLE;
|
||||||
|
} else {
|
||||||
|
#if VERBOSE > 0
|
||||||
|
printf("Created vulkan logical device\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return vk_logdev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vk_logical_device_destroy(VkDevice vk_logdev)
|
||||||
|
{
|
||||||
|
vkDestroyDevice(vk_logdev, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
VkQueue vk_queue_get(VkDevice vk_logdev, int qfamily_idx)
|
||||||
|
{
|
||||||
|
VkQueue vk_queue = VK_NULL_HANDLE;
|
||||||
|
vkGetDeviceQueue(vk_logdev, qfamily_idx, 0, &vk_queue);
|
||||||
|
return vk_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
#if VERBOSE > 0
|
||||||
|
if (SUPPORTS_NATIVE_FP16) {
|
||||||
|
printf("Processor supports half precision floating point\n");
|
||||||
|
} else {
|
||||||
|
printf("Processor doesn't support half precision floating point\n");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VkInstance vk_instance = vk_init();
|
||||||
|
if (vk_instance == VK_NULL_HANDLE) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
VkPhysicalDevice vk_phydev = vk_physical_device_get(vk_instance);
|
||||||
|
int qfamily_idx = vk_device_compute_queue_index(vk_phydev);
|
||||||
|
if (qfamily_idx < 0) {
|
||||||
|
err("The device does not support compute queues\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
VkDevice vk_logdev = vk_logical_device_create(vk_phydev, qfamily_idx);
|
||||||
|
|
||||||
|
vk_logical_device_destroy(vk_logdev);
|
||||||
|
vk_physical_device_destroy(vk_phydev);
|
||||||
|
vk_destroy(vk_instance);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
3
test3/util/.gitignore
vendored
Normal file
3
test3/util/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
__pycache__
|
||||||
|
out
|
||||||
|
vk.xml
|
6
test3/util/Makefile
Normal file
6
test3/util/Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
out/vk_enum_to_str.c: vk.xml
|
||||||
|
python gen_enum_to_str.py --beta false --xml vk.xml --outdir out
|
||||||
|
|
||||||
|
vk.xml:
|
||||||
|
wget -O vk.xml https://raw.githubusercontent.com/KhronosGroup/Vulkan-Docs/main/xml/vk.xml
|
||||||
|
|
573
test3/util/gen_enum_to_str.py
Normal file
573
test3/util/gen_enum_to_str.py
Normal file
@ -0,0 +1,573 @@
|
|||||||
|
# Copyright © 2017 Intel Corporation
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
"""Create enum to string functions for vulkan using vk.xml."""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import functools
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import textwrap
|
||||||
|
import xml.etree.ElementTree as et
|
||||||
|
|
||||||
|
from mako.template import Template
|
||||||
|
from vk_extensions import Extension, filter_api, get_all_required
|
||||||
|
|
||||||
|
COPYRIGHT = textwrap.dedent(u"""\
|
||||||
|
* Copyright © 2017 Intel Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.""")
|
||||||
|
|
||||||
|
C_TEMPLATE = Template(textwrap.dedent(u"""\
|
||||||
|
/* Autogenerated file -- do not edit
|
||||||
|
* generated by ${file}
|
||||||
|
*
|
||||||
|
${copyright}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
#include <vulkan/vk_android_native_buffer.h>
|
||||||
|
#include <vulkan/vk_layer.h>
|
||||||
|
#include "util/macros.h"
|
||||||
|
#include "vk_enum_to_str.h"
|
||||||
|
|
||||||
|
% for enum in enums:
|
||||||
|
|
||||||
|
% if enum.guard:
|
||||||
|
#ifdef ${enum.guard}
|
||||||
|
% endif
|
||||||
|
const char *
|
||||||
|
vk_${enum.name[2:]}_to_str(${enum.name} input)
|
||||||
|
{
|
||||||
|
switch((int64_t)input) {
|
||||||
|
% for v in sorted(enum.values.keys()):
|
||||||
|
case ${v}:
|
||||||
|
return "${enum.values[v]}";
|
||||||
|
% endfor
|
||||||
|
case ${enum.max_enum_name}: return "${enum.max_enum_name}";
|
||||||
|
default:
|
||||||
|
return "Unknown ${enum.name} value.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
% if enum.guard:
|
||||||
|
#endif
|
||||||
|
% endif
|
||||||
|
%endfor
|
||||||
|
|
||||||
|
% for enum in bitmasks:
|
||||||
|
|
||||||
|
% if enum.guard:
|
||||||
|
#ifdef ${enum.guard}
|
||||||
|
% endif
|
||||||
|
const char *
|
||||||
|
vk_${enum.name[2:]}_to_str(${enum.name} input)
|
||||||
|
{
|
||||||
|
switch((int64_t)input) {
|
||||||
|
% for v in sorted(enum.values.keys()):
|
||||||
|
case ${v}:
|
||||||
|
return "${enum.values[v]}";
|
||||||
|
% endfor
|
||||||
|
default:
|
||||||
|
return "Unknown ${enum.name} value.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
% if enum.guard:
|
||||||
|
#endif
|
||||||
|
% endif
|
||||||
|
%endfor
|
||||||
|
|
||||||
|
size_t vk_structure_type_size(const struct VkBaseInStructure *item)
|
||||||
|
{
|
||||||
|
switch((int)item->sType) {
|
||||||
|
% for struct in structs:
|
||||||
|
% if struct.extension is not None and struct.extension.define is not None:
|
||||||
|
#ifdef ${struct.extension.define}
|
||||||
|
case ${struct.stype}: return sizeof(${struct.name});
|
||||||
|
#endif
|
||||||
|
% else:
|
||||||
|
case ${struct.stype}: return sizeof(${struct.name});
|
||||||
|
% endif
|
||||||
|
%endfor
|
||||||
|
case VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO: return sizeof(VkLayerInstanceCreateInfo);
|
||||||
|
case VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO: return sizeof(VkLayerDeviceCreateInfo);
|
||||||
|
default:
|
||||||
|
unreachable("Undefined struct type.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
vk_ObjectType_to_ObjectName(VkObjectType type)
|
||||||
|
{
|
||||||
|
switch((int)type) {
|
||||||
|
% for object_type in sorted(object_types[0].enum_to_name.keys()):
|
||||||
|
case ${object_type}:
|
||||||
|
return "${object_types[0].enum_to_name[object_type]}";
|
||||||
|
% endfor
|
||||||
|
default:
|
||||||
|
return "Unknown VkObjectType value.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""))
|
||||||
|
|
||||||
|
H_TEMPLATE = Template(textwrap.dedent(u"""\
|
||||||
|
/* Autogenerated file -- do not edit
|
||||||
|
* generated by ${file}
|
||||||
|
*
|
||||||
|
${copyright}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MESA_VK_ENUM_TO_STR_H
|
||||||
|
#define MESA_VK_ENUM_TO_STR_H
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
#include <vulkan/vk_android_native_buffer.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
% for enum in enums:
|
||||||
|
% if enum.guard:
|
||||||
|
#ifdef ${enum.guard}
|
||||||
|
% endif
|
||||||
|
const char * vk_${enum.name[2:]}_to_str(${enum.name} input);
|
||||||
|
% if enum.guard:
|
||||||
|
#endif
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
% for enum in bitmasks:
|
||||||
|
% if enum.guard:
|
||||||
|
#ifdef ${enum.guard}
|
||||||
|
% endif
|
||||||
|
const char * vk_${enum.name[2:]}_to_str(${enum.name} input);
|
||||||
|
% if enum.guard:
|
||||||
|
#endif
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
size_t vk_structure_type_size(const struct VkBaseInStructure *item);
|
||||||
|
|
||||||
|
const char * vk_ObjectType_to_ObjectName(VkObjectType type);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif"""))
|
||||||
|
|
||||||
|
|
||||||
|
H_DEFINE_TEMPLATE = Template(textwrap.dedent(u"""\
|
||||||
|
/* Autogenerated file -- do not edit
|
||||||
|
* generated by ${file}
|
||||||
|
*
|
||||||
|
${copyright}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MESA_VK_ENUM_DEFINES_H
|
||||||
|
#define MESA_VK_ENUM_DEFINES_H
|
||||||
|
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
#include <vulkan/vk_android_native_buffer.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
% for ext in extensions:
|
||||||
|
#define _${ext.name}_number (${ext.number})
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
% for enum in bitmasks:
|
||||||
|
% if enum.bitwidth > 32:
|
||||||
|
<% continue %>
|
||||||
|
% endif
|
||||||
|
% if enum.guard:
|
||||||
|
#ifdef ${enum.guard}
|
||||||
|
% endif
|
||||||
|
#define ${enum.all_bits_name()} ${hex(enum.all_bits_value())}u
|
||||||
|
% if enum.guard:
|
||||||
|
#endif
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
% for enum in bitmasks:
|
||||||
|
% if enum.bitwidth < 64:
|
||||||
|
<% continue %>
|
||||||
|
% endif
|
||||||
|
/* Redefine bitmask values of ${enum.name} */
|
||||||
|
% if enum.guard:
|
||||||
|
#ifdef ${enum.guard}
|
||||||
|
% endif
|
||||||
|
% for n, v in enum.name_to_value.items():
|
||||||
|
#define ${n} (${hex(v)}ULL)
|
||||||
|
% endfor
|
||||||
|
% if enum.guard:
|
||||||
|
#endif
|
||||||
|
% endif
|
||||||
|
% endfor
|
||||||
|
|
||||||
|
static inline VkFormatFeatureFlags
|
||||||
|
vk_format_features2_to_features(VkFormatFeatureFlags2 features2)
|
||||||
|
{
|
||||||
|
return features2 & VK_ALL_FORMAT_FEATURE_FLAG_BITS;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif"""))
|
||||||
|
|
||||||
|
|
||||||
|
class NamedFactory(object):
|
||||||
|
"""Factory for creating enums."""
|
||||||
|
|
||||||
|
def __init__(self, type_):
|
||||||
|
self.registry = {}
|
||||||
|
self.type = type_
|
||||||
|
|
||||||
|
def __call__(self, name, **kwargs):
|
||||||
|
try:
|
||||||
|
return self.registry[name]
|
||||||
|
except KeyError:
|
||||||
|
n = self.registry[name] = self.type(name, **kwargs)
|
||||||
|
return n
|
||||||
|
|
||||||
|
def get(self, name):
|
||||||
|
return self.registry.get(name)
|
||||||
|
|
||||||
|
|
||||||
|
class VkExtension(object):
|
||||||
|
"""Simple struct-like class representing extensions"""
|
||||||
|
|
||||||
|
def __init__(self, name, number=None, define=None):
|
||||||
|
self.name = name
|
||||||
|
self.number = number
|
||||||
|
self.define = define
|
||||||
|
|
||||||
|
|
||||||
|
def CamelCase_to_SHOUT_CASE(s):
|
||||||
|
return (s[:1] + re.sub(r'(?<![A-Z])([A-Z])', r'_\1', s[1:])).upper()
|
||||||
|
|
||||||
|
def compute_max_enum_name(s):
|
||||||
|
if s == "VkSwapchainImageUsageFlagBitsANDROID":
|
||||||
|
return "VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM"
|
||||||
|
max_enum_name = CamelCase_to_SHOUT_CASE(s)
|
||||||
|
last_prefix = max_enum_name.rsplit('_', 1)[-1]
|
||||||
|
# Those special prefixes need to be always at the end
|
||||||
|
if last_prefix in ['AMD', 'EXT', 'INTEL', 'KHR', 'NV', 'LUNARG', 'QCOM', 'MSFT'] :
|
||||||
|
max_enum_name = "_".join(max_enum_name.split('_')[:-1])
|
||||||
|
max_enum_name = max_enum_name + "_MAX_ENUM_" + last_prefix
|
||||||
|
else:
|
||||||
|
max_enum_name = max_enum_name + "_MAX_ENUM"
|
||||||
|
|
||||||
|
return max_enum_name
|
||||||
|
|
||||||
|
class VkEnum(object):
|
||||||
|
"""Simple struct-like class representing a single Vulkan Enum."""
|
||||||
|
|
||||||
|
def __init__(self, name, bitwidth=32, values=None):
|
||||||
|
self.name = name
|
||||||
|
self.max_enum_name = compute_max_enum_name(name)
|
||||||
|
self.bitwidth = bitwidth
|
||||||
|
self.extension = None
|
||||||
|
# Maps numbers to names
|
||||||
|
self.values = values or dict()
|
||||||
|
self.name_to_value = dict()
|
||||||
|
self.guard = None
|
||||||
|
self.name_to_alias_list = {}
|
||||||
|
|
||||||
|
def all_bits_name(self):
|
||||||
|
assert self.name.startswith('Vk')
|
||||||
|
assert re.search(r'FlagBits[A-Z]*$', self.name)
|
||||||
|
|
||||||
|
return 'VK_ALL_' + CamelCase_to_SHOUT_CASE(self.name[2:])
|
||||||
|
|
||||||
|
def all_bits_value(self):
|
||||||
|
return functools.reduce(lambda a,b: a | b, self.values.keys(), 0)
|
||||||
|
|
||||||
|
def add_value(self, name, value=None,
|
||||||
|
extnum=None, offset=None, alias=None,
|
||||||
|
error=False):
|
||||||
|
if alias is not None:
|
||||||
|
assert value is None and offset is None
|
||||||
|
if alias not in self.name_to_value:
|
||||||
|
# We don't have this alias yet. Just record the alias and
|
||||||
|
# we'll deal with it later.
|
||||||
|
alias_list = self.name_to_alias_list.setdefault(alias, [])
|
||||||
|
alias_list.append(name);
|
||||||
|
return
|
||||||
|
|
||||||
|
# Use the value from the alias
|
||||||
|
value = self.name_to_value[alias]
|
||||||
|
|
||||||
|
assert value is not None or extnum is not None
|
||||||
|
if value is None:
|
||||||
|
value = 1000000000 + (extnum - 1) * 1000 + offset
|
||||||
|
if error:
|
||||||
|
value = -value
|
||||||
|
|
||||||
|
self.name_to_value[name] = value
|
||||||
|
if value not in self.values:
|
||||||
|
self.values[value] = name
|
||||||
|
elif len(self.values[value]) > len(name):
|
||||||
|
self.values[value] = name
|
||||||
|
|
||||||
|
# Now that the value has been fully added, resolve aliases, if any.
|
||||||
|
if name in self.name_to_alias_list:
|
||||||
|
for alias in self.name_to_alias_list[name]:
|
||||||
|
self.add_value(alias, value)
|
||||||
|
del self.name_to_alias_list[name]
|
||||||
|
|
||||||
|
def add_value_from_xml(self, elem, extension=None):
|
||||||
|
self.extension = extension
|
||||||
|
if 'value' in elem.attrib:
|
||||||
|
self.add_value(elem.attrib['name'],
|
||||||
|
value=int(elem.attrib['value'], base=0))
|
||||||
|
elif 'bitpos' in elem.attrib:
|
||||||
|
self.add_value(elem.attrib['name'],
|
||||||
|
value=(1 << int(elem.attrib['bitpos'], base=0)))
|
||||||
|
elif 'alias' in elem.attrib:
|
||||||
|
self.add_value(elem.attrib['name'], alias=elem.attrib['alias'])
|
||||||
|
else:
|
||||||
|
error = 'dir' in elem.attrib and elem.attrib['dir'] == '-'
|
||||||
|
if 'extnumber' in elem.attrib:
|
||||||
|
extnum = int(elem.attrib['extnumber'])
|
||||||
|
else:
|
||||||
|
extnum = extension.number
|
||||||
|
self.add_value(elem.attrib['name'],
|
||||||
|
extnum=extnum,
|
||||||
|
offset=int(elem.attrib['offset']),
|
||||||
|
error=error)
|
||||||
|
|
||||||
|
def set_guard(self, g):
|
||||||
|
self.guard = g
|
||||||
|
|
||||||
|
|
||||||
|
class VkChainStruct(object):
|
||||||
|
"""Simple struct-like class representing a single Vulkan struct identified with a VkStructureType"""
|
||||||
|
def __init__(self, name, stype):
|
||||||
|
self.name = name
|
||||||
|
self.stype = stype
|
||||||
|
self.extension = None
|
||||||
|
|
||||||
|
|
||||||
|
def struct_get_stype(xml_node):
|
||||||
|
for member in xml_node.findall('./member'):
|
||||||
|
name = member.findall('./name')
|
||||||
|
if len(name) > 0 and name[0].text == "sType":
|
||||||
|
return member.get('values')
|
||||||
|
return None
|
||||||
|
|
||||||
|
class VkObjectType(object):
|
||||||
|
"""Simple struct-like class representing a single Vulkan object type"""
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.enum_to_name = dict()
|
||||||
|
|
||||||
|
|
||||||
|
def parse_xml(enum_factory, ext_factory, struct_factory, bitmask_factory,
|
||||||
|
obj_type_factory, filename, beta):
|
||||||
|
"""Parse the XML file. Accumulate results into the factories.
|
||||||
|
|
||||||
|
This parser is a memory efficient iterative XML parser that returns a list
|
||||||
|
of VkEnum objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
xml = et.parse(filename)
|
||||||
|
api = 'vulkan'
|
||||||
|
|
||||||
|
required_types = get_all_required(xml, 'type', api, beta)
|
||||||
|
|
||||||
|
for enum_type in xml.findall('./enums[@type="enum"]'):
|
||||||
|
if not filter_api(enum_type, api):
|
||||||
|
continue
|
||||||
|
|
||||||
|
type_name = enum_type.attrib['name']
|
||||||
|
if not type_name in required_types:
|
||||||
|
continue
|
||||||
|
|
||||||
|
enum = enum_factory(type_name)
|
||||||
|
for value in enum_type.findall('./enum'):
|
||||||
|
if filter_api(value, api):
|
||||||
|
enum.add_value_from_xml(value)
|
||||||
|
|
||||||
|
# For bitmask we only add the Enum selected for convenience.
|
||||||
|
for enum_type in xml.findall('./enums[@type="bitmask"]'):
|
||||||
|
if not filter_api(enum_type, api):
|
||||||
|
continue
|
||||||
|
|
||||||
|
type_name = enum_type.attrib['name']
|
||||||
|
if not type_name in required_types:
|
||||||
|
continue
|
||||||
|
|
||||||
|
bitwidth = int(enum_type.attrib.get('bitwidth', 32))
|
||||||
|
enum = bitmask_factory(type_name, bitwidth=bitwidth)
|
||||||
|
for value in enum_type.findall('./enum'):
|
||||||
|
if filter_api(value, api):
|
||||||
|
enum.add_value_from_xml(value)
|
||||||
|
|
||||||
|
for feature in xml.findall('./feature'):
|
||||||
|
if not api in feature.attrib['api'].split(','):
|
||||||
|
continue
|
||||||
|
|
||||||
|
for value in feature.findall('./require/enum[@extends]'):
|
||||||
|
extends = value.attrib['extends']
|
||||||
|
enum = enum_factory.get(extends)
|
||||||
|
if enum is not None:
|
||||||
|
enum.add_value_from_xml(value)
|
||||||
|
enum = bitmask_factory.get(extends)
|
||||||
|
if enum is not None:
|
||||||
|
enum.add_value_from_xml(value)
|
||||||
|
|
||||||
|
for struct_type in xml.findall('./types/type[@category="struct"]'):
|
||||||
|
if not filter_api(struct_type, api):
|
||||||
|
continue
|
||||||
|
|
||||||
|
name = struct_type.attrib['name']
|
||||||
|
if name not in required_types:
|
||||||
|
continue
|
||||||
|
|
||||||
|
stype = struct_get_stype(struct_type)
|
||||||
|
if stype is not None:
|
||||||
|
struct_factory(name, stype=stype)
|
||||||
|
|
||||||
|
platform_define = {}
|
||||||
|
for platform in xml.findall('./platforms/platform'):
|
||||||
|
name = platform.attrib['name']
|
||||||
|
define = platform.attrib['protect']
|
||||||
|
platform_define[name] = define
|
||||||
|
|
||||||
|
for ext_elem in xml.findall('./extensions/extension'):
|
||||||
|
ext = Extension.from_xml(ext_elem)
|
||||||
|
if api not in ext.supported:
|
||||||
|
continue
|
||||||
|
|
||||||
|
define = platform_define.get(ext.platform, None)
|
||||||
|
extension = ext_factory(ext.name, number=ext.number, define=define)
|
||||||
|
|
||||||
|
for req_elem in ext_elem.findall('./require'):
|
||||||
|
if not filter_api(req_elem, api):
|
||||||
|
continue
|
||||||
|
|
||||||
|
for value in req_elem.findall('./enum[@extends]'):
|
||||||
|
extends = value.attrib['extends']
|
||||||
|
enum = enum_factory.get(extends)
|
||||||
|
if enum is not None:
|
||||||
|
enum.add_value_from_xml(value, extension)
|
||||||
|
enum = bitmask_factory.get(extends)
|
||||||
|
if enum is not None:
|
||||||
|
enum.add_value_from_xml(value, extension)
|
||||||
|
|
||||||
|
for t in req_elem.findall('./type'):
|
||||||
|
struct = struct_factory.get(t.attrib['name'])
|
||||||
|
if struct is not None:
|
||||||
|
struct.extension = extension
|
||||||
|
|
||||||
|
if define:
|
||||||
|
for value in ext_elem.findall('./require/type[@name]'):
|
||||||
|
enum = enum_factory.get(value.attrib['name'])
|
||||||
|
if enum is not None:
|
||||||
|
enum.set_guard(define)
|
||||||
|
enum = bitmask_factory.get(value.attrib['name'])
|
||||||
|
if enum is not None:
|
||||||
|
enum.set_guard(define)
|
||||||
|
|
||||||
|
obj_type_enum = enum_factory.get("VkObjectType")
|
||||||
|
obj_types = obj_type_factory("VkObjectType")
|
||||||
|
for object_type in xml.findall('./types/type[@category="handle"]'):
|
||||||
|
for object_name in object_type.findall('./name'):
|
||||||
|
# Convert to int to avoid undefined enums
|
||||||
|
enum = object_type.attrib['objtypeenum']
|
||||||
|
|
||||||
|
# Annoyingly, object types are hard to filter by API so just
|
||||||
|
# look for whether or not we can find the enum name in the
|
||||||
|
# VkObjectType enum.
|
||||||
|
if enum not in obj_type_enum.name_to_value:
|
||||||
|
continue
|
||||||
|
|
||||||
|
enum_val = obj_type_enum.name_to_value[enum]
|
||||||
|
obj_types.enum_to_name[enum_val] = object_name.text
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--beta', required=True, help='Enable beta extensions.')
|
||||||
|
parser.add_argument('--xml', required=True,
|
||||||
|
help='Vulkan API XML files',
|
||||||
|
action='append',
|
||||||
|
dest='xml_files')
|
||||||
|
parser.add_argument('--outdir',
|
||||||
|
help='Directory to put the generated files in',
|
||||||
|
required=True)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
enum_factory = NamedFactory(VkEnum)
|
||||||
|
ext_factory = NamedFactory(VkExtension)
|
||||||
|
struct_factory = NamedFactory(VkChainStruct)
|
||||||
|
obj_type_factory = NamedFactory(VkObjectType)
|
||||||
|
bitmask_factory = NamedFactory(VkEnum)
|
||||||
|
|
||||||
|
for filename in args.xml_files:
|
||||||
|
parse_xml(enum_factory, ext_factory, struct_factory, bitmask_factory,
|
||||||
|
obj_type_factory, filename, args.beta)
|
||||||
|
enums = sorted(enum_factory.registry.values(), key=lambda e: e.name)
|
||||||
|
extensions = sorted(ext_factory.registry.values(), key=lambda e: e.name)
|
||||||
|
structs = sorted(struct_factory.registry.values(), key=lambda e: e.name)
|
||||||
|
bitmasks = sorted(bitmask_factory.registry.values(), key=lambda e: e.name)
|
||||||
|
object_types = sorted(obj_type_factory.registry.values(), key=lambda e: e.name)
|
||||||
|
|
||||||
|
for template, file_ in [(C_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.c')),
|
||||||
|
(H_TEMPLATE, os.path.join(args.outdir, 'vk_enum_to_str.h')),
|
||||||
|
(H_DEFINE_TEMPLATE, os.path.join(args.outdir, 'vk_enum_defines.h'))]:
|
||||||
|
with open(file_, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(template.render(
|
||||||
|
file=os.path.basename(__file__),
|
||||||
|
enums=enums,
|
||||||
|
extensions=extensions,
|
||||||
|
structs=structs,
|
||||||
|
bitmasks=bitmasks,
|
||||||
|
object_types=object_types,
|
||||||
|
copyright=COPYRIGHT))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
3
test3/util/test_sse.sh
Executable file
3
test3/util/test_sse.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
gcc -msse3 -dM -E - < /dev/null | grep -E "SSE|AVX" | sort
|
356
test3/util/vk_extensions.py
Normal file
356
test3/util/vk_extensions.py
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
import copy
|
||||||
|
import re
|
||||||
|
import xml.etree.ElementTree as et
|
||||||
|
|
||||||
|
def get_api_list(s):
|
||||||
|
apis = []
|
||||||
|
for a in s.split(','):
|
||||||
|
if a == 'disabled':
|
||||||
|
continue
|
||||||
|
assert a in ('vulkan', 'vulkansc')
|
||||||
|
apis.append(a)
|
||||||
|
return apis
|
||||||
|
|
||||||
|
class Extension:
|
||||||
|
def __init__(self, name, number, ext_version):
|
||||||
|
self.name = name
|
||||||
|
self.type = None
|
||||||
|
self.number = number
|
||||||
|
self.platform = None
|
||||||
|
self.provisional = False
|
||||||
|
self.ext_version = int(ext_version)
|
||||||
|
self.supported = []
|
||||||
|
|
||||||
|
def from_xml(ext_elem):
|
||||||
|
name = ext_elem.attrib['name']
|
||||||
|
number = int(ext_elem.attrib['number'])
|
||||||
|
supported = get_api_list(ext_elem.attrib['supported'])
|
||||||
|
if name == 'VK_ANDROID_native_buffer':
|
||||||
|
assert not supported
|
||||||
|
supported = ['vulkan']
|
||||||
|
|
||||||
|
if not supported:
|
||||||
|
return Extension(name, number, 0)
|
||||||
|
|
||||||
|
version = None
|
||||||
|
for enum_elem in ext_elem.findall('.require/enum'):
|
||||||
|
if enum_elem.attrib['name'].endswith('_SPEC_VERSION'):
|
||||||
|
# Skip alias SPEC_VERSIONs
|
||||||
|
if 'value' in enum_elem.attrib:
|
||||||
|
assert version is None
|
||||||
|
version = int(enum_elem.attrib['value'])
|
||||||
|
|
||||||
|
assert version is not None
|
||||||
|
ext = Extension(name, number, version)
|
||||||
|
ext.type = ext_elem.attrib['type']
|
||||||
|
ext.platform = ext_elem.attrib.get('platform', None)
|
||||||
|
ext.provisional = ext_elem.attrib.get('provisional', False)
|
||||||
|
ext.supported = supported
|
||||||
|
|
||||||
|
return ext
|
||||||
|
|
||||||
|
def c_android_condition(self):
|
||||||
|
# if it's an EXT or vendor extension, it's allowed
|
||||||
|
if not self.name.startswith(ANDROID_EXTENSION_WHITELIST_PREFIXES):
|
||||||
|
return 'true'
|
||||||
|
|
||||||
|
allowed_version = ALLOWED_ANDROID_VERSION.get(self.name, None)
|
||||||
|
if allowed_version is None:
|
||||||
|
return 'false'
|
||||||
|
|
||||||
|
return 'ANDROID_API_LEVEL >= %d' % (allowed_version)
|
||||||
|
|
||||||
|
class ApiVersion:
|
||||||
|
def __init__(self, version):
|
||||||
|
self.version = version
|
||||||
|
|
||||||
|
class VkVersion:
|
||||||
|
def __init__(self, string):
|
||||||
|
split = string.split('.')
|
||||||
|
self.major = int(split[0])
|
||||||
|
self.minor = int(split[1])
|
||||||
|
if len(split) > 2:
|
||||||
|
assert len(split) == 3
|
||||||
|
self.patch = int(split[2])
|
||||||
|
else:
|
||||||
|
self.patch = None
|
||||||
|
|
||||||
|
# Sanity check. The range bits are required by the definition of the
|
||||||
|
# VK_MAKE_VERSION macro
|
||||||
|
assert self.major < 1024 and self.minor < 1024
|
||||||
|
assert self.patch is None or self.patch < 4096
|
||||||
|
assert str(self) == string
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
ver_list = [str(self.major), str(self.minor)]
|
||||||
|
if self.patch is not None:
|
||||||
|
ver_list.append(str(self.patch))
|
||||||
|
return '.'.join(ver_list)
|
||||||
|
|
||||||
|
def c_vk_version(self):
|
||||||
|
ver_list = [str(self.major), str(self.minor), str(self.patch or 0)]
|
||||||
|
return 'VK_MAKE_VERSION(' + ', '.join(ver_list) + ')'
|
||||||
|
|
||||||
|
def __int_ver(self):
|
||||||
|
# This is just an expansion of VK_VERSION
|
||||||
|
return (self.major << 22) | (self.minor << 12) | (self.patch or 0)
|
||||||
|
|
||||||
|
def __gt__(self, other):
|
||||||
|
# If only one of them has a patch version, "ignore" it by making
|
||||||
|
# other's patch version match self.
|
||||||
|
if (self.patch is None) != (other.patch is None):
|
||||||
|
other = copy.copy(other)
|
||||||
|
other.patch = self.patch
|
||||||
|
|
||||||
|
return self.__int_ver() > other.__int_ver()
|
||||||
|
|
||||||
|
# Sort the extension list the way we expect: KHR, then EXT, then vendors
|
||||||
|
# alphabetically. For digits, read them as a whole number sort that.
|
||||||
|
# eg.: VK_KHR_8bit_storage < VK_KHR_16bit_storage < VK_EXT_acquire_xlib_display
|
||||||
|
def extension_order(ext):
|
||||||
|
order = []
|
||||||
|
for substring in re.split('(KHR|EXT|[0-9]+)', ext.name):
|
||||||
|
if substring == 'KHR':
|
||||||
|
order.append(1)
|
||||||
|
if substring == 'EXT':
|
||||||
|
order.append(2)
|
||||||
|
elif substring.isdigit():
|
||||||
|
order.append(int(substring))
|
||||||
|
else:
|
||||||
|
order.append(substring)
|
||||||
|
return order
|
||||||
|
|
||||||
|
def get_all_exts_from_xml(xml, api='vulkan'):
|
||||||
|
""" Get a list of all Vulkan extensions. """
|
||||||
|
|
||||||
|
xml = et.parse(xml)
|
||||||
|
|
||||||
|
extensions = []
|
||||||
|
for ext_elem in xml.findall('.extensions/extension'):
|
||||||
|
ext = Extension.from_xml(ext_elem)
|
||||||
|
if api in ext.supported:
|
||||||
|
extensions.append(ext)
|
||||||
|
|
||||||
|
return sorted(extensions, key=extension_order)
|
||||||
|
|
||||||
|
def init_exts_from_xml(xml, extensions, platform_defines):
|
||||||
|
""" Walk the Vulkan XML and fill out extra extension information. """
|
||||||
|
|
||||||
|
xml = et.parse(xml)
|
||||||
|
|
||||||
|
ext_name_map = {}
|
||||||
|
for ext in extensions:
|
||||||
|
ext_name_map[ext.name] = ext
|
||||||
|
|
||||||
|
# KHR_display is missing from the list.
|
||||||
|
platform_defines.append('VK_USE_PLATFORM_DISPLAY_KHR')
|
||||||
|
for platform in xml.findall('./platforms/platform'):
|
||||||
|
platform_defines.append(platform.attrib['protect'])
|
||||||
|
|
||||||
|
for ext_elem in xml.findall('.extensions/extension'):
|
||||||
|
ext_name = ext_elem.attrib['name']
|
||||||
|
if ext_name not in ext_name_map:
|
||||||
|
continue
|
||||||
|
|
||||||
|
ext = ext_name_map[ext_name]
|
||||||
|
ext.type = ext_elem.attrib['type']
|
||||||
|
|
||||||
|
class Requirements:
|
||||||
|
def __init__(self, core_version=None):
|
||||||
|
self.core_version = core_version
|
||||||
|
self.extensions = []
|
||||||
|
self.guard = None
|
||||||
|
|
||||||
|
def add_extension(self, ext):
|
||||||
|
for e in self.extensions:
|
||||||
|
if e == ext:
|
||||||
|
return;
|
||||||
|
assert e.name != ext.name
|
||||||
|
|
||||||
|
self.extensions.append(ext)
|
||||||
|
|
||||||
|
def filter_api(elem, api):
|
||||||
|
if 'api' not in elem.attrib:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return api in elem.attrib['api'].split(',')
|
||||||
|
|
||||||
|
def get_all_required(xml, thing, api, beta):
|
||||||
|
things = {}
|
||||||
|
for feature in xml.findall('./feature'):
|
||||||
|
if not filter_api(feature, api):
|
||||||
|
continue
|
||||||
|
|
||||||
|
version = VkVersion(feature.attrib['number'])
|
||||||
|
for t in feature.findall('./require/' + thing):
|
||||||
|
name = t.attrib['name']
|
||||||
|
assert name not in things
|
||||||
|
things[name] = Requirements(core_version=version)
|
||||||
|
|
||||||
|
for extension in xml.findall('.extensions/extension'):
|
||||||
|
ext = Extension.from_xml(extension)
|
||||||
|
if api not in ext.supported:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if beta != 'true' and ext.provisional:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for require in extension.findall('./require'):
|
||||||
|
if not filter_api(require, api):
|
||||||
|
continue
|
||||||
|
|
||||||
|
for t in require.findall('./' + thing):
|
||||||
|
name = t.attrib['name']
|
||||||
|
r = things.setdefault(name, Requirements())
|
||||||
|
r.add_extension(ext)
|
||||||
|
|
||||||
|
platform_defines = {}
|
||||||
|
for platform in xml.findall('./platforms/platform'):
|
||||||
|
name = platform.attrib['name']
|
||||||
|
define = platform.attrib['protect']
|
||||||
|
platform_defines[name] = define
|
||||||
|
|
||||||
|
for req in things.values():
|
||||||
|
if req.core_version is not None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for ext in req.extensions:
|
||||||
|
if ext.platform in platform_defines:
|
||||||
|
req.guard = platform_defines[ext.platform]
|
||||||
|
break
|
||||||
|
|
||||||
|
return things
|
||||||
|
|
||||||
|
# Mapping between extension name and the android version in which the extension
|
||||||
|
# was whitelisted in Android CTS's dEQP-VK.info.device_extensions and
|
||||||
|
# dEQP-VK.api.info.android.no_unknown_extensions, excluding those blocked by
|
||||||
|
# android.graphics.cts.VulkanFeaturesTest#testVulkanBlockedExtensions.
|
||||||
|
ALLOWED_ANDROID_VERSION = {
|
||||||
|
# checkInstanceExtensions on oreo-cts-release
|
||||||
|
"VK_KHR_surface": 26,
|
||||||
|
"VK_KHR_display": 26,
|
||||||
|
"VK_KHR_android_surface": 26,
|
||||||
|
"VK_KHR_mir_surface": 26,
|
||||||
|
"VK_KHR_wayland_surface": 26,
|
||||||
|
"VK_KHR_win32_surface": 26,
|
||||||
|
"VK_KHR_xcb_surface": 26,
|
||||||
|
"VK_KHR_xlib_surface": 26,
|
||||||
|
"VK_KHR_get_physical_device_properties2": 26,
|
||||||
|
"VK_KHR_get_surface_capabilities2": 26,
|
||||||
|
"VK_KHR_external_memory_capabilities": 26,
|
||||||
|
"VK_KHR_external_semaphore_capabilities": 26,
|
||||||
|
"VK_KHR_external_fence_capabilities": 26,
|
||||||
|
# on pie-cts-release
|
||||||
|
"VK_KHR_device_group_creation": 28,
|
||||||
|
"VK_KHR_get_display_properties2": 28,
|
||||||
|
# on android10-tests-release
|
||||||
|
"VK_KHR_surface_protected_capabilities": 29,
|
||||||
|
# on android13-tests-release
|
||||||
|
"VK_KHR_portability_enumeration": 33,
|
||||||
|
|
||||||
|
# checkDeviceExtensions on oreo-cts-release
|
||||||
|
"VK_KHR_swapchain": 26,
|
||||||
|
"VK_KHR_display_swapchain": 26,
|
||||||
|
"VK_KHR_sampler_mirror_clamp_to_edge": 26,
|
||||||
|
"VK_KHR_shader_draw_parameters": 26,
|
||||||
|
"VK_KHR_maintenance1": 26,
|
||||||
|
"VK_KHR_push_descriptor": 26,
|
||||||
|
"VK_KHR_descriptor_update_template": 26,
|
||||||
|
"VK_KHR_incremental_present": 26,
|
||||||
|
"VK_KHR_shared_presentable_image": 26,
|
||||||
|
"VK_KHR_storage_buffer_storage_class": 26,
|
||||||
|
"VK_KHR_16bit_storage": 26,
|
||||||
|
"VK_KHR_get_memory_requirements2": 26,
|
||||||
|
"VK_KHR_external_memory": 26,
|
||||||
|
"VK_KHR_external_memory_fd": 26,
|
||||||
|
"VK_KHR_external_memory_win32": 26,
|
||||||
|
"VK_KHR_external_semaphore": 26,
|
||||||
|
"VK_KHR_external_semaphore_fd": 26,
|
||||||
|
"VK_KHR_external_semaphore_win32": 26,
|
||||||
|
"VK_KHR_external_fence": 26,
|
||||||
|
"VK_KHR_external_fence_fd": 26,
|
||||||
|
"VK_KHR_external_fence_win32": 26,
|
||||||
|
"VK_KHR_win32_keyed_mutex": 26,
|
||||||
|
"VK_KHR_dedicated_allocation": 26,
|
||||||
|
"VK_KHR_variable_pointers": 26,
|
||||||
|
"VK_KHR_relaxed_block_layout": 26,
|
||||||
|
"VK_KHR_bind_memory2": 26,
|
||||||
|
"VK_KHR_maintenance2": 26,
|
||||||
|
"VK_KHR_image_format_list": 26,
|
||||||
|
"VK_KHR_sampler_ycbcr_conversion": 26,
|
||||||
|
# on oreo-mr1-cts-release
|
||||||
|
"VK_KHR_draw_indirect_count": 27,
|
||||||
|
# on pie-cts-release
|
||||||
|
"VK_KHR_device_group": 28,
|
||||||
|
"VK_KHR_multiview": 28,
|
||||||
|
"VK_KHR_maintenance3": 28,
|
||||||
|
"VK_KHR_create_renderpass2": 28,
|
||||||
|
"VK_KHR_driver_properties": 28,
|
||||||
|
# on android10-tests-release
|
||||||
|
"VK_KHR_shader_float_controls": 29,
|
||||||
|
"VK_KHR_shader_float16_int8": 29,
|
||||||
|
"VK_KHR_8bit_storage": 29,
|
||||||
|
"VK_KHR_depth_stencil_resolve": 29,
|
||||||
|
"VK_KHR_swapchain_mutable_format": 29,
|
||||||
|
"VK_KHR_shader_atomic_int64": 29,
|
||||||
|
"VK_KHR_vulkan_memory_model": 29,
|
||||||
|
"VK_KHR_swapchain_mutable_format": 29,
|
||||||
|
"VK_KHR_uniform_buffer_standard_layout": 29,
|
||||||
|
# on android11-tests-release
|
||||||
|
"VK_KHR_imageless_framebuffer": 30,
|
||||||
|
"VK_KHR_shader_subgroup_extended_types": 30,
|
||||||
|
"VK_KHR_buffer_device_address": 30,
|
||||||
|
"VK_KHR_separate_depth_stencil_layouts": 30,
|
||||||
|
"VK_KHR_timeline_semaphore": 30,
|
||||||
|
"VK_KHR_spirv_1_4": 30,
|
||||||
|
"VK_KHR_pipeline_executable_properties": 30,
|
||||||
|
"VK_KHR_shader_clock": 30,
|
||||||
|
# blocked by testVulkanBlockedExtensions
|
||||||
|
# "VK_KHR_performance_query": 30,
|
||||||
|
"VK_KHR_shader_non_semantic_info": 30,
|
||||||
|
"VK_KHR_copy_commands2": 30,
|
||||||
|
# on android12-tests-release
|
||||||
|
"VK_KHR_shader_terminate_invocation": 31,
|
||||||
|
"VK_KHR_ray_tracing_pipeline": 31,
|
||||||
|
"VK_KHR_ray_query": 31,
|
||||||
|
"VK_KHR_acceleration_structure": 31,
|
||||||
|
"VK_KHR_pipeline_library": 31,
|
||||||
|
"VK_KHR_deferred_host_operations": 31,
|
||||||
|
"VK_KHR_fragment_shading_rate": 31,
|
||||||
|
"VK_KHR_zero_initialize_workgroup_memory": 31,
|
||||||
|
"VK_KHR_workgroup_memory_explicit_layout": 31,
|
||||||
|
"VK_KHR_synchronization2": 31,
|
||||||
|
"VK_KHR_shader_integer_dot_product": 31,
|
||||||
|
# on android13-tests-release
|
||||||
|
"VK_KHR_dynamic_rendering": 33,
|
||||||
|
"VK_KHR_format_feature_flags2": 33,
|
||||||
|
"VK_KHR_global_priority": 33,
|
||||||
|
"VK_KHR_maintenance4": 33,
|
||||||
|
"VK_KHR_portability_subset": 33,
|
||||||
|
"VK_KHR_present_id": 33,
|
||||||
|
"VK_KHR_present_wait": 33,
|
||||||
|
"VK_KHR_shader_subgroup_uniform_control_flow": 33,
|
||||||
|
|
||||||
|
# testNoUnknownExtensions on oreo-cts-release
|
||||||
|
"VK_GOOGLE_display_timing": 26,
|
||||||
|
# on pie-cts-release
|
||||||
|
"VK_ANDROID_external_memory_android_hardware_buffer": 28,
|
||||||
|
# on android11-tests-release
|
||||||
|
"VK_GOOGLE_decorate_string": 30,
|
||||||
|
"VK_GOOGLE_hlsl_functionality1": 30,
|
||||||
|
# on android13-tests-release
|
||||||
|
"VK_GOOGLE_surfaceless_query": 33,
|
||||||
|
|
||||||
|
# this HAL extension is always allowed and will be filtered out by the
|
||||||
|
# loader
|
||||||
|
"VK_ANDROID_native_buffer": 26,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Extensions with these prefixes are checked in Android CTS, and thus must be
|
||||||
|
# whitelisted per the preceding dict.
|
||||||
|
ANDROID_EXTENSION_WHITELIST_PREFIXES = (
|
||||||
|
"VK_KHX",
|
||||||
|
"VK_KHR",
|
||||||
|
"VK_GOOGLE",
|
||||||
|
"VK_ANDROID"
|
||||||
|
)
|
108
test3/vk_result_to_str.c
Normal file
108
test3/vk_result_to_str.c
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
// generated by util/gen_enum_to_str.py from the mesa project
|
||||||
|
const char *vk_Result_to_str(VkResult input)
|
||||||
|
{
|
||||||
|
switch ((int64_t)input) {
|
||||||
|
case -1000338000:
|
||||||
|
return "VK_ERROR_COMPRESSION_EXHAUSTED_EXT";
|
||||||
|
case -1000299000:
|
||||||
|
return "VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR";
|
||||||
|
case -1000257000:
|
||||||
|
return "VK_ERROR_INVALID_DEVICE_ADDRESS_EXT";
|
||||||
|
case -1000255000:
|
||||||
|
return "VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT";
|
||||||
|
case -1000174001:
|
||||||
|
return "VK_ERROR_NOT_PERMITTED_KHR";
|
||||||
|
case -1000161000:
|
||||||
|
return "VK_ERROR_FRAGMENTATION";
|
||||||
|
case -1000158000:
|
||||||
|
return "VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT";
|
||||||
|
case -1000072003:
|
||||||
|
return "VK_ERROR_INVALID_EXTERNAL_HANDLE";
|
||||||
|
case -1000069000:
|
||||||
|
return "VK_ERROR_OUT_OF_POOL_MEMORY";
|
||||||
|
case -1000023005:
|
||||||
|
return "VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR";
|
||||||
|
case -1000023004:
|
||||||
|
return "VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR";
|
||||||
|
case -1000023003:
|
||||||
|
return "VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR";
|
||||||
|
case -1000023002:
|
||||||
|
return "VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR";
|
||||||
|
case -1000023001:
|
||||||
|
return "VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR";
|
||||||
|
case -1000023000:
|
||||||
|
return "VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR";
|
||||||
|
case -1000012000:
|
||||||
|
return "VK_ERROR_INVALID_SHADER_NV";
|
||||||
|
case -1000011001:
|
||||||
|
return "VK_ERROR_VALIDATION_FAILED_EXT";
|
||||||
|
case -1000003001:
|
||||||
|
return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
|
||||||
|
case -1000001004:
|
||||||
|
return "VK_ERROR_OUT_OF_DATE_KHR";
|
||||||
|
case -1000000001:
|
||||||
|
return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
|
||||||
|
case -1000000000:
|
||||||
|
return "VK_ERROR_SURFACE_LOST_KHR";
|
||||||
|
case -13:
|
||||||
|
return "VK_ERROR_UNKNOWN";
|
||||||
|
case -12:
|
||||||
|
return "VK_ERROR_FRAGMENTED_POOL";
|
||||||
|
case -11:
|
||||||
|
return "VK_ERROR_FORMAT_NOT_SUPPORTED";
|
||||||
|
case -10:
|
||||||
|
return "VK_ERROR_TOO_MANY_OBJECTS";
|
||||||
|
case -9:
|
||||||
|
return "VK_ERROR_INCOMPATIBLE_DRIVER";
|
||||||
|
case -8:
|
||||||
|
return "VK_ERROR_FEATURE_NOT_PRESENT";
|
||||||
|
case -7:
|
||||||
|
return "VK_ERROR_EXTENSION_NOT_PRESENT";
|
||||||
|
case -6:
|
||||||
|
return "VK_ERROR_LAYER_NOT_PRESENT";
|
||||||
|
case -5:
|
||||||
|
return "VK_ERROR_MEMORY_MAP_FAILED";
|
||||||
|
case -4:
|
||||||
|
return "VK_ERROR_DEVICE_LOST";
|
||||||
|
case -3:
|
||||||
|
return "VK_ERROR_INITIALIZATION_FAILED";
|
||||||
|
case -2:
|
||||||
|
return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
|
||||||
|
case -1:
|
||||||
|
return "VK_ERROR_OUT_OF_HOST_MEMORY";
|
||||||
|
case 0:
|
||||||
|
return "VK_SUCCESS";
|
||||||
|
case 1:
|
||||||
|
return "VK_NOT_READY";
|
||||||
|
case 2:
|
||||||
|
return "VK_TIMEOUT";
|
||||||
|
case 3:
|
||||||
|
return "VK_EVENT_SET";
|
||||||
|
case 4:
|
||||||
|
return "VK_EVENT_RESET";
|
||||||
|
case 5:
|
||||||
|
return "VK_INCOMPLETE";
|
||||||
|
case 1000001003:
|
||||||
|
return "VK_SUBOPTIMAL_KHR";
|
||||||
|
case 1000268000:
|
||||||
|
return "VK_THREAD_IDLE_KHR";
|
||||||
|
case 1000268001:
|
||||||
|
return "VK_THREAD_DONE_KHR";
|
||||||
|
case 1000268002:
|
||||||
|
return "VK_OPERATION_DEFERRED_KHR";
|
||||||
|
case 1000268003:
|
||||||
|
return "VK_OPERATION_NOT_DEFERRED_KHR";
|
||||||
|
case 1000297000:
|
||||||
|
return "VK_PIPELINE_COMPILE_REQUIRED";
|
||||||
|
case 1000482000:
|
||||||
|
return "VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT";
|
||||||
|
case VK_RESULT_MAX_ENUM:
|
||||||
|
return "VK_RESULT_MAX_ENUM";
|
||||||
|
default:
|
||||||
|
return "Unknown VkResult value.";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user