parent
68bea8a225
commit
ee79b4c195
@ -0,0 +1,2 @@ |
|||||||
|
*.o |
||||||
|
test3 |
@ -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
|
@ -0,0 +1 @@ |
|||||||
|
Trying to implement test2 with just vulkan and in C |
@ -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; |
||||||
|
} |
@ -0,0 +1,3 @@ |
|||||||
|
__pycache__ |
||||||
|
out |
||||||
|
vk.xml |
@ -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
|
||||||
|
|
@ -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() |
@ -0,0 +1,3 @@ |
|||||||
|
#!/bin/sh |
||||||
|
|
||||||
|
gcc -msse3 -dM -E - < /dev/null | grep -E "SSE|AVX" | sort |
@ -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" |
||||||
|
) |
@ -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