Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_instance.py
4570 views
# Copyright © 2020 Hoe Hao Cheng1#2# Permission is hereby granted, free of charge, to any person obtaining a3# copy of this software and associated documentation files (the "Software"),4# to deal in the Software without restriction, including without limitation5# the rights to use, copy, modify, merge, publish, distribute, sublicense,6# and/or sell copies of the Software, and to permit persons to whom the7# Software is furnished to do so, subject to the following conditions:8#9# The above copyright notice and this permission notice (including the next10# paragraph) shall be included in all copies or substantial portions of the11# Software.12#13# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING18# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS19# IN THE SOFTWARE.20#21# Authors:22# Hoe Hao Cheng <[email protected]>23#2425from mako.template import Template26from os import path27from xml.etree import ElementTree28from zink_extensions import Extension,Layer,ExtensionRegistry,Version29import sys3031# constructor: Extension(name, conditions=[], nonstandard=False)32# The attributes:33# - conditions: If the extension is provided by the Vulkan implementation, then34# these are the extra conditions needed to enable the extension.35# - nonstandard: Disables validation (cross-checking with vk.xml) if True.36EXTENSIONS = [37Extension("VK_EXT_debug_utils"),38Extension("VK_KHR_get_physical_device_properties2"),39Extension("VK_MVK_moltenvk",40nonstandard=True),41Extension("VK_KHR_surface"),42]4344# constructor: Layer(name, conditions=[])45# - conditions: See documentation of EXTENSIONS.46LAYERS = [47# if we have debug_util, allow a validation layer to be added.48Layer("VK_LAYER_KHRONOS_validation",49conditions=["zink_debug & ZINK_DEBUG_VALIDATION"]),50Layer("VK_LAYER_LUNARG_standard_validation",51conditions=["zink_debug & ZINK_DEBUG_VALIDATION", "!have_layer_KHRONOS_validation"]),52]5354REPLACEMENTS = {55"VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES2_EXTENSION_NAME" : "VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME"56}5758header_code = """59#ifndef ZINK_INSTANCE_H60#define ZINK_INSTANCE_H6162#include "os/os_process.h"6364#include <vulkan/vulkan.h>6566#if defined(__APPLE__)67// Source of MVK_VERSION68#include "MoltenVK/vk_mvk_moltenvk.h"69#endif7071struct zink_screen;7273struct zink_instance_info {74uint32_t loader_version;7576%for ext in extensions:77bool have_${ext.name_with_vendor()};78%endfor7980%for layer in layers:81bool have_layer_${layer.pure_name()};82%endfor83};8485VkInstance86zink_create_instance(struct zink_instance_info *instance_info);8788void89zink_verify_instance_extensions(struct zink_screen *screen);9091/* stub functions that get inserted into the dispatch table if they are not92* properly loaded.93*/94%for ext in extensions:95%if registry.in_registry(ext.name):96%for cmd in registry.get_registry_entry(ext.name).instance_commands:97void zink_stub_${cmd.lstrip("vk")}(void);98%endfor99%for cmd in registry.get_registry_entry(ext.name).pdevice_commands:100void zink_stub_${cmd.lstrip("vk")}(void);101%endfor102%endif103%endfor104105#endif106"""107108impl_code = """109#include "zink_instance.h"110#include "zink_screen.h"111112VkInstance113zink_create_instance(struct zink_instance_info *instance_info)114{115/* reserve one slot for MoltenVK */116const char *layers[${len(layers) + 1}] = {0};117uint32_t num_layers = 0;118119const char *extensions[${len(extensions) + 1}] = {0};120uint32_t num_extensions = 0;121122%for ext in extensions:123bool have_${ext.name_with_vendor()} = false;124%endfor125126%for layer in layers:127bool have_layer_${layer.pure_name()} = false;128%endfor129130#if defined(MVK_VERSION)131bool have_moltenvk_layer = false;132#endif133134// Build up the extensions from the reported ones but only for the unnamed layer135uint32_t extension_count = 0;136if (vkEnumerateInstanceExtensionProperties(NULL, &extension_count, NULL) == VK_SUCCESS) {137VkExtensionProperties *extension_props = malloc(extension_count * sizeof(VkExtensionProperties));138if (extension_props) {139if (vkEnumerateInstanceExtensionProperties(NULL, &extension_count, extension_props) == VK_SUCCESS) {140for (uint32_t i = 0; i < extension_count; i++) {141%for ext in extensions:142if (!strcmp(extension_props[i].extensionName, ${ext.extension_name_literal()})) {143have_${ext.name_with_vendor()} = true;144}145%endfor146}147}148free(extension_props);149}150}151152// Build up the layers from the reported ones153uint32_t layer_count = 0;154155if (vkEnumerateInstanceLayerProperties(&layer_count, NULL) == VK_SUCCESS) {156VkLayerProperties *layer_props = malloc(layer_count * sizeof(VkLayerProperties));157if (layer_props) {158if (vkEnumerateInstanceLayerProperties(&layer_count, layer_props) == VK_SUCCESS) {159for (uint32_t i = 0; i < layer_count; i++) {160%for layer in layers:161if (!strcmp(layer_props[i].layerName, ${layer.extension_name_literal()})) {162have_layer_${layer.pure_name()} = true;163}164%endfor165#if defined(MVK_VERSION)166if (!strcmp(layer_props[i].layerName, "MoltenVK")) {167have_moltenvk_layer = true;168layers[num_layers++] = "MoltenVK";169}170#endif171}172}173free(layer_props);174}175}176177%for ext in extensions:178<%179conditions = ""180if ext.enable_conds:181for cond in ext.enable_conds:182conditions += "&& (" + cond + ") "183conditions = conditions.strip()184%>\185if (have_${ext.name_with_vendor()} ${conditions}) {186instance_info->have_${ext.name_with_vendor()} = have_${ext.name_with_vendor()};187extensions[num_extensions++] = ${ext.extension_name_literal()};188}189%endfor190191%for layer in layers:192<%193conditions = ""194if layer.enable_conds:195for cond in layer.enable_conds:196conditions += "&& (" + cond + ") "197conditions = conditions.strip()198%>\199if (have_layer_${layer.pure_name()} ${conditions}) {200layers[num_layers++] = ${layer.extension_name_literal()};201instance_info->have_layer_${layer.pure_name()} = true;202}203%endfor204205VkApplicationInfo ai = {0};206ai.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;207208char proc_name[128];209if (os_get_process_name(proc_name, ARRAY_SIZE(proc_name)))210ai.pApplicationName = proc_name;211else212ai.pApplicationName = "unknown";213214ai.pEngineName = "mesa zink";215ai.apiVersion = instance_info->loader_version;216217VkInstanceCreateInfo ici = {0};218ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;219ici.pApplicationInfo = &ai;220ici.ppEnabledExtensionNames = extensions;221ici.enabledExtensionCount = num_extensions;222ici.ppEnabledLayerNames = layers;223ici.enabledLayerCount = num_layers;224225VkInstance instance = VK_NULL_HANDLE;226VkResult err = vkCreateInstance(&ici, NULL, &instance);227if (err != VK_SUCCESS)228return VK_NULL_HANDLE;229230return instance;231}232233void234zink_verify_instance_extensions(struct zink_screen *screen)235{236%for ext in extensions:237%if registry.in_registry(ext.name):238if (screen->instance_info.have_${ext.name_with_vendor()}) {239%for cmd in registry.get_registry_entry(ext.name).instance_commands:240if (!screen->vk.${cmd.lstrip("vk")}) {241#ifndef NDEBUG242screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_${cmd.lstrip("vk")};243#else244screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_function_not_loaded;245#endif246}247%endfor248%for cmd in registry.get_registry_entry(ext.name).pdevice_commands:249if (!screen->vk.${cmd.lstrip("vk")}) {250#ifndef NDEBUG251screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_${cmd.lstrip("vk")};252#else253screen->vk.${cmd.lstrip("vk")} = (PFN_${cmd})zink_stub_function_not_loaded;254#endif255}256%endfor257}258%endif259%endfor260}261262#ifndef NDEBUG263/* generated stub functions */264## see zink_device_info.py for why this is needed265<% generated_funcs = set() %>266267%for ext in extensions:268%if registry.in_registry(ext.name):269%for cmd in registry.get_registry_entry(ext.name).instance_commands + registry.get_registry_entry(ext.name).pdevice_commands:270%if cmd in generated_funcs:271<% continue %>272%else:273<% generated_funcs.add(cmd) %>274%endif275void276zink_stub_${cmd.lstrip("vk")}()277{278mesa_loge("ZINK: ${cmd} is not loaded properly!");279abort();280}281%endfor282%endif283%endfor284285#endif286"""287288289def replace_code(code: str, replacement: dict):290for (k, v) in replacement.items():291code = code.replace(k, v)292293return code294295296if __name__ == "__main__":297try:298header_path = sys.argv[1]299impl_path = sys.argv[2]300vkxml_path = sys.argv[3]301302header_path = path.abspath(header_path)303impl_path = path.abspath(impl_path)304vkxml_path = path.abspath(vkxml_path)305except:306print("usage: %s <path to .h> <path to .c> <path to vk.xml>" % sys.argv[0])307exit(1)308309registry = ExtensionRegistry(vkxml_path)310311extensions = EXTENSIONS312layers = LAYERS313replacement = REPLACEMENTS314315# Perform extension validation and set core_since for the extension if available316error_count = 0317for ext in extensions:318if not registry.in_registry(ext.name):319# disable validation for nonstandard extensions320if ext.is_nonstandard:321continue322323error_count += 1324print("The extension {} is not registered in vk.xml - a typo?".format(ext.name))325continue326327entry = registry.get_registry_entry(ext.name)328329if entry.ext_type != "instance":330error_count += 1331print("The extension {} is {} extension - expected an instance extension.".format(ext.name, entry.ext_type))332continue333334if entry.promoted_in:335ext.core_since = Version((*entry.promoted_in, 0))336337if error_count > 0:338print("zink_instance.py: Found {} error(s) in total. Quitting.".format(error_count))339exit(1)340341with open(header_path, "w") as header_file:342header = Template(header_code).render(extensions=extensions, layers=layers, registry=registry).strip()343header = replace_code(header, replacement)344print(header, file=header_file)345346with open(impl_path, "w") as impl_file:347impl = Template(impl_code).render(extensions=extensions, layers=layers, registry=registry).strip()348impl = replace_code(impl, replacement)349print(impl, file=impl_file)350351352