Commit e5034f0d authored by Alejandro Piñeiro's avatar Alejandro Piñeiro Committed by Marge Bot
Browse files

v3dv: add v3d vulkan driver skeleton



Initial commit, mostly a import of the minimum from anv/radv to get a
skeleton to start to work with.

In includes:
 * meson files
 * Copy & adapt entrypoints ane extensions scripts from anv (that were
   later used on radv)

This is a firt approach, but is is likely that we can remove/simplify
some things.

v2: fix copyright character at broadcom/vulkan/meson.build (Eric)
v3: no spaces inside arrays (Dylan)
v4: add gnu_symbol_visibility (detected by CI on first Merge attemp)
Reviewed-by: Emma Anholt's avatarEric Anholt <eric@anholt.net>

squash! v3dv: add v3d vulkan driver skeleton

Part-of: <mesa/mesa!6766>
parent bdb1e5aa
......@@ -273,6 +273,7 @@ with_amd_vk = _vulkan_drivers.contains('amd')
with_freedreno_vk = _vulkan_drivers.contains('freedreno')
with_swrast_vk = _vulkan_drivers.contains('swrast')
with_freedreno_kgsl = get_option('freedreno-kgsl')
with_broadcom_vk = _vulkan_drivers.contains('broadcom')
with_any_vk = _vulkan_drivers.length() != 0
if with_swrast_vk and not with_gallium_softpipe
......
......@@ -173,7 +173,7 @@ option(
'vulkan-drivers',
type : 'array',
value : ['auto'],
choices : ['auto', 'amd', 'freedreno', 'intel', 'swrast'],
choices : ['auto', 'amd', 'broadcom', 'freedreno', 'intel', 'swrast'],
description : 'List of vulkan drivers to build. If this is set to auto all drivers applicable to the target OS/architecture will be built'
)
option(
......
......@@ -25,7 +25,7 @@ subdir('cle')
v3d_versions = ['33', '41', '42']
v3d_libs = []
if with_gallium_v3d
if with_gallium_v3d or with_broadcom_vk
subdir('compiler')
subdir('qpu')
subdir('simulator')
......@@ -63,3 +63,7 @@ libbroadcom_v3d = static_library(
build_by_default : false,
dependencies: [dep_valgrind, dep_thread],
)
if with_broadcom_vk
subdir('vulkan')
endif
((prog-mode
(indent-tabs-mode . nil)
(tab-width . 8)
(c-basic-offset . 3)
(c-file-style . "k&r")
(fill-column . 78)
)
)
[*.{c,h}]
indent_style = space
indent_size = 3
# Copyright © 2019 Raspberry Pi
#
# 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.
v3dv_entrypoints = custom_target(
'v3dv_entrypoints.[ch]',
input : ['v3dv_entrypoints_gen.py', vk_api_xml],
output : ['v3dv_entrypoints.h', 'v3dv_entrypoints.c'],
command : [
prog_python, '@INPUT0@', '--xml', '@INPUT1@', '--outdir',
meson.current_build_dir()
],
depend_files : files('v3dv_extensions.py'),
)
v3dv_extensions_c = custom_target(
'v3dv_extensions.c',
input : ['v3dv_extensions_gen.py', vk_api_xml],
output : 'v3dv_extensions.c',
command : [
prog_python, '@INPUT0@', '--xml', '@INPUT1@',
'--out-c', '@OUTPUT@',
],
depend_files : files('v3dv_extensions.py'),
)
v3dv_extensions_h = custom_target(
'v3dv_extensions.h',
input : ['v3dv_extensions_gen.py', vk_api_xml],
output : 'v3dv_extensions.h',
command : [
prog_python, '@INPUT0@', '--xml', '@INPUT1@',
'--out-h', '@OUTPUT@',
],
depend_files : files('v3dv_extensions.py'),
)
libv3dv_files = files(
'v3dv_device.c',
'v3dv_pipeline.c',
'v3dv_private.h',
'v3dv_util.c',
)
# The vulkan driver only supports version >= 42, which is the version present in
# Rpi4. We need to explicitly set it as we are reusing pieces from the GL v3d
# driver.
v3dv_flags = ['-DV3D_VERSION=42']
v3dv_deps = [
dep_libdrm,
idep_vulkan_util,
]
libvulkan_broadcom = shared_library(
'vulkan_broadcom',
[libv3dv_files, v3dv_entrypoints, v3dv_extensions_c, v3dv_extensions_h, sha1_h],
include_directories : [
inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_broadcom, inc_compiler, inc_util,
],
link_with : [
libbroadcom_v3d,
],
dependencies : v3dv_deps,
c_args : v3dv_flags,
link_args : ['-Wl,--build-id=sha1', ld_args_bsymbolic, ld_args_gc_sections],
gnu_symbol_visibility : 'hidden',
install : true,
)
if with_symbols_check
test(
'v3dv symbols check',
symbols_check,
args : [
'--lib', libvulkan_broadcom,
'--symbols-file', vulkan_icd_symbols,
symbols_check_args,
],
suite : ['broadcom'],
)
endif
broadcom_icd = custom_target(
'broadcom_icd',
input : 'v3dv_icd.py',
output : 'broadcom_icd.@0@.json'.format(host_machine.cpu()),
command : [
prog_python, '@INPUT@',
'--lib-path', join_paths(get_option('prefix'), get_option('libdir')),
'--out', '@OUTPUT@',
],
depend_files : files('v3dv_extensions.py'),
build_by_default : true,
install_dir : with_vulkan_icd_dir,
install : true,
)
/*
* Copyright © 2019 Raspberry Pi
*
* 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.
*/
#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include "v3dv_private.h"
#include "vk_util.h"
VkResult
v3dv_EnumerateInstanceExtensionProperties(const char *pLayerName,
uint32_t *pPropertyCount,
VkExtensionProperties *pProperties)
{
VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
for (int i = 0; i < V3DV_INSTANCE_EXTENSION_COUNT; i++) {
if (v3dv_instance_extensions_supported.extensions[i]) {
vk_outarray_append(&out, prop) {
*prop = v3dv_instance_extensions[i];
}
}
}
return vk_outarray_status(&out);
}
VkResult
v3dv_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkInstance *pInstance)
{
/* FIXME: stub */
return VK_SUCCESS;
}
void
v3dv_DestroyInstance(VkInstance _instance,
const VkAllocationCallbacks *pAllocator)
{
/* FIXME: stub */
}
VkResult
v3dv_EnumeratePhysicalDevices(VkInstance _instance,
uint32_t *pPhysicalDeviceCount,
VkPhysicalDevice *pPhysicalDevices)
{
/* FIXME: stub */
return VK_SUCCESS;
}
void
v3dv_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
VkPhysicalDeviceFeatures *pFeatures)
{
/* FIXME: stub */
}
void
v3dv_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties *pProperties)
{
/* FIXME: stub */
}
void
v3dv_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
uint32_t *pCount,
VkQueueFamilyProperties *pQueueFamilyProperties)
{
/* FIXME: stub */
}
void
v3dv_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
VkPhysicalDeviceMemoryProperties *pMemoryProperties)
{
/* FIXME: stub */
}
PFN_vkVoidFunction
v3dv_GetInstanceProcAddr(VkInstance _instance,
const char *pName)
{
V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
/* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly
* when we have to return valid function pointers, NULL, or it's left
* undefined. See the table for exact details.
*/
if (pName == NULL)
return NULL;
#define LOOKUP_V3DV_ENTRYPOINT(entrypoint) \
if (strcmp(pName, "vk" #entrypoint) == 0) \
return (PFN_vkVoidFunction)v3dv_##entrypoint
LOOKUP_V3DV_ENTRYPOINT(EnumerateInstanceExtensionProperties);
LOOKUP_V3DV_ENTRYPOINT(CreateInstance);
#undef LOOKUP_V3DV_ENTRYPOINT
if (instance == NULL)
return NULL;
int idx = v3dv_get_instance_entrypoint_index(pName);
if (idx >= 0)
return instance->dispatch.entrypoints[idx];
idx = v3dv_get_physical_device_entrypoint_index(pName);
if (idx >= 0)
return instance->physicalDevice.dispatch.entrypoints[idx];
idx = v3dv_get_device_entrypoint_index(pName);
if (idx >= 0)
return instance->device_dispatch.entrypoints[idx];
return NULL;
}
/* With version 1+ of the loader interface the ICD should expose
* vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
*/
PUBLIC
VKAPI_ATTR PFN_vkVoidFunction
VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance,
const char *pName);
PUBLIC
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,
const char* pName)
{
return v3dv_GetInstanceProcAddr(instance, pName);
}
PFN_vkVoidFunction
v3dv_GetDeviceProcAddr(VkDevice _device,
const char *pName)
{
V3DV_FROM_HANDLE(v3dv_device, device, _device);
if (!device || !pName)
return NULL;
int idx = v3dv_get_device_entrypoint_index(pName);
if (idx < 0)
return NULL;
return device->dispatch.entrypoints[idx];
}
/* With version 4+ of the loader interface the ICD should expose
* vk_icdGetPhysicalDeviceProcAddr()
*/
PUBLIC
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
const char* pName);
PFN_vkVoidFunction
vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
const char* pName)
{
V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
if (!pName || !instance)
return NULL;
int idx = v3dv_get_physical_device_entrypoint_index(pName);
if (idx < 0)
return NULL;
return instance->physicalDevice.dispatch.entrypoints[idx];
}
VkResult
v3dv_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName,
uint32_t *pPropertyCount,
VkExtensionProperties *pProperties)
{
/* FIXME: stub */
return VK_SUCCESS;
}
VkResult
v3dv_CreateDevice(VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDevice *pDevice)
{
/* FIXME: stub */
return VK_SUCCESS;
}
void
v3dv_DestroyDevice(VkDevice _device,
const VkAllocationCallbacks *pAllocator)
{
/* FIXME: stub */
}
void
v3dv_GetDeviceQueue(VkDevice _device,
uint32_t queueNodeIndex,
uint32_t queueIndex,
VkQueue *pQueue)
{
/* FIXME: stub */
}
This diff is collapsed.
COPYRIGHT = """\
/*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
*/
"""
import copy
import re
def _bool_to_c_expr(b):
if b is True:
return 'true'
if b is False:
return 'false'
return b
class Extension:
def __init__(self, name, ext_version, enable):
self.name = name
self.ext_version = int(ext_version)
self.enable = _bool_to_c_expr(enable)
class ApiVersion:
def __init__(self, version, enable):
self.version = version
self.enable = _bool_to_c_expr(enable)
API_PATCH_VERSION = 155
# Supported API versions. Each one is the maximum patch version for the given
# version. Version come in increasing order and each version is available if
# it's provided "enable" condition is true and all previous versions are
# available.
API_VERSIONS = [
ApiVersion('1.0', True),
# FIXME: for now we only support 1.0. We maintain this support from anv just in case in
# the future we support more that one version supported.
# ApiVersion('1.1', <condition> ),
]
MAX_API_VERSION = None # Computed later
EXTENSIONS = [
#FIXME: for now we don't support additional extensions beyond 1.0. Revisit later
]
# 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
for i in range(len(EXTENSIONS) - 1):
if extension_order(EXTENSIONS[i + 1]) < extension_order(EXTENSIONS[i]):
print(EXTENSIONS[i + 1].name + ' should come before ' + EXTENSIONS[i].name)
exit(1)
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):
patch = self.patch if self.patch is not None else 0
ver_list = [str(self.major), str(self.minor), str(patch)]
return 'VK_MAKE_VERSION(' + ', '.join(ver_list) + ')'
def __int_ver(self):
# This is just an expansion of VK_VERSION
patch = self.patch if self.patch is not None else 0
return (self.major << 22) | (self.minor << 12) | patch
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()
MAX_API_VERSION = VkVersion('0.0.0')
for version in API_VERSIONS:
version.version = VkVersion(version.version)
version.version.patch = API_PATCH_VERSION
assert version.version > MAX_API_VERSION
MAX_API_VERSION = version.version
COPYRIGHT = """\
/*
* 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, sub license, 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 NON-INFRINGEMENT.
* IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS 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.
*/
"""
import argparse
import xml.etree.cElementTree as et
from mako.template import Template
from v3dv_extensions import *
platform_defines = []
def _init_exts_from_xml(xml):
""" 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']
_TEMPLATE_H = Template(COPYRIGHT + """
#ifndef V3DV_EXTENSIONS_H
#define V3DV_EXTENSIONS_H
#include "stdbool.h"
#define V3DV_INSTANCE_EXTENSION_COUNT ${len(instance_extensions)}
extern const VkExtensionProperties v3dv_instance_extensions[];
struct v3dv_instance_extension_table {
union {
bool extensions[V3DV_INSTANCE_EXTENSION_COUNT];
struct {
%for ext in instance_extensions:
bool ${ext.name[3:]};
%endfor
};
};
};