mesa/src/broadcom/vulkan/v3dv_device.c

432 lines
13 KiB
C
Raw Normal View History

/*
* 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"
#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,
};
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)
{
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);
return VK_SUCCESS;
}
static void
physical_device_finish(struct v3dv_physical_device *device)
{
/* FIXME: stub */
}
void
v3dv_DestroyInstance(VkInstance _instance,
const VkAllocationCallbacks *pAllocator)
{
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);
}
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 */
}
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);
}