2019-11-25 15:29:12 +00:00
|
|
|
/*
|
|
|
|
* 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"
|
|
|
|
|
2019-11-27 10:49:49 +00:00
|
|
|
#include "compiler/glsl_types.h"
|
|
|
|
|
|
|
|
static void *
|
|
|
|
default_alloc_func(void *pUserData, size_t size, size_t align,
|
|
|
|
VkSystemAllocationScope allocationScope)
|
|
|
|
{
|
|
|
|
return malloc(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
|
|
|
default_realloc_func(void *pUserData, void *pOriginal, size_t size,
|
|
|
|
size_t align, VkSystemAllocationScope allocationScope)
|
|
|
|
{
|
|
|
|
return realloc(pOriginal, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
default_free_func(void *pUserData, void *pMemory)
|
|
|
|
{
|
|
|
|
free(pMemory);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const VkAllocationCallbacks default_alloc = {
|
|
|
|
.pUserData = NULL,
|
|
|
|
.pfnAllocation = default_alloc_func,
|
|
|
|
.pfnReallocation = default_realloc_func,
|
|
|
|
.pfnFree = default_free_func,
|
|
|
|
};
|
|
|
|
|
2019-11-25 15:29:12 +00:00
|
|
|
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)
|
|
|
|
{
|
2019-11-27 10:49:49 +00:00
|
|
|
struct v3dv_instance *instance;
|
|
|
|
VkResult result;
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
|
|
|
|
|
|
|
|
struct v3dv_instance_extension_table enabled_extensions = {};
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
|
|
|
|
int idx;
|
|
|
|
for (idx = 0; idx < V3DV_INSTANCE_EXTENSION_COUNT; idx++) {
|
|
|
|
if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
|
|
|
|
v3dv_instance_extensions[idx].extensionName) == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (idx >= V3DV_INSTANCE_EXTENSION_COUNT)
|
|
|
|
return vk_error(NULL, VK_ERROR_EXTENSION_NOT_PRESENT);
|
|
|
|
|
|
|
|
if (!v3dv_instance_extensions_supported.extensions[idx])
|
|
|
|
return vk_error(NULL, VK_ERROR_EXTENSION_NOT_PRESENT);
|
|
|
|
|
|
|
|
enabled_extensions.extensions[idx] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
instance = vk_alloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
|
|
|
|
if (!instance)
|
|
|
|
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
instance->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
|
|
|
|
|
|
|
|
if (pAllocator)
|
|
|
|
instance->alloc = *pAllocator;
|
|
|
|
else
|
|
|
|
instance->alloc = default_alloc;
|
|
|
|
|
|
|
|
instance->app_info = (struct v3dv_app_info) { .api_version = 0 };
|
|
|
|
if (pCreateInfo->pApplicationInfo) {
|
|
|
|
const VkApplicationInfo *app = pCreateInfo->pApplicationInfo;
|
|
|
|
|
|
|
|
instance->app_info.app_name =
|
|
|
|
vk_strdup(&instance->alloc, app->pApplicationName,
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
|
|
|
|
instance->app_info.app_version = app->applicationVersion;
|
|
|
|
|
|
|
|
instance->app_info.engine_name =
|
|
|
|
vk_strdup(&instance->alloc, app->pEngineName,
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
|
|
|
|
instance->app_info.engine_version = app->engineVersion;
|
|
|
|
|
|
|
|
instance->app_info.api_version = app->apiVersion;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (instance->app_info.api_version == 0)
|
|
|
|
instance->app_info.api_version = VK_API_VERSION_1_0;
|
|
|
|
|
|
|
|
instance->enabled_extensions = enabled_extensions;
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < ARRAY_SIZE(instance->dispatch.entrypoints); i++) {
|
|
|
|
/* Vulkan requires that entrypoints for extensions which have not been
|
|
|
|
* enabled must not be advertised.
|
|
|
|
*/
|
|
|
|
if (!v3dv_instance_entrypoint_is_enabled(i,
|
|
|
|
instance->app_info.api_version,
|
|
|
|
&instance->enabled_extensions)) {
|
|
|
|
instance->dispatch.entrypoints[i] = NULL;
|
|
|
|
} else {
|
|
|
|
instance->dispatch.entrypoints[i] =
|
|
|
|
v3dv_instance_dispatch_table.entrypoints[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct v3dv_physical_device *pdevice = &instance->physicalDevice;
|
|
|
|
for (unsigned i = 0; i < ARRAY_SIZE(pdevice->dispatch.entrypoints); i++) {
|
|
|
|
/* Vulkan requires that entrypoints for extensions which have not been
|
|
|
|
* enabled must not be advertised.
|
|
|
|
*/
|
|
|
|
if (!v3dv_physical_device_entrypoint_is_enabled(i,
|
|
|
|
instance->app_info.api_version,
|
|
|
|
&instance->enabled_extensions)) {
|
|
|
|
pdevice->dispatch.entrypoints[i] = NULL;
|
|
|
|
} else {
|
|
|
|
pdevice->dispatch.entrypoints[i] =
|
|
|
|
v3dv_physical_device_dispatch_table.entrypoints[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (unsigned i = 0; i < ARRAY_SIZE(instance->device_dispatch.entrypoints); i++) {
|
|
|
|
/* Vulkan requires that entrypoints for extensions which have not been
|
|
|
|
* enabled must not be advertised.
|
|
|
|
*/
|
|
|
|
if (!v3dv_device_entrypoint_is_enabled(i,
|
|
|
|
instance->app_info.api_version,
|
|
|
|
&instance->enabled_extensions,
|
|
|
|
NULL)) {
|
|
|
|
instance->device_dispatch.entrypoints[i] = NULL;
|
|
|
|
} else {
|
|
|
|
instance->device_dispatch.entrypoints[i] =
|
|
|
|
v3dv_device_dispatch_table.entrypoints[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
instance->physicalDeviceCount = -1;
|
|
|
|
|
|
|
|
result = vk_debug_report_instance_init(&instance->debug_report_callbacks);
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
vk_free2(&default_alloc, pAllocator, instance);
|
|
|
|
return vk_error(NULL, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
glsl_type_singleton_init_or_ref();
|
|
|
|
|
|
|
|
VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
|
|
|
|
|
|
|
|
*pInstance = v3dv_instance_to_handle(instance);
|
2019-11-25 15:29:12 +00:00
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-11-27 11:43:36 +00:00
|
|
|
static void
|
|
|
|
physical_device_finish(struct v3dv_physical_device *device)
|
|
|
|
{
|
|
|
|
/* FIXME: stub */
|
|
|
|
}
|
|
|
|
|
2019-11-25 15:29:12 +00:00
|
|
|
void
|
|
|
|
v3dv_DestroyInstance(VkInstance _instance,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
{
|
2019-11-27 11:43:36 +00:00
|
|
|
V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
|
|
|
|
|
|
|
|
if (!instance)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (instance->physicalDeviceCount > 0) {
|
|
|
|
/* We support at most one physical device. */
|
|
|
|
assert(instance->physicalDeviceCount == 1);
|
|
|
|
physical_device_finish(&instance->physicalDevice);
|
|
|
|
}
|
|
|
|
|
|
|
|
vk_free(&instance->alloc, (char *)instance->app_info.app_name);
|
|
|
|
vk_free(&instance->alloc, (char *)instance->app_info.engine_name);
|
|
|
|
|
|
|
|
VG(VALGRIND_DESTROY_MEMPOOL(instance));
|
|
|
|
|
|
|
|
vk_debug_report_instance_destroy(&instance->debug_report_callbacks);
|
|
|
|
|
|
|
|
glsl_type_singleton_decref();
|
|
|
|
|
|
|
|
vk_free(&instance->alloc, instance);
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 */
|
|
|
|
}
|
2019-11-27 10:24:22 +00:00
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_CreateDebugReportCallbackEXT(VkInstance _instance,
|
|
|
|
const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
|
|
|
|
const VkAllocationCallbacks* pAllocator,
|
|
|
|
VkDebugReportCallbackEXT* pCallback)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
|
|
|
|
return vk_create_debug_report_callback(&instance->debug_report_callbacks,
|
|
|
|
pCreateInfo, pAllocator, &instance->alloc,
|
|
|
|
pCallback);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_DestroyDebugReportCallbackEXT(VkInstance _instance,
|
|
|
|
VkDebugReportCallbackEXT _callback,
|
|
|
|
const VkAllocationCallbacks* pAllocator)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
|
|
|
|
vk_destroy_debug_report_callback(&instance->debug_report_callbacks,
|
|
|
|
_callback, pAllocator, &instance->alloc);
|
|
|
|
}
|