2020-09-19 04:39:19 +08:00
|
|
|
# Copyright © 2020 Hoe Hao Cheng
|
|
|
|
#
|
|
|
|
# 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 (including the next
|
|
|
|
# paragraph) 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.
|
|
|
|
#
|
|
|
|
# Authors:
|
|
|
|
# Hoe Hao Cheng <haochengho12907@gmail.com>
|
|
|
|
#
|
|
|
|
|
|
|
|
from mako.template import Template
|
2020-11-25 01:01:52 +08:00
|
|
|
from mako.lookup import TemplateLookup
|
2020-09-19 04:39:19 +08:00
|
|
|
from os import path
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
|
2020-11-05 11:00:01 +00:00
|
|
|
# constructor: Extensions(name, alias="", required=False, properties=False, features=False, have_feature=None, guard=False)
|
2020-09-19 04:39:19 +08:00
|
|
|
# The attributes:
|
|
|
|
# - required: the generated code debug_prints "ZINK: {name} required!" and
|
|
|
|
# returns NULL if the extension is unavailable.
|
|
|
|
#
|
|
|
|
# - properties: enable the detection of extension properties in a physical
|
|
|
|
# device in the generated code using vkGetPhysicalDeviceProperties2(),
|
|
|
|
# and store the returned properties struct inside
|
|
|
|
# `zink_device_info.{alias}_props`.
|
|
|
|
# Example: the properties for `VK_EXT_transform_feedback`, is stored in
|
|
|
|
# `VkPhysicalDeviceTransformFeedbackPropertiesEXT tf_props`.
|
|
|
|
#
|
2020-11-05 11:00:01 +00:00
|
|
|
# - have_feature: enable the fine-grained detection of extension features in a
|
2020-09-19 04:39:19 +08:00
|
|
|
# device. Similar to `properties`, this stores the features
|
|
|
|
# struct inside `zink_device_info.{alias}_feats`.
|
|
|
|
# It sets `zink_device_info.have_{name} = true` only if
|
2020-11-05 11:00:01 +00:00
|
|
|
# `{alias}_feats.{has_feature}` is true.
|
|
|
|
# If have_feature is None, `have_{extension_name}` is true when the extensions
|
2020-09-19 04:39:19 +08:00
|
|
|
# given by vkEnumerateDeviceExtensionProperties() include the extension.
|
|
|
|
# Furthermore, `zink_device_info.{extension_alias}_feats` is unavailable.
|
2020-11-05 11:00:01 +00:00
|
|
|
#
|
|
|
|
# - features: enable the getting extension features in a
|
|
|
|
# device. Similar to `have_feature`, this stores the features
|
|
|
|
# struct inside `zink_device_info.{alias}_feats`.
|
|
|
|
# Unlike `have_feature` it does not create a `have_` member.
|
|
|
|
#
|
|
|
|
# - guard: adds a #if defined(`extension_name`)/#endif guard around the code generated for this Extension.
|
2020-09-19 04:39:19 +08:00
|
|
|
def EXTENSIONS():
|
|
|
|
return [
|
|
|
|
Extension("VK_KHR_maintenance1", required=True),
|
2020-12-02 17:21:12 +01:00
|
|
|
Extension("VK_KHR_external_memory"),
|
2020-09-19 04:39:19 +08:00
|
|
|
Extension("VK_KHR_external_memory_fd"),
|
2020-07-17 09:52:16 -04:00
|
|
|
Extension("VK_KHR_vulkan_memory_model"),
|
2020-11-05 11:00:01 +00:00
|
|
|
Extension("VK_EXT_conditional_rendering", alias="cond_render", have_feature="conditionalRendering"),
|
|
|
|
Extension("VK_EXT_transform_feedback", alias="tf", properties=True, have_feature="transformFeedback"),
|
|
|
|
Extension("VK_EXT_index_type_uint8", alias="index_uint8", have_feature="indexTypeUint8"),
|
|
|
|
Extension("VK_EXT_robustness2", alias="rb2", properties=True, have_feature="nullDescriptor"),
|
|
|
|
Extension("VK_EXT_vertex_attribute_divisor", alias="vdiv", properties=True, have_feature="vertexAttributeInstanceRateDivisor"),
|
2020-09-19 04:39:19 +08:00
|
|
|
Extension("VK_EXT_calibrated_timestamps"),
|
2020-11-05 11:00:01 +00:00
|
|
|
Extension("VK_EXT_custom_border_color", alias="border_color", properties=True, have_feature="customBorderColors"),
|
2020-08-21 08:37:13 -04:00
|
|
|
Extension("VK_EXT_blend_operation_advanced", alias="blend", properties=True),
|
2020-11-05 11:00:01 +00:00
|
|
|
Extension("VK_EXT_extended_dynamic_state", alias="dynamic_state", have_feature="extendedDynamicState"),
|
|
|
|
Extension("VK_EXT_pipeline_creation_cache_control", alias="pipeline_cache_control", have_feature="pipelineCreationCacheControl"),
|
2020-10-10 10:53:46 -04:00
|
|
|
Extension("VK_EXT_shader_stencil_export", alias="stencil_export"),
|
2020-11-05 11:17:40 +00:00
|
|
|
Extension("VK_EXTX_portability_subset", alias="portability_subset_extx", properties=True, features=True, guard=True),
|
2020-09-19 04:39:19 +08:00
|
|
|
]
|
|
|
|
|
2020-11-08 12:11:12 +00:00
|
|
|
# constructor: Versions(device_version(major, minor, patch), struct_version(major, minor))
|
|
|
|
# The attributes:
|
|
|
|
# - device_version: Vulkan version, as tuple, to use with VK_MAKE_VERSION(version_major, version_minor, version_patch)
|
|
|
|
#
|
|
|
|
# - struct_version: Vulkan version, as tuple, to use with structures and macros
|
|
|
|
def VERSIONS():
|
|
|
|
return [
|
|
|
|
# VkPhysicalDeviceVulkan11Properties and VkPhysicalDeviceVulkan11Features is new from Vk 1.2, not Vk 1.1
|
|
|
|
# https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/vkspec.html#_new_structures
|
|
|
|
Version((1,2,0), (1,1)),
|
|
|
|
Version((1,2,0), (1,2)),
|
|
|
|
]
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
# There exists some inconsistencies regarding the enum constants, fix them.
|
|
|
|
# This is basically generated_code.replace(key, value).
|
|
|
|
def REPLACEMENTS():
|
|
|
|
return {
|
|
|
|
"ROBUSTNESS2": "ROBUSTNESS_2"
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-25 01:01:52 +08:00
|
|
|
# This template provides helper functions for the other templates.
|
|
|
|
# Right now, the following functions are defined:
|
|
|
|
# - guard(ext) : surrounds the body with an if-def guard according to
|
|
|
|
# `ext.extension_name()` if `ext.guard` is True.
|
|
|
|
include_template = """
|
|
|
|
<%def name="guard_(ext, body)">
|
|
|
|
%if ext.guard:
|
|
|
|
#ifdef ${ext.extension_name()}
|
|
|
|
%endif
|
|
|
|
${capture(body)|trim}
|
|
|
|
%if ext.guard:
|
|
|
|
#endif
|
|
|
|
%endif
|
|
|
|
</%def>
|
|
|
|
|
|
|
|
## This ugliness is here to prevent mako from adding tons of excessive whitespace
|
|
|
|
<%def name="guard(ext)">${capture(guard_, ext, body=caller.body).strip('\\r\\n')}</%def>
|
|
|
|
"""
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
header_code = """
|
2020-11-25 01:01:52 +08:00
|
|
|
<%namespace name="helpers" file="helpers"/>
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
#ifndef ZINK_DEVICE_INFO_H
|
|
|
|
#define ZINK_DEVICE_INFO_H
|
|
|
|
|
|
|
|
#include "util/u_memory.h"
|
|
|
|
|
|
|
|
#include <vulkan/vulkan.h>
|
|
|
|
|
2020-11-05 11:17:40 +00:00
|
|
|
#if defined(__APPLE__)
|
|
|
|
// Source of MVK_VERSION
|
|
|
|
// Source of VK_EXTX_PORTABILITY_SUBSET_EXTENSION_NAME
|
|
|
|
#include "MoltenVK/vk_mvk_moltenvk.h"
|
|
|
|
#endif
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
struct zink_screen;
|
|
|
|
|
|
|
|
struct zink_device_info {
|
2020-11-08 12:11:12 +00:00
|
|
|
uint32_t device_version;
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
%for ext in extensions:
|
2020-11-25 01:01:52 +08:00
|
|
|
<%helpers:guard ext="${ext}">
|
2020-09-19 04:39:19 +08:00
|
|
|
bool have_${ext.name_with_vendor()};
|
2020-11-25 01:01:52 +08:00
|
|
|
</%helpers:guard>
|
2020-09-19 04:39:19 +08:00
|
|
|
%endfor
|
2020-11-08 12:11:12 +00:00
|
|
|
%for version in versions:
|
|
|
|
bool have_vulkan${version.struct()};
|
|
|
|
%endfor
|
2020-09-19 04:39:19 +08:00
|
|
|
|
|
|
|
VkPhysicalDeviceFeatures2 feats;
|
2020-11-08 12:11:12 +00:00
|
|
|
%for version in versions:
|
|
|
|
VkPhysicalDeviceVulkan${version.struct()}Features feats${version.struct()};
|
|
|
|
%endfor
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
VkPhysicalDeviceProperties props;
|
2020-11-08 12:11:12 +00:00
|
|
|
%for version in versions:
|
|
|
|
VkPhysicalDeviceVulkan${version.struct()}Properties props${version.struct()};
|
|
|
|
%endfor
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
VkPhysicalDeviceMemoryProperties mem_props;
|
|
|
|
|
|
|
|
%for ext in extensions:
|
2020-11-25 01:01:52 +08:00
|
|
|
<%helpers:guard ext="${ext}">
|
2020-11-05 11:00:01 +00:00
|
|
|
%if ext.feature_field is not None or ext.has_features:
|
2020-09-19 04:39:19 +08:00
|
|
|
VkPhysicalDevice${ext.name_in_camel_case()}Features${ext.vendor()} ${ext.field("feats")};
|
|
|
|
%endif
|
|
|
|
%if ext.has_properties:
|
|
|
|
VkPhysicalDevice${ext.name_in_camel_case()}Properties${ext.vendor()} ${ext.field("props")};
|
|
|
|
%endif
|
2020-11-25 01:01:52 +08:00
|
|
|
</%helpers:guard>
|
2020-09-19 04:39:19 +08:00
|
|
|
%endfor
|
|
|
|
|
|
|
|
const char *extensions[${len(extensions)}];
|
|
|
|
uint32_t num_extensions;
|
|
|
|
};
|
|
|
|
|
|
|
|
bool
|
|
|
|
zink_get_physical_device_info(struct zink_screen *screen);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
impl_code = """
|
2020-11-25 01:01:52 +08:00
|
|
|
<%namespace name="helpers" file="helpers"/>
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
#include "zink_device_info.h"
|
|
|
|
#include "zink_screen.h"
|
|
|
|
|
|
|
|
bool
|
|
|
|
zink_get_physical_device_info(struct zink_screen *screen)
|
|
|
|
{
|
|
|
|
struct zink_device_info *info = &screen->info;
|
|
|
|
%for ext in extensions:
|
2020-11-25 01:01:52 +08:00
|
|
|
<%helpers:guard ext="${ext}">
|
2020-09-19 04:39:19 +08:00
|
|
|
bool support_${ext.name_with_vendor()} = false;
|
2020-11-25 01:01:52 +08:00
|
|
|
</%helpers:guard>
|
2020-09-19 04:39:19 +08:00
|
|
|
%endfor
|
|
|
|
uint32_t num_extensions = 0;
|
|
|
|
|
2020-11-08 12:11:12 +00:00
|
|
|
// get device API support
|
|
|
|
vkGetPhysicalDeviceProperties(screen->pdev, &info->props);
|
|
|
|
info->device_version = info->props.apiVersion;
|
|
|
|
|
|
|
|
// get device memory properties
|
2020-09-19 04:39:19 +08:00
|
|
|
vkGetPhysicalDeviceMemoryProperties(screen->pdev, &info->mem_props);
|
|
|
|
|
|
|
|
// enumerate device supported extensions
|
|
|
|
if (vkEnumerateDeviceExtensionProperties(screen->pdev, NULL, &num_extensions, NULL) == VK_SUCCESS) {
|
|
|
|
if (num_extensions > 0) {
|
|
|
|
VkExtensionProperties *extensions = MALLOC(sizeof(VkExtensionProperties) * num_extensions);
|
|
|
|
if (!extensions) goto fail;
|
|
|
|
vkEnumerateDeviceExtensionProperties(screen->pdev, NULL, &num_extensions, extensions);
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < num_extensions; ++i) {
|
|
|
|
%for ext in extensions:
|
2020-11-25 01:01:52 +08:00
|
|
|
<%helpers:guard ext="${ext}">
|
2020-09-19 04:39:19 +08:00
|
|
|
if (!strcmp(extensions[i].extensionName, "${ext.name}")) {
|
|
|
|
support_${ext.name_with_vendor()} = true;
|
|
|
|
}
|
2020-11-25 01:01:52 +08:00
|
|
|
</%helpers:guard>
|
2020-09-19 04:39:19 +08:00
|
|
|
%endfor
|
|
|
|
}
|
|
|
|
|
|
|
|
FREE(extensions);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-08 12:11:12 +00:00
|
|
|
// get device features
|
2020-12-07 08:25:13 +00:00
|
|
|
if (screen->vk_GetPhysicalDeviceFeatures2) {
|
2020-11-04 17:42:29 +00:00
|
|
|
// check for device extension features
|
|
|
|
info->feats.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
2020-09-19 04:39:19 +08:00
|
|
|
|
2020-11-08 12:11:12 +00:00
|
|
|
%for version in versions:
|
|
|
|
if (${version.version()} <= info->device_version) {
|
|
|
|
info->feats${version.struct()}.sType = ${version.stype("FEATURES")};
|
|
|
|
info->feats${version.struct()}.pNext = info->feats.pNext;
|
|
|
|
info->feats.pNext = &info->feats${version.struct()};
|
|
|
|
info->have_vulkan${version.struct()} = true;
|
|
|
|
}
|
|
|
|
%endfor
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
%for ext in extensions:
|
2020-11-05 11:00:01 +00:00
|
|
|
%if ext.feature_field is not None or ext.has_features:
|
2020-11-25 01:01:52 +08:00
|
|
|
<%helpers:guard ext="${ext}">
|
2020-11-04 17:42:29 +00:00
|
|
|
if (support_${ext.name_with_vendor()}) {
|
|
|
|
info->${ext.field("feats")}.sType = ${ext.stype("FEATURES")};
|
|
|
|
info->${ext.field("feats")}.pNext = info->feats.pNext;
|
|
|
|
info->feats.pNext = &info->${ext.field("feats")};
|
|
|
|
}
|
2020-11-25 01:01:52 +08:00
|
|
|
</%helpers:guard>
|
2020-09-19 04:39:19 +08:00
|
|
|
%endif
|
|
|
|
%endfor
|
|
|
|
|
2020-11-04 17:42:29 +00:00
|
|
|
screen->vk_GetPhysicalDeviceFeatures2(screen->pdev, &info->feats);
|
2020-09-19 04:39:19 +08:00
|
|
|
|
|
|
|
%for ext in extensions:
|
2020-11-25 01:01:52 +08:00
|
|
|
<%helpers:guard ext="${ext}">
|
2020-11-08 12:11:12 +00:00
|
|
|
%if ext.feature_field is not None:
|
2020-11-04 17:42:29 +00:00
|
|
|
if (support_${ext.name_with_vendor()} && info->${ext.field("feats")}.${ext.feature_field}) {
|
|
|
|
info->have_${ext.name_with_vendor()} = true;
|
|
|
|
}
|
2020-09-19 04:39:19 +08:00
|
|
|
%endif
|
2020-11-25 01:01:52 +08:00
|
|
|
</%helpers:guard>
|
2020-09-19 04:39:19 +08:00
|
|
|
%endfor
|
2020-11-04 17:42:29 +00:00
|
|
|
} else {
|
|
|
|
vkGetPhysicalDeviceFeatures(screen->pdev, &info->feats.features);
|
2020-11-08 12:11:12 +00:00
|
|
|
}
|
2020-11-04 17:42:29 +00:00
|
|
|
|
|
|
|
%for ext in extensions:
|
2020-11-25 01:01:52 +08:00
|
|
|
<%helpers:guard ext="${ext}">
|
2020-11-04 17:42:29 +00:00
|
|
|
%if ext.feature_field is None:
|
2020-11-08 12:11:12 +00:00
|
|
|
info->have_${ext.name_with_vendor()} = support_${ext.name_with_vendor()};
|
2020-11-04 17:42:29 +00:00
|
|
|
%endif
|
2020-11-25 01:01:52 +08:00
|
|
|
</%helpers:guard>
|
2020-11-04 17:42:29 +00:00
|
|
|
%endfor
|
2020-09-19 04:39:19 +08:00
|
|
|
|
|
|
|
// check for device properties
|
2020-12-07 08:25:13 +00:00
|
|
|
if (screen->vk_GetPhysicalDeviceProperties2) {
|
2020-11-04 17:42:29 +00:00
|
|
|
VkPhysicalDeviceProperties2 props = {};
|
|
|
|
props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
2020-09-19 04:39:19 +08:00
|
|
|
|
2020-11-08 12:11:12 +00:00
|
|
|
%for version in versions:
|
|
|
|
if (${version.version()} <= info->device_version) {
|
|
|
|
info->props${version.struct()}.sType = ${version.stype("PROPERTIES")};
|
|
|
|
info->props${version.struct()}.pNext = props.pNext;
|
|
|
|
props.pNext = &info->props${version.struct()};
|
|
|
|
}
|
|
|
|
%endfor
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
%for ext in extensions:
|
|
|
|
%if ext.has_properties:
|
2020-11-25 01:01:52 +08:00
|
|
|
<%helpers:guard ext="${ext}">
|
2020-11-04 17:42:29 +00:00
|
|
|
if (info->have_${ext.name_with_vendor()}) {
|
|
|
|
info->${ext.field("props")}.sType = ${ext.stype("PROPERTIES")};
|
|
|
|
info->${ext.field("props")}.pNext = props.pNext;
|
|
|
|
props.pNext = &info->${ext.field("props")};
|
|
|
|
}
|
2020-11-25 01:01:52 +08:00
|
|
|
</%helpers:guard>
|
2020-09-19 04:39:19 +08:00
|
|
|
%endif
|
|
|
|
%endfor
|
|
|
|
|
2020-11-08 12:11:12 +00:00
|
|
|
// note: setting up local VkPhysicalDeviceProperties2.
|
2020-11-04 17:42:29 +00:00
|
|
|
screen->vk_GetPhysicalDeviceProperties2(screen->pdev, &props);
|
|
|
|
}
|
2020-09-19 04:39:19 +08:00
|
|
|
|
|
|
|
// generate extension list
|
|
|
|
num_extensions = 0;
|
|
|
|
|
|
|
|
%for ext in extensions:
|
2020-11-25 01:01:52 +08:00
|
|
|
<%helpers:guard ext="${ext}">
|
2020-09-19 04:39:19 +08:00
|
|
|
if (info->have_${ext.name_with_vendor()}) {
|
|
|
|
info->extensions[num_extensions++] = "${ext.name}";
|
|
|
|
%if ext.is_required:
|
|
|
|
} else {
|
|
|
|
debug_printf("ZINK: ${ext.name} required!\\n");
|
|
|
|
goto fail;
|
|
|
|
%endif
|
|
|
|
}
|
2020-11-25 01:01:52 +08:00
|
|
|
</%helpers:guard>
|
2020-09-19 04:39:19 +08:00
|
|
|
%endfor
|
|
|
|
|
|
|
|
info->num_extensions = num_extensions;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
"""
|
|
|
|
|
2020-11-08 12:11:12 +00:00
|
|
|
class Version:
|
|
|
|
driver_version : (1,0,0)
|
|
|
|
struct_version : (1,0)
|
|
|
|
|
|
|
|
def __init__(self, version, struct):
|
|
|
|
self.device_version = version
|
|
|
|
self.struct_version = struct
|
|
|
|
|
|
|
|
# e.g. "VM_MAKE_VERSION(1,2,0)"
|
|
|
|
def version(self):
|
|
|
|
return ("VK_MAKE_VERSION("
|
|
|
|
+ str(self.device_version[0])
|
|
|
|
+ ","
|
|
|
|
+ str(self.device_version[1])
|
|
|
|
+ ","
|
|
|
|
+ str(self.device_version[2])
|
|
|
|
+ ")")
|
|
|
|
|
|
|
|
# e.g. "10"
|
|
|
|
def struct(self):
|
|
|
|
return (str(self.struct_version[0])+str(self.struct_version[1]))
|
|
|
|
|
|
|
|
# the sType of the extension's struct
|
|
|
|
# e.g. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT
|
|
|
|
# for VK_EXT_transform_feedback and struct="FEATURES"
|
|
|
|
def stype(self, struct: str):
|
|
|
|
return ("VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_"
|
|
|
|
+ str(self.struct_version[0]) + "_" + str(self.struct_version[1])
|
|
|
|
+ '_' + struct)
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
class Extension:
|
|
|
|
name : str = None
|
|
|
|
alias : str = None
|
|
|
|
is_required : bool = False
|
|
|
|
has_properties : bool = False
|
2020-11-05 11:00:01 +00:00
|
|
|
has_features : bool = False
|
|
|
|
feature_field : str = None
|
|
|
|
guard : bool = False
|
2020-09-19 04:39:19 +08:00
|
|
|
|
2020-11-05 11:00:01 +00:00
|
|
|
def __init__(self, name, alias="", required=False, properties=False, features=False, have_feature=None, guard=False):
|
2020-09-19 04:39:19 +08:00
|
|
|
self.name = name
|
|
|
|
self.alias = alias
|
|
|
|
self.is_required = required
|
|
|
|
self.has_properties = properties
|
2020-11-05 11:00:01 +00:00
|
|
|
self.has_features = features
|
|
|
|
self.feature_field = have_feature
|
|
|
|
self.guard = guard
|
2020-09-19 04:39:19 +08:00
|
|
|
|
2020-11-05 11:00:01 +00:00
|
|
|
if alias == "" and (properties == True or have_feature is not None):
|
2020-09-19 04:39:19 +08:00
|
|
|
raise RuntimeError("alias must be available when properties/feature is used")
|
|
|
|
|
|
|
|
# e.g.: "VK_EXT_robustness2" -> "robustness2"
|
|
|
|
def pure_name(self):
|
|
|
|
return '_'.join(self.name.split('_')[2:])
|
|
|
|
|
|
|
|
# e.g.: "VK_EXT_robustness2" -> "EXT_robustness2"
|
|
|
|
def name_with_vendor(self):
|
|
|
|
return self.name[3:]
|
|
|
|
|
|
|
|
# e.g.: "VK_EXT_robustness2" -> "Robustness2"
|
|
|
|
def name_in_camel_case(self):
|
|
|
|
return "".join([x.title() for x in self.name.split('_')[2:]])
|
|
|
|
|
|
|
|
# e.g.: "VK_EXT_robustness2" -> "VK_EXT_ROBUSTNESS2_EXTENSION_NAME"
|
|
|
|
# do note that inconsistencies exist, i.e. we have
|
|
|
|
# VK_EXT_ROBUSTNESS_2_EXTENSION_NAME defined in the headers, but then
|
|
|
|
# we also have VK_KHR_MAINTENANCE1_EXTENSION_NAME
|
|
|
|
def extension_name(self):
|
|
|
|
return self.name.upper() + "_EXTENSION_NAME"
|
|
|
|
|
|
|
|
# generate a C string literal for the extension
|
|
|
|
def extension_name_literal(self):
|
|
|
|
return '"' + self.name + '"'
|
|
|
|
|
|
|
|
# get the field in zink_device_info that refers to the extension's
|
|
|
|
# feature/properties struct
|
|
|
|
# e.g. rb2_<suffix> for VK_EXT_robustness2
|
|
|
|
def field(self, suffix: str):
|
|
|
|
return self.alias + '_' + suffix
|
|
|
|
|
|
|
|
# the sType of the extension's struct
|
|
|
|
# e.g. VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT
|
|
|
|
# for VK_EXT_transform_feedback and struct="FEATURES"
|
|
|
|
def stype(self, struct: str):
|
|
|
|
return ("VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_"
|
|
|
|
+ self.pure_name().upper()
|
|
|
|
+ '_' + struct + '_'
|
|
|
|
+ self.vendor())
|
|
|
|
|
|
|
|
# e.g. EXT in VK_EXT_robustness2
|
|
|
|
def vendor(self):
|
|
|
|
return self.name.split('_')[1]
|
|
|
|
|
|
|
|
|
|
|
|
def replace_code(code: str, replacement: dict):
|
|
|
|
for (k, v) in replacement.items():
|
|
|
|
code = code.replace(k, v)
|
|
|
|
|
|
|
|
return code
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
try:
|
|
|
|
header_path = sys.argv[1]
|
|
|
|
impl_path = sys.argv[2]
|
|
|
|
|
|
|
|
header_path = path.abspath(header_path)
|
|
|
|
impl_path = path.abspath(impl_path)
|
|
|
|
except:
|
|
|
|
print("usage: %s <path to .h> <path to .c>" % sys.argv[0])
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
extensions = EXTENSIONS()
|
2020-11-08 12:11:12 +00:00
|
|
|
versions = VERSIONS()
|
2020-09-19 04:39:19 +08:00
|
|
|
replacement = REPLACEMENTS()
|
|
|
|
|
2020-11-25 01:01:52 +08:00
|
|
|
lookup = TemplateLookup()
|
|
|
|
lookup.put_string("helpers", include_template)
|
|
|
|
|
2020-09-19 04:39:19 +08:00
|
|
|
with open(header_path, "w") as header_file:
|
2020-11-25 01:01:52 +08:00
|
|
|
header = Template(header_code, lookup=lookup).render(extensions=extensions, versions=versions).strip()
|
2020-09-19 04:39:19 +08:00
|
|
|
header = replace_code(header, replacement)
|
|
|
|
print(header, file=header_file)
|
|
|
|
|
|
|
|
with open(impl_path, "w") as impl_file:
|
2020-11-25 01:01:52 +08:00
|
|
|
impl = Template(impl_code, lookup=lookup).render(extensions=extensions, versions=versions).strip()
|
2020-09-19 04:39:19 +08:00
|
|
|
impl = replace_code(impl, replacement)
|
|
|
|
print(impl, file=impl_file)
|