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>
|
2019-11-28 08:48:29 +00:00
|
|
|
#include <fcntl.h>
|
2019-11-25 15:29:12 +00:00
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/sysinfo.h>
|
|
|
|
#include <unistd.h>
|
2019-11-27 12:58:02 +00:00
|
|
|
#include <xf86drm.h>
|
2019-11-25 15:29:12 +00:00
|
|
|
|
|
|
|
#include "v3dv_private.h"
|
|
|
|
|
2019-12-04 09:39:01 +00:00
|
|
|
#include "common/v3d_debug.h"
|
2019-12-13 09:31:05 +00:00
|
|
|
|
|
|
|
#include "broadcom/cle/v3dx_pack.h"
|
|
|
|
|
2019-12-02 12:59:04 +00:00
|
|
|
#include "compiler/v3d_compiler.h"
|
2019-11-27 10:49:49 +00:00
|
|
|
#include "compiler/glsl_types.h"
|
2019-12-02 12:59:04 +00:00
|
|
|
|
2019-12-04 09:39:01 +00:00
|
|
|
#include "drm-uapi/v3d_drm.h"
|
2020-01-23 10:24:05 +00:00
|
|
|
#include "format/u_format.h"
|
2019-12-04 09:39:01 +00:00
|
|
|
#include "vk_util.h"
|
2019-11-27 10:49:49 +00:00
|
|
|
|
2020-07-04 12:09:58 +01:00
|
|
|
#include "util/build_id.h"
|
2020-07-07 14:56:44 +01:00
|
|
|
#include "util/debug.h"
|
2020-07-04 12:09:58 +01:00
|
|
|
|
2020-01-20 09:45:06 +00:00
|
|
|
#ifdef VK_USE_PLATFORM_XCB_KHR
|
|
|
|
#include <xcb/xcb.h>
|
|
|
|
#include <xcb/dri3.h>
|
2020-11-16 08:50:22 +00:00
|
|
|
#include <X11/Xlib-xcb.h>
|
2020-01-20 09:45:06 +00:00
|
|
|
#endif
|
|
|
|
|
2020-11-20 08:57:07 +00:00
|
|
|
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
|
|
|
#include <wayland-client.h>
|
|
|
|
#include "wayland-drm-client-protocol.h"
|
|
|
|
#endif
|
|
|
|
|
2020-07-07 11:23:12 +01:00
|
|
|
#ifdef USE_V3D_SIMULATOR
|
|
|
|
#include "drm-uapi/i915_drm.h"
|
|
|
|
#endif
|
|
|
|
|
2019-11-27 10:49:49 +00:00
|
|
|
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)
|
|
|
|
{
|
2019-11-29 10:09:51 +00:00
|
|
|
/* We don't support any layers */
|
|
|
|
if (pLayerName)
|
|
|
|
return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
|
|
|
|
|
2019-11-25 15:29:12 +00:00
|
|
|
VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
|
|
|
|
|
2021-01-27 23:21:38 +00:00
|
|
|
for (int i = 0; i < VK_INSTANCE_EXTENSION_COUNT; i++) {
|
2019-11-25 15:29:12 +00:00
|
|
|
if (v3dv_instance_extensions_supported.extensions[i]) {
|
|
|
|
vk_outarray_append(&out, prop) {
|
2021-01-27 23:21:38 +00:00
|
|
|
*prop = vk_instance_extensions[i];
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2021-01-27 12:46:58 +00:00
|
|
|
if (pAllocator == NULL)
|
|
|
|
pAllocator = &default_alloc;
|
|
|
|
|
2019-11-27 10:49:49 +00:00
|
|
|
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);
|
|
|
|
|
2021-01-27 23:21:38 +00:00
|
|
|
struct vk_instance_dispatch_table dispatch_table;
|
|
|
|
vk_instance_dispatch_table_from_entrypoints(
|
|
|
|
&dispatch_table, &v3dv_instance_entrypoints, true);
|
|
|
|
|
|
|
|
result = vk_instance_init(&instance->vk,
|
|
|
|
&v3dv_instance_extensions_supported,
|
|
|
|
&dispatch_table,
|
2021-01-27 12:46:58 +00:00
|
|
|
pCreateInfo, pAllocator);
|
2019-11-27 10:49:49 +00:00
|
|
|
|
2021-01-27 12:46:58 +00:00
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
vk_free(pAllocator, instance);
|
|
|
|
return vk_error(instance, result);
|
|
|
|
}
|
2019-11-27 10:49:49 +00:00
|
|
|
|
2019-12-03 09:54:52 +00:00
|
|
|
v3d_process_debug_variable();
|
|
|
|
|
2019-11-27 10:49:49 +00:00
|
|
|
instance->physicalDeviceCount = -1;
|
|
|
|
|
2020-09-20 21:54:33 +01:00
|
|
|
/* We start with the default values for the pipeline_cache envvars */
|
|
|
|
instance->pipeline_cache_enabled = true;
|
|
|
|
instance->default_pipeline_cache_enabled = true;
|
|
|
|
const char *pipeline_cache_str = getenv("V3DV_ENABLE_PIPELINE_CACHE");
|
|
|
|
if (pipeline_cache_str != NULL) {
|
|
|
|
if (strncmp(pipeline_cache_str, "full", 4) == 0) {
|
|
|
|
/* nothing to do, just to filter correct values */
|
|
|
|
} else if (strncmp(pipeline_cache_str, "no-default-cache", 16) == 0) {
|
|
|
|
instance->default_pipeline_cache_enabled = false;
|
|
|
|
} else if (strncmp(pipeline_cache_str, "off", 3) == 0) {
|
|
|
|
instance->pipeline_cache_enabled = false;
|
|
|
|
instance->default_pipeline_cache_enabled = false;
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Wrong value for envvar V3DV_ENABLE_PIPELINE_CACHE. "
|
|
|
|
"Allowed values are: full, no-default-cache, off\n");
|
|
|
|
}
|
|
|
|
}
|
2020-07-07 14:56:44 +01:00
|
|
|
|
2020-08-05 09:35:16 +01:00
|
|
|
if (instance->pipeline_cache_enabled == false) {
|
|
|
|
fprintf(stderr, "WARNING: v3dv pipeline cache is disabled. Performance "
|
|
|
|
"can be affected negatively\n");
|
2020-09-20 21:54:33 +01:00
|
|
|
} else {
|
|
|
|
if (instance->default_pipeline_cache_enabled == false) {
|
|
|
|
fprintf(stderr, "WARNING: default v3dv pipeline cache is disabled. "
|
|
|
|
"Performance can be affected negatively\n");
|
|
|
|
}
|
2020-08-05 09:35:16 +01:00
|
|
|
}
|
|
|
|
|
2019-11-27 10:49:49 +00:00
|
|
|
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)
|
|
|
|
{
|
2020-02-24 16:16:09 +00:00
|
|
|
v3dv_wsi_finish(device);
|
|
|
|
|
2020-04-23 09:46:07 +01:00
|
|
|
v3d_compiler_free(device->compiler);
|
|
|
|
|
2020-01-23 10:59:28 +00:00
|
|
|
close(device->render_fd);
|
2020-01-20 09:45:06 +00:00
|
|
|
if (device->display_fd >= 0)
|
|
|
|
close(device->display_fd);
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
if (device->master_fd >= 0)
|
|
|
|
close(device->master_fd);
|
2019-11-29 12:55:38 +00:00
|
|
|
|
2019-11-29 08:01:56 +00:00
|
|
|
free(device->name);
|
|
|
|
|
2019-11-29 12:55:38 +00:00
|
|
|
#if using_v3d_simulator
|
|
|
|
v3d_simulator_destroy(device->sim_file);
|
|
|
|
#endif
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
|
2021-01-27 12:46:58 +00:00
|
|
|
vk_physical_device_finish(&device->vk);
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
mtx_destroy(&device->mutex);
|
2019-11-27 11:43:36 +00:00
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
VG(VALGRIND_DESTROY_MEMPOOL(instance));
|
|
|
|
|
|
|
|
glsl_type_singleton_decref();
|
|
|
|
|
2021-01-27 12:46:58 +00:00
|
|
|
vk_instance_finish(&instance->vk);
|
|
|
|
vk_free(&instance->vk.alloc, instance);
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
2019-12-04 09:25:21 +00:00
|
|
|
static uint64_t
|
|
|
|
compute_heap_size()
|
|
|
|
{
|
2020-08-08 23:46:20 +01:00
|
|
|
#if !using_v3d_simulator
|
2019-12-04 09:25:21 +00:00
|
|
|
/* Query the total ram from the system */
|
|
|
|
struct sysinfo info;
|
|
|
|
sysinfo(&info);
|
|
|
|
|
|
|
|
uint64_t total_ram = (uint64_t)info.totalram * (uint64_t)info.mem_unit;
|
2020-08-08 23:46:20 +01:00
|
|
|
#else
|
|
|
|
uint64_t total_ram = (uint64_t) v3d_simulator_get_mem_size();
|
|
|
|
#endif
|
2019-12-04 09:25:21 +00:00
|
|
|
|
|
|
|
/* We don't want to burn too much ram with the GPU. If the user has 4GiB
|
|
|
|
* or less, we use at most half. If they have more than 4GiB, we use 3/4.
|
|
|
|
*/
|
|
|
|
uint64_t available_ram;
|
|
|
|
if (total_ram <= 4ull * 1024ull * 1024ull * 1024ull)
|
|
|
|
available_ram = total_ram / 2;
|
|
|
|
else
|
|
|
|
available_ram = total_ram * 3 / 4;
|
|
|
|
|
|
|
|
return available_ram;
|
|
|
|
}
|
|
|
|
|
2020-01-20 09:45:06 +00:00
|
|
|
#if !using_v3d_simulator
|
|
|
|
#ifdef VK_USE_PLATFORM_XCB_KHR
|
|
|
|
static int
|
2020-11-16 08:50:22 +00:00
|
|
|
create_display_fd_xcb(VkIcdSurfaceBase *surface)
|
2020-01-20 09:45:06 +00:00
|
|
|
{
|
2020-09-17 15:12:31 +01:00
|
|
|
int fd = -1;
|
|
|
|
|
2020-11-16 08:50:22 +00:00
|
|
|
xcb_connection_t *conn;
|
|
|
|
if (surface) {
|
|
|
|
if (surface->platform == VK_ICD_WSI_PLATFORM_XLIB)
|
|
|
|
conn = XGetXCBConnection(((VkIcdSurfaceXlib *)surface)->dpy);
|
|
|
|
else
|
|
|
|
conn = ((VkIcdSurfaceXcb *)surface)->connection;
|
|
|
|
} else {
|
|
|
|
conn = xcb_connect(NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2020-09-17 15:12:31 +01:00
|
|
|
if (xcb_connection_has_error(conn))
|
|
|
|
goto finish;
|
|
|
|
|
2020-01-20 09:45:06 +00:00
|
|
|
const xcb_setup_t *setup = xcb_get_setup(conn);
|
|
|
|
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
|
|
|
|
xcb_screen_t *screen = iter.data;
|
|
|
|
|
|
|
|
xcb_dri3_open_cookie_t cookie;
|
|
|
|
xcb_dri3_open_reply_t *reply;
|
|
|
|
cookie = xcb_dri3_open(conn, screen->root, None);
|
|
|
|
reply = xcb_dri3_open_reply(conn, cookie, NULL);
|
|
|
|
if (!reply)
|
2020-09-17 15:12:31 +01:00
|
|
|
goto finish;
|
2020-01-20 09:45:06 +00:00
|
|
|
|
2020-09-17 15:12:31 +01:00
|
|
|
if (reply->nfd != 1)
|
|
|
|
goto finish;
|
2020-01-20 09:45:06 +00:00
|
|
|
|
2020-09-17 15:12:31 +01:00
|
|
|
fd = xcb_dri3_open_reply_fds(conn, reply)[0];
|
2020-01-20 09:45:06 +00:00
|
|
|
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
|
|
|
|
2020-09-17 15:12:31 +01:00
|
|
|
finish:
|
2020-11-16 08:50:22 +00:00
|
|
|
if (!surface)
|
|
|
|
xcb_disconnect(conn);
|
2020-09-17 15:12:31 +01:00
|
|
|
if (reply)
|
|
|
|
free(reply);
|
|
|
|
|
2020-01-20 09:45:06 +00:00
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
#endif
|
2020-11-16 08:50:22 +00:00
|
|
|
|
2020-11-20 08:57:07 +00:00
|
|
|
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
|
|
|
struct v3dv_wayland_info {
|
|
|
|
struct wl_drm *wl_drm;
|
|
|
|
int fd;
|
|
|
|
bool is_set;
|
|
|
|
bool authenticated;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3dv_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
|
|
|
|
{
|
|
|
|
struct v3dv_wayland_info *info = data;
|
|
|
|
info->fd = open(device, O_RDWR | O_CLOEXEC);
|
|
|
|
info->is_set = info->fd != -1;
|
2020-12-02 06:57:32 +00:00
|
|
|
if (!info->is_set) {
|
|
|
|
fprintf(stderr, "v3dv_drm_handle_device: could not open %s (%s)\n",
|
|
|
|
device, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
2020-11-20 08:57:07 +00:00
|
|
|
|
|
|
|
drm_magic_t magic;
|
2020-11-30 06:44:28 +00:00
|
|
|
if (drmGetMagic(info->fd, &magic)) {
|
2020-12-02 06:57:32 +00:00
|
|
|
fprintf(stderr, "v3dv_drm_handle_device: drmGetMagic failed\n");
|
|
|
|
close(info->fd);
|
|
|
|
info->fd = -1;
|
|
|
|
info->is_set = false;
|
2020-11-30 06:44:28 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-11-20 08:57:07 +00:00
|
|
|
wl_drm_authenticate(info->wl_drm, magic);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3dv_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3dv_drm_handle_authenticated(void *data, struct wl_drm *drm)
|
|
|
|
{
|
|
|
|
struct v3dv_wayland_info *info = data;
|
|
|
|
info->authenticated = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3dv_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
struct wl_drm_listener v3dv_drm_listener = {
|
|
|
|
.device = v3dv_drm_handle_device,
|
|
|
|
.format = v3dv_drm_handle_format,
|
|
|
|
.authenticated = v3dv_drm_handle_authenticated,
|
|
|
|
.capabilities = v3dv_drm_handle_capabilities
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3dv_registry_global(void *data,
|
|
|
|
struct wl_registry *registry,
|
|
|
|
uint32_t name,
|
|
|
|
const char *interface,
|
|
|
|
uint32_t version)
|
|
|
|
{
|
|
|
|
struct v3dv_wayland_info *info = data;
|
|
|
|
if (strcmp(interface, "wl_drm") == 0) {
|
|
|
|
info->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface,
|
|
|
|
MIN2(version, 2));
|
|
|
|
wl_drm_add_listener(info->wl_drm, &v3dv_drm_listener, data);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
v3dv_registry_global_remove_cb(void *data,
|
|
|
|
struct wl_registry *registry,
|
|
|
|
uint32_t name)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
create_display_fd_wayland(VkIcdSurfaceBase *surface)
|
|
|
|
{
|
|
|
|
struct wl_display *display;
|
|
|
|
struct wl_registry *registry = NULL;
|
|
|
|
|
|
|
|
struct v3dv_wayland_info info = {
|
|
|
|
.wl_drm = NULL,
|
|
|
|
.fd = -1,
|
|
|
|
.is_set = false,
|
|
|
|
.authenticated = false
|
|
|
|
};
|
|
|
|
|
|
|
|
if (surface)
|
|
|
|
display = ((VkIcdSurfaceWayland *) surface)->display;
|
|
|
|
else
|
|
|
|
display = wl_display_connect(NULL);
|
|
|
|
|
|
|
|
if (!display)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
registry = wl_display_get_registry(display);
|
|
|
|
if (!registry) {
|
|
|
|
if (!surface)
|
|
|
|
wl_display_disconnect(display);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct wl_registry_listener registry_listener = {
|
|
|
|
v3dv_registry_global,
|
|
|
|
v3dv_registry_global_remove_cb
|
|
|
|
};
|
|
|
|
wl_registry_add_listener(registry, ®istry_listener, &info);
|
|
|
|
|
|
|
|
wl_display_roundtrip(display); /* For the registry advertisement */
|
|
|
|
wl_display_roundtrip(display); /* For the DRM device event */
|
|
|
|
wl_display_roundtrip(display); /* For the authentication event */
|
|
|
|
|
|
|
|
wl_drm_destroy(info.wl_drm);
|
|
|
|
wl_registry_destroy(registry);
|
|
|
|
|
|
|
|
if (!surface)
|
|
|
|
wl_display_disconnect(display);
|
|
|
|
|
|
|
|
if (!info.is_set)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (!info.authenticated)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return info.fd;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-11-16 08:50:22 +00:00
|
|
|
/* Acquire an authenticated display fd without a surface reference. This is the
|
|
|
|
* case where the application is making WSI allocations outside the Vulkan
|
|
|
|
* swapchain context (only Zink, for now). Since we lack information about the
|
|
|
|
* underlying surface we just try our best to figure out the correct display
|
|
|
|
* and platform to use. It should work in most cases.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
acquire_display_device_no_surface(struct v3dv_instance *instance,
|
|
|
|
struct v3dv_physical_device *pdevice)
|
|
|
|
{
|
2020-11-20 08:57:07 +00:00
|
|
|
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
|
|
|
pdevice->display_fd = create_display_fd_wayland(NULL);
|
|
|
|
#endif
|
|
|
|
|
2020-11-16 08:50:22 +00:00
|
|
|
#ifdef VK_USE_PLATFORM_XCB_KHR
|
2020-11-20 08:57:07 +00:00
|
|
|
if (pdevice->display_fd == -1)
|
|
|
|
pdevice->display_fd = create_display_fd_xcb(NULL);
|
2020-11-16 08:50:22 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
|
|
|
|
if (pdevice->display_fd == - 1 && pdevice->master_fd >= 0)
|
|
|
|
pdevice->display_fd = dup(pdevice->master_fd);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Acquire an authenticated display fd from the surface. This is the regular
|
|
|
|
* case where the application is using swapchains to create WSI allocations.
|
|
|
|
* In this case we use the surface information to figure out the correct
|
|
|
|
* display and platform combination.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
acquire_display_device_surface(struct v3dv_instance *instance,
|
|
|
|
struct v3dv_physical_device *pdevice,
|
|
|
|
VkIcdSurfaceBase *surface)
|
|
|
|
{
|
|
|
|
/* Mesa will set both of VK_USE_PLATFORM_{XCB,XLIB} when building with
|
|
|
|
* platform X11, so only check for XCB and rely on XCB to get an
|
|
|
|
* authenticated device also for Xlib.
|
|
|
|
*/
|
|
|
|
#ifdef VK_USE_PLATFORM_XCB_KHR
|
|
|
|
if (surface->platform == VK_ICD_WSI_PLATFORM_XCB ||
|
|
|
|
surface->platform == VK_ICD_WSI_PLATFORM_XLIB) {
|
|
|
|
pdevice->display_fd = create_display_fd_xcb(surface);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-11-20 08:57:07 +00:00
|
|
|
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
|
|
|
|
if (surface->platform == VK_ICD_WSI_PLATFORM_WAYLAND)
|
|
|
|
pdevice->display_fd = create_display_fd_wayland(surface);
|
|
|
|
#endif
|
|
|
|
|
2020-11-16 08:50:22 +00:00
|
|
|
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
|
|
|
|
if (surface->platform == VK_ICD_WSI_PLATFORM_DISPLAY &&
|
|
|
|
pdevice->master_fd >= 0) {
|
|
|
|
pdevice->display_fd = dup(pdevice->master_fd);
|
|
|
|
}
|
2020-01-20 09:45:06 +00:00
|
|
|
#endif
|
2020-11-16 08:50:22 +00:00
|
|
|
}
|
|
|
|
#endif /* !using_v3d_simulator */
|
2020-01-20 09:45:06 +00:00
|
|
|
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
/* Attempts to get an authenticated display fd from the display server that
|
|
|
|
* we can use to allocate BOs for presentable images.
|
|
|
|
*/
|
|
|
|
VkResult
|
|
|
|
v3dv_physical_device_acquire_display(struct v3dv_instance *instance,
|
2020-11-16 08:50:22 +00:00
|
|
|
struct v3dv_physical_device *pdevice,
|
|
|
|
VkIcdSurfaceBase *surface)
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
{
|
|
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
mtx_lock(&pdevice->mutex);
|
|
|
|
|
|
|
|
if (pdevice->display_fd != -1)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
/* When running on the simulator we do everything on a single render node so
|
|
|
|
* we don't need to get an authenticated display fd from the display server.
|
|
|
|
*/
|
|
|
|
#if !using_v3d_simulator
|
2020-11-16 08:50:22 +00:00
|
|
|
if (surface)
|
|
|
|
acquire_display_device_surface(instance, pdevice, surface);
|
|
|
|
else
|
|
|
|
acquire_display_device_no_surface(instance, pdevice);
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
|
|
|
|
if (pdevice->display_fd == -1)
|
|
|
|
result = VK_ERROR_INITIALIZATION_FAILED;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
done:
|
|
|
|
mtx_unlock(&pdevice->mutex);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-05-26 07:38:31 +01:00
|
|
|
static bool
|
|
|
|
v3d_has_feature(struct v3dv_physical_device *device, enum drm_v3d_param feature)
|
|
|
|
{
|
|
|
|
struct drm_v3d_get_param p = {
|
|
|
|
.param = feature,
|
|
|
|
};
|
|
|
|
if (v3dv_ioctl(device->render_fd, DRM_IOCTL_V3D_GET_PARAM, &p) != 0)
|
|
|
|
return false;
|
|
|
|
return p.value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
device_has_expected_features(struct v3dv_physical_device *device)
|
|
|
|
{
|
|
|
|
return v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_TFU) &&
|
|
|
|
v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_CSD) &&
|
|
|
|
v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH);
|
|
|
|
}
|
|
|
|
|
2020-07-04 12:09:58 +01:00
|
|
|
|
|
|
|
static VkResult
|
|
|
|
init_uuids(struct v3dv_physical_device *device)
|
|
|
|
{
|
|
|
|
const struct build_id_note *note =
|
|
|
|
build_id_find_nhdr_for_addr(init_uuids);
|
|
|
|
if (!note) {
|
2021-01-27 22:45:28 +00:00
|
|
|
return vk_errorf((struct v3dv_instance*) device->vk.instance,
|
2020-07-04 12:09:58 +01:00
|
|
|
VK_ERROR_INITIALIZATION_FAILED,
|
|
|
|
"Failed to find build-id");
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned build_id_len = build_id_length(note);
|
|
|
|
if (build_id_len < 20) {
|
2021-01-27 22:45:28 +00:00
|
|
|
return vk_errorf((struct v3dv_instance*) device->vk.instance,
|
2020-07-04 12:09:58 +01:00
|
|
|
VK_ERROR_INITIALIZATION_FAILED,
|
|
|
|
"build-id too short. It needs to be a SHA");
|
|
|
|
}
|
|
|
|
|
2020-10-05 09:44:59 +01:00
|
|
|
uint32_t vendor_id = v3dv_physical_device_vendor_id(device);
|
|
|
|
uint32_t device_id = v3dv_physical_device_device_id(device);
|
|
|
|
|
2020-07-04 12:09:58 +01:00
|
|
|
struct mesa_sha1 sha1_ctx;
|
|
|
|
uint8_t sha1[20];
|
|
|
|
STATIC_ASSERT(VK_UUID_SIZE <= sizeof(sha1));
|
|
|
|
|
|
|
|
/* The pipeline cache UUID is used for determining when a pipeline cache is
|
|
|
|
* invalid. It needs both a driver build and the PCI ID of the device.
|
|
|
|
*/
|
|
|
|
_mesa_sha1_init(&sha1_ctx);
|
|
|
|
_mesa_sha1_update(&sha1_ctx, build_id_data(note), build_id_len);
|
|
|
|
_mesa_sha1_update(&sha1_ctx, &device_id, sizeof(device_id));
|
|
|
|
_mesa_sha1_final(&sha1_ctx, sha1);
|
|
|
|
memcpy(device->pipeline_cache_uuid, sha1, VK_UUID_SIZE);
|
|
|
|
|
2020-10-05 09:44:59 +01:00
|
|
|
/* The driver UUID is used for determining sharability of images and memory
|
|
|
|
* between two Vulkan instances in separate processes. People who want to
|
|
|
|
* share memory need to also check the device UUID (below) so all this
|
|
|
|
* needs to be is the build-id.
|
|
|
|
*/
|
|
|
|
memcpy(device->driver_uuid, build_id_data(note), VK_UUID_SIZE);
|
|
|
|
|
|
|
|
/* The device UUID uniquely identifies the given device within the machine.
|
|
|
|
* Since we never have more than one device, this doesn't need to be a real
|
|
|
|
* UUID.
|
|
|
|
*/
|
|
|
|
_mesa_sha1_init(&sha1_ctx);
|
|
|
|
_mesa_sha1_update(&sha1_ctx, &vendor_id, sizeof(vendor_id));
|
|
|
|
_mesa_sha1_update(&sha1_ctx, &device_id, sizeof(device_id));
|
|
|
|
_mesa_sha1_final(&sha1_ctx, sha1);
|
|
|
|
memcpy(device->device_uuid, sha1, VK_UUID_SIZE);
|
|
|
|
|
2020-07-04 12:09:58 +01:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-11-27 12:58:02 +00:00
|
|
|
static VkResult
|
|
|
|
physical_device_init(struct v3dv_physical_device *device,
|
|
|
|
struct v3dv_instance *instance,
|
2020-11-04 17:45:10 +00:00
|
|
|
drmDevicePtr drm_render_device,
|
|
|
|
drmDevicePtr drm_primary_device)
|
2019-11-27 12:58:02 +00:00
|
|
|
{
|
2019-11-29 08:01:56 +00:00
|
|
|
VkResult result = VK_SUCCESS;
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
int32_t master_fd = -1;
|
2019-11-29 08:01:56 +00:00
|
|
|
|
2021-01-27 23:21:38 +00:00
|
|
|
struct vk_physical_device_dispatch_table dispatch_table;
|
|
|
|
vk_physical_device_dispatch_table_from_entrypoints
|
|
|
|
(&dispatch_table, &v3dv_physical_device_entrypoints, true);
|
|
|
|
|
|
|
|
result = vk_physical_device_init(&device->vk, &instance->vk, NULL,
|
|
|
|
&dispatch_table);
|
2021-01-27 12:46:58 +00:00
|
|
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
goto fail;
|
2019-11-28 08:48:29 +00:00
|
|
|
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
assert(drm_render_device);
|
2020-11-04 17:45:10 +00:00
|
|
|
const char *path = drm_render_device->nodes[DRM_NODE_RENDER];
|
2020-01-20 09:45:06 +00:00
|
|
|
int32_t render_fd = open(path, O_RDWR | O_CLOEXEC);
|
2021-01-27 12:46:58 +00:00
|
|
|
if (render_fd < 0) {
|
|
|
|
result = VK_ERROR_INCOMPATIBLE_DRIVER;
|
|
|
|
goto fail;
|
|
|
|
}
|
2020-01-20 09:45:06 +00:00
|
|
|
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
/* If we are running on VK_KHR_display we need to acquire the master
|
|
|
|
* display device now for the v3dv_wsi_init() call below. For anything else
|
|
|
|
* we postpone that until a swapchain is created.
|
2020-01-20 09:45:06 +00:00
|
|
|
*/
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
|
2021-01-27 23:21:38 +00:00
|
|
|
if (instance->vk.enabled_extensions.KHR_display) {
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
#if !using_v3d_simulator
|
2020-11-04 17:45:10 +00:00
|
|
|
/* Open the primary node on the vc4 display device */
|
|
|
|
assert(drm_primary_device);
|
|
|
|
const char *primary_path = drm_primary_device->nodes[DRM_NODE_PRIMARY];
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
master_fd = open(primary_path, O_RDWR | O_CLOEXEC);
|
2020-11-04 17:45:10 +00:00
|
|
|
#else
|
|
|
|
/* There is only one device with primary and render nodes.
|
|
|
|
* Open its primary node.
|
|
|
|
*/
|
|
|
|
const char *primary_path = drm_render_device->nodes[DRM_NODE_PRIMARY];
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
master_fd = open(primary_path, O_RDWR | O_CLOEXEC);
|
|
|
|
#endif
|
2020-11-04 17:45:10 +00:00
|
|
|
}
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
|
|
|
|
#if using_v3d_simulator
|
2020-11-04 17:45:10 +00:00
|
|
|
device->sim_file = v3d_simulator_init(render_fd);
|
2020-01-20 09:45:06 +00:00
|
|
|
#endif
|
|
|
|
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
device->render_fd = render_fd; /* The v3d render node */
|
|
|
|
device->display_fd = -1; /* Authenticated vc4 primary node */
|
|
|
|
device->master_fd = master_fd; /* Master vc4 primary node */
|
2019-11-28 08:48:29 +00:00
|
|
|
|
2020-01-23 10:59:28 +00:00
|
|
|
if (!v3d_get_device_info(device->render_fd, &device->devinfo, &v3dv_ioctl)) {
|
2019-11-29 08:01:56 +00:00
|
|
|
result = VK_ERROR_INCOMPATIBLE_DRIVER;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2020-05-26 07:38:31 +01:00
|
|
|
if (device->devinfo.ver < 42) {
|
|
|
|
result = VK_ERROR_INCOMPATIBLE_DRIVER;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!device_has_expected_features(device)) {
|
|
|
|
result = VK_ERROR_INCOMPATIBLE_DRIVER;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2020-10-05 09:44:59 +01:00
|
|
|
result = init_uuids(device);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
goto fail;
|
|
|
|
|
2019-12-02 12:59:04 +00:00
|
|
|
device->compiler = v3d_compiler_init(&device->devinfo);
|
|
|
|
device->next_program_id = 0;
|
|
|
|
|
2019-11-29 08:01:56 +00:00
|
|
|
asprintf(&device->name, "V3D %d.%d",
|
|
|
|
device->devinfo.ver / 10, device->devinfo.ver % 10);
|
|
|
|
|
2019-12-04 09:25:21 +00:00
|
|
|
/* Setup available memory heaps and types */
|
|
|
|
VkPhysicalDeviceMemoryProperties *mem = &device->memory;
|
|
|
|
mem->memoryHeapCount = 1;
|
|
|
|
mem->memoryHeaps[0].size = compute_heap_size();
|
|
|
|
mem->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
|
|
|
|
|
|
|
|
/* This is the only combination required by the spec */
|
2020-09-23 10:28:41 +01:00
|
|
|
mem->memoryTypeCount = 1;
|
2019-12-04 09:25:21 +00:00
|
|
|
mem->memoryTypes[0].propertyFlags =
|
|
|
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
|
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
|
|
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
|
|
|
|
mem->memoryTypes[0].heapIndex = 0;
|
|
|
|
|
2020-01-10 10:31:51 +00:00
|
|
|
device->options.merge_jobs = getenv("V3DV_NO_MERGE_JOBS") == NULL;
|
|
|
|
|
2020-01-16 10:14:17 +00:00
|
|
|
result = v3dv_wsi_init(device);
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
vk_error(instance, result);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
v3dv_physical_device_get_supported_extensions(device,
|
2021-01-27 23:21:38 +00:00
|
|
|
&device->vk.supported_extensions);
|
2020-06-04 10:14:10 +01:00
|
|
|
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
pthread_mutex_init(&device->mutex, NULL);
|
|
|
|
|
2020-01-20 09:45:06 +00:00
|
|
|
return VK_SUCCESS;
|
2020-01-16 10:14:17 +00:00
|
|
|
|
2019-12-04 09:25:21 +00:00
|
|
|
fail:
|
2021-01-27 12:46:58 +00:00
|
|
|
vk_physical_device_finish(&device->vk);
|
|
|
|
|
2020-01-20 09:45:06 +00:00
|
|
|
if (render_fd >= 0)
|
|
|
|
close(render_fd);
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
if (master_fd >= 0)
|
|
|
|
close(master_fd);
|
2019-11-29 08:01:56 +00:00
|
|
|
|
|
|
|
return result;
|
2019-11-27 12:58:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static VkResult
|
|
|
|
enumerate_devices(struct v3dv_instance *instance)
|
|
|
|
{
|
|
|
|
/* TODO: Check for more devices? */
|
|
|
|
drmDevicePtr devices[8];
|
|
|
|
VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER;
|
|
|
|
int max_devices;
|
|
|
|
|
|
|
|
instance->physicalDeviceCount = 0;
|
|
|
|
|
|
|
|
max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
|
|
|
|
if (max_devices < 1)
|
|
|
|
return VK_ERROR_INCOMPATIBLE_DRIVER;
|
|
|
|
|
2020-01-20 09:45:06 +00:00
|
|
|
#if !using_v3d_simulator
|
|
|
|
int32_t v3d_idx = -1;
|
|
|
|
int32_t vc4_idx = -1;
|
|
|
|
#endif
|
2019-11-27 12:58:02 +00:00
|
|
|
for (unsigned i = 0; i < (unsigned)max_devices; i++) {
|
2020-01-20 09:45:06 +00:00
|
|
|
#if using_v3d_simulator
|
|
|
|
/* In the simulator, we look for an Intel render node */
|
2020-11-04 17:45:10 +00:00
|
|
|
const int required_nodes = (1 << DRM_NODE_RENDER) | (1 << DRM_NODE_PRIMARY);
|
|
|
|
if ((devices[i]->available_nodes & required_nodes) == required_nodes &&
|
|
|
|
devices[i]->bustype == DRM_BUS_PCI &&
|
|
|
|
devices[i]->deviceinfo.pci->vendor_id == 0x8086) {
|
2020-01-20 09:45:06 +00:00
|
|
|
result = physical_device_init(&instance->physicalDevice, instance,
|
2020-11-04 17:45:10 +00:00
|
|
|
devices[i], NULL);
|
2019-11-27 12:58:02 +00:00
|
|
|
if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
|
|
|
|
break;
|
|
|
|
}
|
2020-01-20 09:45:06 +00:00
|
|
|
#else
|
|
|
|
/* On actual hardware, we should have a render node (v3d)
|
|
|
|
* and a primary node (vc4). We will need to use the primary
|
|
|
|
* to allocate WSI buffers and share them with the render node
|
|
|
|
* via prime, but that is a privileged operation so we need the
|
|
|
|
* primary node to be authenticated, and for that we need the
|
|
|
|
* display server to provide the device fd (with DRI3), so we
|
|
|
|
* here we only check that the device is present but we don't
|
|
|
|
* try to open it.
|
|
|
|
*/
|
|
|
|
if (devices[i]->bustype != DRM_BUS_PLATFORM)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER) {
|
|
|
|
char **compat = devices[i]->deviceinfo.platform->compatible;
|
|
|
|
while (*compat) {
|
|
|
|
if (strncmp(*compat, "brcm,2711-v3d", 13) == 0) {
|
|
|
|
v3d_idx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
compat++;
|
|
|
|
}
|
|
|
|
} else if (devices[i]->available_nodes & 1 << DRM_NODE_PRIMARY) {
|
|
|
|
char **compat = devices[i]->deviceinfo.platform->compatible;
|
|
|
|
while (*compat) {
|
2020-07-03 09:46:51 +01:00
|
|
|
if (strncmp(*compat, "brcm,bcm2711-vc5", 16) == 0 ||
|
|
|
|
strncmp(*compat, "brcm,bcm2835-vc4", 16) == 0 ) {
|
2020-01-20 09:45:06 +00:00
|
|
|
vc4_idx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
compat++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2019-11-27 12:58:02 +00:00
|
|
|
}
|
2020-01-20 09:45:06 +00:00
|
|
|
|
|
|
|
#if !using_v3d_simulator
|
|
|
|
if (v3d_idx == -1 || vc4_idx == -1)
|
|
|
|
result = VK_ERROR_INCOMPATIBLE_DRIVER;
|
|
|
|
else
|
|
|
|
result = physical_device_init(&instance->physicalDevice, instance,
|
2020-11-04 17:45:10 +00:00
|
|
|
devices[v3d_idx], devices[vc4_idx]);
|
2020-01-20 09:45:06 +00:00
|
|
|
#endif
|
|
|
|
|
2019-11-27 12:58:02 +00:00
|
|
|
drmFreeDevices(devices, max_devices);
|
|
|
|
|
|
|
|
if (result == VK_SUCCESS)
|
|
|
|
instance->physicalDeviceCount = 1;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VkResult
|
|
|
|
instance_ensure_physical_device(struct v3dv_instance *instance)
|
|
|
|
{
|
|
|
|
if (instance->physicalDeviceCount < 0) {
|
|
|
|
VkResult result = enumerate_devices(instance);
|
|
|
|
if (result != VK_SUCCESS &&
|
|
|
|
result != VK_ERROR_INCOMPATIBLE_DRIVER)
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-11-25 15:29:12 +00:00
|
|
|
VkResult
|
|
|
|
v3dv_EnumeratePhysicalDevices(VkInstance _instance,
|
|
|
|
uint32_t *pPhysicalDeviceCount,
|
|
|
|
VkPhysicalDevice *pPhysicalDevices)
|
|
|
|
{
|
2019-11-27 12:58:02 +00:00
|
|
|
V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
|
|
|
|
VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
|
|
|
|
|
|
|
|
VkResult result = instance_ensure_physical_device(instance);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
|
|
|
|
|
|
|
if (instance->physicalDeviceCount == 0)
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
assert(instance->physicalDeviceCount == 1);
|
|
|
|
vk_outarray_append(&out, i) {
|
|
|
|
*i = v3dv_physical_device_to_handle(&instance->physicalDevice);
|
|
|
|
}
|
2019-11-25 15:29:12 +00:00
|
|
|
|
2019-11-27 12:58:02 +00:00
|
|
|
return vk_outarray_status(&out);
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
|
|
|
|
VkPhysicalDeviceFeatures *pFeatures)
|
|
|
|
{
|
2019-11-29 09:58:53 +00:00
|
|
|
memset(pFeatures, 0, sizeof(*pFeatures));
|
|
|
|
|
|
|
|
*pFeatures = (VkPhysicalDeviceFeatures) {
|
2020-02-21 08:33:03 +00:00
|
|
|
.robustBufferAccess = true, /* This feature is mandatory */
|
2020-11-04 12:35:08 +00:00
|
|
|
.fullDrawIndexUint32 = false, /* Only available since V3D 4.4.9.1 */
|
2020-06-28 01:08:16 +01:00
|
|
|
.imageCubeArray = true,
|
2020-11-04 12:35:08 +00:00
|
|
|
.independentBlend = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.geometryShader = false,
|
|
|
|
.tessellationShader = false,
|
2020-08-06 13:15:41 +01:00
|
|
|
.sampleRateShading = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.dualSrcBlend = false,
|
2020-10-26 12:00:07 +00:00
|
|
|
.logicOp = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.multiDrawIndirect = false,
|
2020-11-04 12:35:08 +00:00
|
|
|
.drawIndirectFirstInstance = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.depthClamp = false,
|
|
|
|
.depthBiasClamp = false,
|
2020-07-22 09:12:51 +01:00
|
|
|
.fillModeNonSolid = true,
|
2020-05-13 10:21:12 +01:00
|
|
|
.depthBounds = false, /* Only available since V3D 4.3.16.2 */
|
2020-05-13 11:21:55 +01:00
|
|
|
.wideLines = true,
|
2020-08-16 01:19:10 +01:00
|
|
|
.largePoints = true,
|
2020-10-27 11:39:53 +00:00
|
|
|
.alphaToOne = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.multiViewport = false,
|
2020-03-29 15:29:55 +01:00
|
|
|
.samplerAnisotropy = true,
|
2020-02-27 07:55:40 +00:00
|
|
|
.textureCompressionETC2 = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.textureCompressionASTC_LDR = false,
|
|
|
|
.textureCompressionBC = false,
|
v3dv: implement occlusion queries
The design for queries in Vulkan requires that some commands execute
in the GPU as part of a command buffer. Unfortunately, V3D doesn't
really have supprt for this, which means that we need to execute them
in the CPU but we still need to make it look as if they happened
inside the comamnd buffer from the point of view of the user, which
adds certain hassle.
The above means that in some cases we need to do CPU waits for certain
parts of the command buffer to execute so we can then run the CPU
code. For exmaple, we need to wait before executing a query resets
just in case the GPU is using them, and we have to do a CPU wait wait
for previous GPU jobs to complete before copying query results if the
user has asked us to do that. In the future, we may want to have
submission thread instead so we don't block the main thread in these
scenarios.
Because we now need to execute some tasks in the CPU as part of a
command buffer, this introduces the concept of job types, there is one
type for all GPU jobs, and then we have one type for each kind of job
that needs to execute in the CPU. CPU jobs are executed by the queue
in order just like GPU jobs, only that they are exclusively CPU tasks.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
2020-04-16 09:30:38 +01:00
|
|
|
.occlusionQueryPrecise = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.pipelineStatisticsQuery = false,
|
v3dv: initial descriptor set support
Focused on getting the basic UBO and SSBO cases implemented. So no
dynamic offset, push contanst, samplers, and so on.
This include a initial implementation for CreatedescriptorPool,
CreateDescriptorSetLayout, AllocateDescriptorSets,
UpdateDescriptorSets, CreatePipelineLayout, and CmdBindDescriptorSets.
Also introduces lowering vulkan intrinsics. For now just
vulkan_resource_index.
We also introduce a descriptor_map, in this case for the ubos and
ssbos, used to assign a index for each set/binding combination, that
would be used when filling back the details of the ubo or ssbo on
other places (like QUNIFORM_UBO_ADDR or QUNIFORM_SSBO_OFFSET).
Note that at this point we don't need a bo for the descriptor pool, so
descriptor sets are not getting a piece of it. That would likely
change as we start to support more descriptor set types.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
2020-01-20 14:29:38 +00:00
|
|
|
.vertexPipelineStoresAndAtomics = true,
|
|
|
|
.fragmentStoresAndAtomics = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.shaderTessellationAndGeometryPointSize = false,
|
|
|
|
.shaderImageGatherExtended = false,
|
2020-11-04 12:35:08 +00:00
|
|
|
.shaderStorageImageExtendedFormats = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.shaderStorageImageMultisample = false,
|
|
|
|
.shaderStorageImageReadWithoutFormat = false,
|
|
|
|
.shaderStorageImageWriteWithoutFormat = false,
|
|
|
|
.shaderUniformBufferArrayDynamicIndexing = false,
|
|
|
|
.shaderSampledImageArrayDynamicIndexing = false,
|
|
|
|
.shaderStorageBufferArrayDynamicIndexing = false,
|
|
|
|
.shaderStorageImageArrayDynamicIndexing = false,
|
2020-07-21 09:29:21 +01:00
|
|
|
.shaderClipDistance = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
.shaderCullDistance = false,
|
|
|
|
.shaderFloat64 = false,
|
|
|
|
.shaderInt64 = false,
|
|
|
|
.shaderInt16 = false,
|
|
|
|
.shaderResourceResidency = false,
|
|
|
|
.shaderResourceMinLod = false,
|
|
|
|
.sparseBinding = false,
|
|
|
|
.sparseResidencyBuffer = false,
|
|
|
|
.sparseResidencyImage2D = false,
|
|
|
|
.sparseResidencyImage3D = false,
|
|
|
|
.sparseResidency2Samples = false,
|
|
|
|
.sparseResidency4Samples = false,
|
|
|
|
.sparseResidency8Samples = false,
|
|
|
|
.sparseResidency16Samples = false,
|
|
|
|
.sparseResidencyAliased = false,
|
|
|
|
.variableMultisampleRate = false,
|
2020-05-26 11:05:43 +01:00
|
|
|
.inheritedQueries = true,
|
2019-11-29 09:58:53 +00:00
|
|
|
};
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
2020-01-15 07:48:07 +00:00
|
|
|
void
|
|
|
|
v3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
|
|
|
|
VkPhysicalDeviceFeatures2 *pFeatures)
|
|
|
|
{
|
|
|
|
v3dv_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
|
|
|
|
|
|
|
|
vk_foreach_struct(ext, pFeatures->pNext) {
|
|
|
|
switch (ext->sType) {
|
2020-11-12 15:35:31 +00:00
|
|
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
|
|
|
|
VkPhysicalDevicePrivateDataFeaturesEXT *features =
|
|
|
|
(VkPhysicalDevicePrivateDataFeaturesEXT *)ext;
|
|
|
|
features->privateData = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-01-15 07:48:07 +00:00
|
|
|
default:
|
|
|
|
v3dv_debug_ignored_stype(ext->sType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-04 00:32:11 +01:00
|
|
|
uint32_t
|
|
|
|
v3dv_physical_device_vendor_id(struct v3dv_physical_device *dev)
|
|
|
|
{
|
2020-10-05 09:44:59 +01:00
|
|
|
return 0x14E4; /* Broadcom */
|
2020-07-04 00:32:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-07-07 11:23:12 +01:00
|
|
|
#if using_v3d_simulator
|
|
|
|
static bool
|
|
|
|
get_i915_param(int fd, uint32_t param, int *value)
|
|
|
|
{
|
|
|
|
int tmp;
|
|
|
|
|
|
|
|
struct drm_i915_getparam gp = {
|
|
|
|
.param = param,
|
|
|
|
.value = &tmp,
|
|
|
|
};
|
|
|
|
|
|
|
|
int ret = drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
|
|
|
|
if (ret != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
*value = tmp;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-07-04 00:32:11 +01:00
|
|
|
uint32_t
|
|
|
|
v3dv_physical_device_device_id(struct v3dv_physical_device *dev)
|
|
|
|
{
|
2020-07-07 11:23:12 +01:00
|
|
|
#if using_v3d_simulator
|
|
|
|
int devid = 0;
|
|
|
|
|
|
|
|
if (!get_i915_param(dev->render_fd, I915_PARAM_CHIPSET_ID, &devid))
|
2020-10-05 09:44:59 +01:00
|
|
|
fprintf(stderr, "Error getting device_id\n");
|
2020-07-07 11:23:12 +01:00
|
|
|
|
|
|
|
return devid;
|
|
|
|
#else
|
2020-10-05 09:44:59 +01:00
|
|
|
return dev->devinfo.ver;
|
2020-07-07 11:23:12 +01:00
|
|
|
#endif
|
2020-07-04 00:32:11 +01:00
|
|
|
}
|
|
|
|
|
2019-11-25 15:29:12 +00:00
|
|
|
void
|
|
|
|
v3dv_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
|
|
|
|
VkPhysicalDeviceProperties *pProperties)
|
|
|
|
{
|
2019-11-28 11:47:19 +00:00
|
|
|
V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
|
|
|
|
|
|
|
|
const uint32_t page_size = 4096;
|
|
|
|
const uint32_t mem_size = compute_heap_size();
|
|
|
|
|
|
|
|
/* Per-stage limits */
|
|
|
|
const uint32_t max_samplers = 16;
|
|
|
|
const uint32_t max_uniform_buffers = 12;
|
2020-03-06 12:39:36 +00:00
|
|
|
const uint32_t max_storage_buffers = 12;
|
|
|
|
const uint32_t max_dynamic_storage_buffers = 6;
|
2019-11-28 11:47:19 +00:00
|
|
|
const uint32_t max_sampled_images = 16;
|
|
|
|
const uint32_t max_storage_images = 4;
|
2020-08-04 22:12:51 +01:00
|
|
|
const uint32_t max_input_attachments = 4;
|
|
|
|
assert(max_sampled_images + max_storage_images + max_input_attachments
|
|
|
|
<= V3D_MAX_TEXTURE_SAMPLERS);
|
2019-11-28 11:47:19 +00:00
|
|
|
|
|
|
|
const uint32_t max_varying_components = 16 * 4;
|
|
|
|
const uint32_t max_render_targets = 4;
|
|
|
|
|
|
|
|
const uint32_t v3d_coord_shift = 6;
|
|
|
|
|
2020-08-15 23:05:01 +01:00
|
|
|
const uint32_t v3d_point_line_granularity = 2.0f / (1 << v3d_coord_shift);
|
2019-11-28 11:47:19 +00:00
|
|
|
const uint32_t max_fb_size = 4096;
|
|
|
|
|
2020-02-21 08:26:47 +00:00
|
|
|
const VkSampleCountFlags supported_sample_counts =
|
|
|
|
VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
|
2019-11-28 11:47:19 +00:00
|
|
|
|
2020-10-29 10:55:23 +00:00
|
|
|
struct timespec clock_res;
|
|
|
|
clock_getres(CLOCK_MONOTONIC, &clock_res);
|
|
|
|
const float timestamp_period =
|
|
|
|
clock_res.tv_sec * 1000000000.0f + clock_res.tv_nsec;
|
|
|
|
|
2019-11-28 11:47:19 +00:00
|
|
|
/* FIXME: this will probably require an in-depth review */
|
|
|
|
VkPhysicalDeviceLimits limits = {
|
|
|
|
.maxImageDimension1D = 4096,
|
|
|
|
.maxImageDimension2D = 4096,
|
|
|
|
.maxImageDimension3D = 4096,
|
|
|
|
.maxImageDimensionCube = 4096,
|
|
|
|
.maxImageArrayLayers = 2048,
|
|
|
|
.maxTexelBufferElements = (1ul << 28),
|
2020-02-21 08:26:47 +00:00
|
|
|
.maxUniformBufferRange = (1ul << 27),
|
|
|
|
.maxStorageBufferRange = (1ul << 27),
|
2020-09-11 22:26:07 +01:00
|
|
|
.maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
|
2019-11-28 11:47:19 +00:00
|
|
|
.maxMemoryAllocationCount = mem_size / page_size,
|
|
|
|
.maxSamplerAllocationCount = 64 * 1024,
|
|
|
|
.bufferImageGranularity = 256, /* A cache line */
|
|
|
|
.sparseAddressSpaceSize = 0,
|
v3dv: initial descriptor set support
Focused on getting the basic UBO and SSBO cases implemented. So no
dynamic offset, push contanst, samplers, and so on.
This include a initial implementation for CreatedescriptorPool,
CreateDescriptorSetLayout, AllocateDescriptorSets,
UpdateDescriptorSets, CreatePipelineLayout, and CmdBindDescriptorSets.
Also introduces lowering vulkan intrinsics. For now just
vulkan_resource_index.
We also introduce a descriptor_map, in this case for the ubos and
ssbos, used to assign a index for each set/binding combination, that
would be used when filling back the details of the ubo or ssbo on
other places (like QUNIFORM_UBO_ADDR or QUNIFORM_SSBO_OFFSET).
Note that at this point we don't need a bo for the descriptor pool, so
descriptor sets are not getting a piece of it. That would likely
change as we start to support more descriptor set types.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
2020-01-20 14:29:38 +00:00
|
|
|
.maxBoundDescriptorSets = MAX_SETS,
|
2019-11-28 11:47:19 +00:00
|
|
|
.maxPerStageDescriptorSamplers = max_samplers,
|
|
|
|
.maxPerStageDescriptorUniformBuffers = max_uniform_buffers,
|
|
|
|
.maxPerStageDescriptorStorageBuffers = max_storage_buffers,
|
|
|
|
.maxPerStageDescriptorSampledImages = max_sampled_images,
|
|
|
|
.maxPerStageDescriptorStorageImages = max_storage_images,
|
2020-08-04 22:12:51 +01:00
|
|
|
.maxPerStageDescriptorInputAttachments = max_input_attachments,
|
2019-11-28 11:47:19 +00:00
|
|
|
.maxPerStageResources = 128,
|
|
|
|
|
|
|
|
/* We multiply some limits by 6 to account for all shader stages */
|
|
|
|
.maxDescriptorSetSamplers = 6 * max_samplers,
|
|
|
|
.maxDescriptorSetUniformBuffers = 6 * max_uniform_buffers,
|
|
|
|
.maxDescriptorSetUniformBuffersDynamic = 8,
|
|
|
|
.maxDescriptorSetStorageBuffers = 6 * max_storage_buffers,
|
2020-03-06 12:39:36 +00:00
|
|
|
.maxDescriptorSetStorageBuffersDynamic = 6 * max_dynamic_storage_buffers,
|
2019-11-28 11:47:19 +00:00
|
|
|
.maxDescriptorSetSampledImages = 6 * max_sampled_images,
|
|
|
|
.maxDescriptorSetStorageImages = 6 * max_storage_images,
|
|
|
|
.maxDescriptorSetInputAttachments = 4,
|
|
|
|
|
|
|
|
/* Vertex limits */
|
2020-07-31 00:11:39 +01:00
|
|
|
.maxVertexInputAttributes = MAX_VERTEX_ATTRIBS,
|
|
|
|
.maxVertexInputBindings = MAX_VBS,
|
2019-11-28 11:47:19 +00:00
|
|
|
.maxVertexInputAttributeOffset = 0xffffffff,
|
|
|
|
.maxVertexInputBindingStride = 0xffffffff,
|
|
|
|
.maxVertexOutputComponents = max_varying_components,
|
|
|
|
|
|
|
|
/* Tessellation limits */
|
|
|
|
.maxTessellationGenerationLevel = 0,
|
|
|
|
.maxTessellationPatchSize = 0,
|
|
|
|
.maxTessellationControlPerVertexInputComponents = 0,
|
|
|
|
.maxTessellationControlPerVertexOutputComponents = 0,
|
|
|
|
.maxTessellationControlPerPatchOutputComponents = 0,
|
|
|
|
.maxTessellationControlTotalOutputComponents = 0,
|
|
|
|
.maxTessellationEvaluationInputComponents = 0,
|
|
|
|
.maxTessellationEvaluationOutputComponents = 0,
|
|
|
|
|
|
|
|
/* Geometry limits */
|
|
|
|
.maxGeometryShaderInvocations = 0,
|
|
|
|
.maxGeometryInputComponents = 0,
|
|
|
|
.maxGeometryOutputComponents = 0,
|
|
|
|
.maxGeometryOutputVertices = 0,
|
|
|
|
.maxGeometryTotalOutputComponents = 0,
|
|
|
|
|
|
|
|
/* Fragment limits */
|
|
|
|
.maxFragmentInputComponents = max_varying_components,
|
|
|
|
.maxFragmentOutputAttachments = 4,
|
|
|
|
.maxFragmentDualSrcAttachments = 0,
|
|
|
|
.maxFragmentCombinedOutputResources = max_render_targets +
|
|
|
|
max_storage_buffers +
|
|
|
|
max_storage_images,
|
|
|
|
|
|
|
|
/* Compute limits */
|
|
|
|
.maxComputeSharedMemorySize = 16384,
|
|
|
|
.maxComputeWorkGroupCount = { 65535, 65535, 65535 },
|
|
|
|
.maxComputeWorkGroupInvocations = 256,
|
|
|
|
.maxComputeWorkGroupSize = { 256, 256, 256 },
|
|
|
|
|
|
|
|
.subPixelPrecisionBits = v3d_coord_shift,
|
|
|
|
.subTexelPrecisionBits = 8,
|
|
|
|
.mipmapPrecisionBits = 8,
|
|
|
|
.maxDrawIndexedIndexValue = 0x00ffffff,
|
|
|
|
.maxDrawIndirectCount = 0x7fffffff,
|
|
|
|
.maxSamplerLodBias = 14.0f,
|
|
|
|
.maxSamplerAnisotropy = 16.0f,
|
2019-12-28 10:59:32 +00:00
|
|
|
.maxViewports = MAX_VIEWPORTS,
|
2019-11-28 11:47:19 +00:00
|
|
|
.maxViewportDimensions = { max_fb_size, max_fb_size },
|
|
|
|
.viewportBoundsRange = { -2.0 * max_fb_size,
|
|
|
|
2.0 * max_fb_size - 1 },
|
|
|
|
.viewportSubPixelBits = 0,
|
|
|
|
.minMemoryMapAlignment = page_size,
|
2020-07-30 13:35:43 +01:00
|
|
|
.minTexelBufferOffsetAlignment = VC5_UIFBLOCK_SIZE,
|
v3dv/descriptor_set: support for array of ubo/ssbo
For that we include the array_index when asking for a ubo/ssbo index
from the descriptor_map.
Until now, array_index was not included, but the descriptor_map took
into account the array_size. This had the advantage that you only need
a entry on the descriptor map, and the index was properly return.
But this make it complex to get back the set, binding and array_index
back from the ubo/ssbo binding. So it was more easy to just add
array_index. Somehow now the "key" on the descriptor map is the
combination of (set, binding, array_index).
Note that this also make sense as the vulkan api identifies each array
index as a descriptor, so for example, from spec,
VkDescriptorSetLayoutBinding:descriptorCount
"descriptorCount is the number of descriptors contained in the
binding, accessed in a shader as an array"
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
2020-02-13 21:22:18 +00:00
|
|
|
.minUniformBufferOffsetAlignment = 32,
|
|
|
|
.minStorageBufferOffsetAlignment = 32,
|
2019-11-28 11:47:19 +00:00
|
|
|
.minTexelOffset = -8,
|
|
|
|
.maxTexelOffset = 7,
|
|
|
|
.minTexelGatherOffset = -8,
|
|
|
|
.maxTexelGatherOffset = 7,
|
|
|
|
.minInterpolationOffset = -0.5,
|
|
|
|
.maxInterpolationOffset = 0.5,
|
|
|
|
.subPixelInterpolationOffsetBits = v3d_coord_shift,
|
|
|
|
.maxFramebufferWidth = max_fb_size,
|
|
|
|
.maxFramebufferHeight = max_fb_size,
|
|
|
|
.maxFramebufferLayers = 256,
|
|
|
|
.framebufferColorSampleCounts = supported_sample_counts,
|
|
|
|
.framebufferDepthSampleCounts = supported_sample_counts,
|
|
|
|
.framebufferStencilSampleCounts = supported_sample_counts,
|
|
|
|
.framebufferNoAttachmentsSampleCounts = supported_sample_counts,
|
|
|
|
.maxColorAttachments = max_render_targets,
|
|
|
|
.sampledImageColorSampleCounts = supported_sample_counts,
|
|
|
|
.sampledImageIntegerSampleCounts = supported_sample_counts,
|
|
|
|
.sampledImageDepthSampleCounts = supported_sample_counts,
|
|
|
|
.sampledImageStencilSampleCounts = supported_sample_counts,
|
|
|
|
.storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
.maxSampleMaskWords = 1,
|
2020-10-29 10:55:23 +00:00
|
|
|
.timestampComputeAndGraphics = true,
|
|
|
|
.timestampPeriod = timestamp_period,
|
2020-07-21 09:29:21 +01:00
|
|
|
.maxClipDistances = 8,
|
2019-11-28 11:47:19 +00:00
|
|
|
.maxCullDistances = 0,
|
2020-07-21 09:29:21 +01:00
|
|
|
.maxCombinedClipAndCullDistances = 8,
|
2019-11-28 11:47:19 +00:00
|
|
|
.discreteQueuePriorities = 2,
|
2020-08-15 23:05:01 +01:00
|
|
|
.pointSizeRange = { v3d_point_line_granularity,
|
|
|
|
V3D_MAX_POINT_SIZE },
|
|
|
|
.lineWidthRange = { 1.0f, V3D_MAX_LINE_WIDTH },
|
|
|
|
.pointSizeGranularity = v3d_point_line_granularity,
|
|
|
|
.lineWidthGranularity = v3d_point_line_granularity,
|
2019-11-28 11:47:19 +00:00
|
|
|
.strictLines = true,
|
|
|
|
.standardSampleLocations = false,
|
|
|
|
.optimalBufferCopyOffsetAlignment = 32,
|
|
|
|
.optimalBufferCopyRowPitchAlignment = 32,
|
|
|
|
.nonCoherentAtomSize = 256,
|
|
|
|
};
|
|
|
|
|
|
|
|
*pProperties = (VkPhysicalDeviceProperties) {
|
|
|
|
.apiVersion = v3dv_physical_device_api_version(pdevice),
|
|
|
|
.driverVersion = vk_get_driver_version(),
|
2020-07-04 00:32:11 +01:00
|
|
|
.vendorID = v3dv_physical_device_vendor_id(pdevice),
|
|
|
|
.deviceID = v3dv_physical_device_device_id(pdevice),
|
2019-11-28 11:47:19 +00:00
|
|
|
.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
|
|
|
|
.limits = limits,
|
|
|
|
.sparseProperties = { 0 },
|
|
|
|
};
|
|
|
|
|
|
|
|
snprintf(pProperties->deviceName, sizeof(pProperties->deviceName),
|
|
|
|
"%s", pdevice->name);
|
|
|
|
memcpy(pProperties->pipelineCacheUUID,
|
|
|
|
pdevice->pipeline_cache_uuid, VK_UUID_SIZE);
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
2020-01-15 07:48:07 +00:00
|
|
|
void
|
|
|
|
v3dv_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
|
|
|
|
VkPhysicalDeviceProperties2 *pProperties)
|
|
|
|
{
|
2020-10-05 09:44:59 +01:00
|
|
|
V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
|
|
|
|
|
2020-01-15 07:48:07 +00:00
|
|
|
v3dv_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
|
|
|
|
|
|
|
|
vk_foreach_struct(ext, pProperties->pNext) {
|
|
|
|
switch (ext->sType) {
|
2020-01-15 09:00:11 +00:00
|
|
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
|
|
|
|
VkPhysicalDeviceIDProperties *id_props =
|
|
|
|
(VkPhysicalDeviceIDProperties *)ext;
|
2020-10-05 09:44:59 +01:00
|
|
|
memcpy(id_props->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
|
|
|
|
memcpy(id_props->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
|
2020-01-15 09:00:11 +00:00
|
|
|
/* The LUID is for Windows. */
|
|
|
|
id_props->deviceLUIDValid = false;
|
|
|
|
break;
|
|
|
|
}
|
2020-11-09 10:31:06 +00:00
|
|
|
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT:
|
|
|
|
/* Do nothing, not even logging. This is a non-PCI device, so we will
|
|
|
|
* never provide this extension.
|
|
|
|
*/
|
|
|
|
break;
|
2020-01-15 07:48:07 +00:00
|
|
|
default:
|
|
|
|
v3dv_debug_ignored_stype(ext->sType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-29 10:33:37 +00:00
|
|
|
/* We support exactly one queue family. */
|
|
|
|
static const VkQueueFamilyProperties
|
|
|
|
v3dv_queue_family_properties = {
|
|
|
|
.queueFlags = VK_QUEUE_GRAPHICS_BIT |
|
|
|
|
VK_QUEUE_COMPUTE_BIT |
|
|
|
|
VK_QUEUE_TRANSFER_BIT,
|
|
|
|
.queueCount = 1,
|
2020-10-29 10:55:23 +00:00
|
|
|
.timestampValidBits = 64,
|
2019-11-29 10:33:37 +00:00
|
|
|
.minImageTransferGranularity = { 1, 1, 1 },
|
|
|
|
};
|
|
|
|
|
2019-11-25 15:29:12 +00:00
|
|
|
void
|
|
|
|
v3dv_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
|
|
|
|
uint32_t *pCount,
|
|
|
|
VkQueueFamilyProperties *pQueueFamilyProperties)
|
|
|
|
{
|
2019-11-29 10:33:37 +00:00
|
|
|
VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pCount);
|
|
|
|
|
|
|
|
vk_outarray_append(&out, p) {
|
|
|
|
*p = v3dv_queue_family_properties;
|
|
|
|
}
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
2020-01-15 07:48:07 +00:00
|
|
|
void
|
|
|
|
v3dv_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
|
|
|
|
uint32_t *pQueueFamilyPropertyCount,
|
|
|
|
VkQueueFamilyProperties2 *pQueueFamilyProperties)
|
|
|
|
{
|
|
|
|
VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
|
|
|
|
|
|
|
|
vk_outarray_append(&out, p) {
|
|
|
|
p->queueFamilyProperties = v3dv_queue_family_properties;
|
|
|
|
|
|
|
|
vk_foreach_struct(s, p->pNext) {
|
|
|
|
v3dv_debug_ignored_stype(s->sType);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-25 15:29:12 +00:00
|
|
|
void
|
|
|
|
v3dv_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
|
|
|
|
VkPhysicalDeviceMemoryProperties *pMemoryProperties)
|
|
|
|
{
|
2019-12-04 09:25:21 +00:00
|
|
|
V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice);
|
|
|
|
*pMemoryProperties = device->memory;
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
2020-01-15 07:48:07 +00:00
|
|
|
void
|
|
|
|
v3dv_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,
|
|
|
|
VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
|
|
|
|
{
|
|
|
|
v3dv_GetPhysicalDeviceMemoryProperties(physicalDevice,
|
|
|
|
&pMemoryProperties->memoryProperties);
|
|
|
|
|
|
|
|
vk_foreach_struct(ext, pMemoryProperties->pNext) {
|
|
|
|
switch (ext->sType) {
|
|
|
|
default:
|
|
|
|
v3dv_debug_ignored_stype(ext->sType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-25 15:29:12 +00:00
|
|
|
|
|
|
|
PFN_vkVoidFunction
|
|
|
|
v3dv_GetInstanceProcAddr(VkInstance _instance,
|
|
|
|
const char *pName)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
|
2021-01-27 23:21:38 +00:00
|
|
|
return vk_instance_get_proc_addr(&instance->vk,
|
|
|
|
&v3dv_instance_entrypoints,
|
|
|
|
pName);
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
2021-01-27 23:21:38 +00:00
|
|
|
return vk_instance_get_physical_device_proc_addr(&instance->vk, pName);
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
2019-12-03 08:10:10 +00:00
|
|
|
VkResult
|
|
|
|
v3dv_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
|
|
|
|
VkLayerProperties *pProperties)
|
|
|
|
{
|
|
|
|
if (pProperties == NULL) {
|
|
|
|
*pPropertyCount = 0;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
|
|
|
|
uint32_t *pPropertyCount,
|
|
|
|
VkLayerProperties *pProperties)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
|
|
|
|
|
|
|
|
if (pProperties == NULL) {
|
|
|
|
*pPropertyCount = 0;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2021-01-27 22:45:28 +00:00
|
|
|
return vk_error((struct v3dv_instance*) physical_device->vk.instance,
|
|
|
|
VK_ERROR_LAYER_NOT_PRESENT);
|
2019-12-03 08:10:10 +00:00
|
|
|
}
|
|
|
|
|
2019-11-29 11:44:40 +00:00
|
|
|
static VkResult
|
|
|
|
queue_init(struct v3dv_device *device, struct v3dv_queue *queue)
|
|
|
|
{
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_object_base_init(&device->vk, &queue->base, VK_OBJECT_TYPE_QUEUE);
|
2019-11-29 11:44:40 +00:00
|
|
|
queue->device = device;
|
|
|
|
queue->flags = 0;
|
2020-09-18 17:02:05 +01:00
|
|
|
queue->noop_job = NULL;
|
2020-05-18 09:41:11 +01:00
|
|
|
list_inithead(&queue->submit_wait_list);
|
|
|
|
pthread_mutex_init(&queue->mutex, NULL);
|
2019-11-29 11:44:40 +00:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
queue_finish(struct v3dv_queue *queue)
|
|
|
|
{
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_object_base_finish(&queue->base);
|
2020-05-18 09:41:11 +01:00
|
|
|
assert(list_is_empty(&queue->submit_wait_list));
|
2020-09-18 17:02:05 +01:00
|
|
|
if (queue->noop_job)
|
|
|
|
v3dv_job_destroy(queue->noop_job);
|
2020-05-18 09:41:11 +01:00
|
|
|
pthread_mutex_destroy(&queue->mutex);
|
2019-11-29 11:44:40 +00:00
|
|
|
}
|
|
|
|
|
2020-03-31 12:06:55 +01:00
|
|
|
static void
|
|
|
|
init_device_meta(struct v3dv_device *device)
|
|
|
|
{
|
|
|
|
mtx_init(&device->meta.mtx, mtx_plain);
|
2020-08-26 07:38:41 +01:00
|
|
|
v3dv_meta_clear_init(device);
|
|
|
|
v3dv_meta_blit_init(device);
|
2020-11-12 09:43:54 +00:00
|
|
|
v3dv_meta_texel_buffer_copy_init(device);
|
2020-08-25 13:25:45 +01:00
|
|
|
}
|
|
|
|
|
2020-03-31 12:06:55 +01:00
|
|
|
static void
|
|
|
|
destroy_device_meta(struct v3dv_device *device)
|
|
|
|
{
|
|
|
|
mtx_destroy(&device->meta.mtx);
|
2020-08-26 07:38:41 +01:00
|
|
|
v3dv_meta_clear_finish(device);
|
|
|
|
v3dv_meta_blit_finish(device);
|
2020-11-12 09:43:54 +00:00
|
|
|
v3dv_meta_texel_buffer_copy_finish(device);
|
2020-03-31 12:06:55 +01:00
|
|
|
}
|
|
|
|
|
2019-11-25 15:29:12 +00:00
|
|
|
VkResult
|
|
|
|
v3dv_CreateDevice(VkPhysicalDevice physicalDevice,
|
|
|
|
const VkDeviceCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkDevice *pDevice)
|
|
|
|
{
|
2019-11-29 11:44:40 +00:00
|
|
|
V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
|
2021-01-27 22:45:28 +00:00
|
|
|
struct v3dv_instance *instance = (struct v3dv_instance*) physical_device->vk.instance;
|
2019-11-29 11:44:40 +00:00
|
|
|
VkResult result;
|
|
|
|
struct v3dv_device *device;
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
|
|
|
|
|
|
|
|
/* Check enabled features */
|
|
|
|
if (pCreateInfo->pEnabledFeatures) {
|
|
|
|
VkPhysicalDeviceFeatures supported_features;
|
|
|
|
v3dv_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
|
|
|
|
VkBool32 *supported_feature = (VkBool32 *)&supported_features;
|
|
|
|
VkBool32 *enabled_feature = (VkBool32 *)pCreateInfo->pEnabledFeatures;
|
|
|
|
unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
|
|
|
|
for (uint32_t i = 0; i < num_features; i++) {
|
|
|
|
if (enabled_feature[i] && !supported_feature[i])
|
|
|
|
return vk_error(instance, VK_ERROR_FEATURE_NOT_PRESENT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check requested queues (we only expose one queue ) */
|
|
|
|
assert(pCreateInfo->queueCreateInfoCount == 1);
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
|
|
|
|
assert(pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex == 0);
|
|
|
|
assert(pCreateInfo->pQueueCreateInfos[i].queueCount == 1);
|
|
|
|
if (pCreateInfo->pQueueCreateInfos[i].flags != 0)
|
|
|
|
return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
|
|
|
|
}
|
|
|
|
|
2021-01-27 22:45:28 +00:00
|
|
|
device = vk_zalloc2(&physical_device->vk.instance->alloc, pAllocator,
|
2019-11-29 11:44:40 +00:00
|
|
|
sizeof(*device), 8,
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
|
|
|
if (!device)
|
|
|
|
return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
2021-01-27 23:21:38 +00:00
|
|
|
struct vk_device_dispatch_table dispatch_table;
|
|
|
|
vk_device_dispatch_table_from_entrypoints(&dispatch_table,
|
|
|
|
&v3dv_device_entrypoints, true);
|
|
|
|
result = vk_device_init(&device->vk, &physical_device->vk,
|
2021-01-29 18:30:34 +00:00
|
|
|
&dispatch_table, pCreateInfo, pAllocator);
|
2021-01-24 15:26:24 +00:00
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
vk_free(&device->vk.alloc, device);
|
|
|
|
return vk_error(instance, result);
|
|
|
|
}
|
2020-11-12 15:30:41 +00:00
|
|
|
|
2019-11-29 11:44:40 +00:00
|
|
|
device->instance = instance;
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
device->pdevice = physical_device;
|
2019-11-29 11:44:40 +00:00
|
|
|
|
|
|
|
if (pAllocator)
|
2020-11-12 15:30:41 +00:00
|
|
|
device->vk.alloc = *pAllocator;
|
2019-11-29 11:44:40 +00:00
|
|
|
else
|
2021-01-27 22:45:28 +00:00
|
|
|
device->vk.alloc = physical_device->vk.instance->alloc;
|
2019-11-29 11:44:40 +00:00
|
|
|
|
2020-05-18 09:41:11 +01:00
|
|
|
pthread_mutex_init(&device->mutex, NULL);
|
|
|
|
|
2019-11-29 11:44:40 +00:00
|
|
|
result = queue_init(device, &device->queue);
|
|
|
|
if (result != VK_SUCCESS)
|
2020-01-20 09:45:06 +00:00
|
|
|
goto fail;
|
2019-11-29 11:44:40 +00:00
|
|
|
|
|
|
|
device->devinfo = physical_device->devinfo;
|
|
|
|
|
2020-08-27 09:48:29 +01:00
|
|
|
if (pCreateInfo->pEnabledFeatures) {
|
|
|
|
memcpy(&device->features, pCreateInfo->pEnabledFeatures,
|
|
|
|
sizeof(device->features));
|
|
|
|
}
|
|
|
|
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
int ret = drmSyncobjCreate(physical_device->render_fd,
|
2020-01-13 07:53:26 +00:00
|
|
|
DRM_SYNCOBJ_CREATE_SIGNALED,
|
|
|
|
&device->last_job_sync);
|
|
|
|
if (ret) {
|
|
|
|
result = VK_ERROR_INITIALIZATION_FAILED;
|
2020-01-20 09:45:06 +00:00
|
|
|
goto fail;
|
2020-01-13 07:53:26 +00:00
|
|
|
}
|
|
|
|
|
2020-03-31 12:06:55 +01:00
|
|
|
init_device_meta(device);
|
v3dv/bo: adding a BO cache
Heavily based on the already existing for the v3d OpenGL driver, but
without references, and with some extra OOM checks (Vulkan CTS has
several OOM tests).
With this commit v3dv_bo_alloc and v3dv_bo_free became frontends to
the bo_cache. The former tries to get a BO from the cache if possible,
and the latter stores the BO on the cache if possible. The former also
adds a new parameter to point if the BO to allocate is private.
As v3d we are only caching private BOs, those created by the driver
for internal use (like CLs, tile_alloc, etc). They are the ones with
the highest change of being reused (for example, CL BOs are always
4KB, so they can always be reused). User-created BOs can have any
size, including some very large ones for buffers and images, which
makes them far less likely to be reused and would add a lot of memory
pressure if we decided to cache them.
In any case, in practice, we found that we could get a performance
improvement by caching also user-created BOs, but that would need more
care and an analysis to decide which ones makes sense. Would also
require to change how the cached BOs are stored by size. Right now
there are an array of list_head, that doesn't work well with big
BOs. If done, that would be handled on a separate commit.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
2020-06-05 11:21:54 +01:00
|
|
|
v3dv_bo_cache_init(device);
|
2020-07-22 01:08:06 +01:00
|
|
|
v3dv_pipeline_cache_init(&device->default_pipeline_cache, device,
|
2020-09-20 21:54:33 +01:00
|
|
|
device->instance->default_pipeline_cache_enabled);
|
2019-11-29 11:44:40 +00:00
|
|
|
|
|
|
|
*pDevice = v3dv_device_to_handle(device);
|
2019-11-25 15:29:12 +00:00
|
|
|
|
|
|
|
return VK_SUCCESS;
|
2019-11-29 11:44:40 +00:00
|
|
|
|
2020-01-20 09:45:06 +00:00
|
|
|
fail:
|
2021-01-23 10:29:04 +00:00
|
|
|
vk_device_finish(&device->vk);
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_free(&device->vk.alloc, device);
|
2019-11-29 11:44:40 +00:00
|
|
|
|
|
|
|
return result;
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_DestroyDevice(VkDevice _device,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
{
|
2019-11-29 11:44:40 +00:00
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
2020-01-13 07:53:26 +00:00
|
|
|
|
2020-03-13 10:35:06 +00:00
|
|
|
v3dv_DeviceWaitIdle(_device);
|
2019-11-29 11:44:40 +00:00
|
|
|
queue_finish(&device->queue);
|
2020-05-18 09:41:11 +01:00
|
|
|
pthread_mutex_destroy(&device->mutex);
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
drmSyncobjDestroy(device->pdevice->render_fd, device->last_job_sync);
|
2020-03-31 12:06:55 +01:00
|
|
|
destroy_device_meta(device);
|
2020-07-22 01:08:06 +01:00
|
|
|
v3dv_pipeline_cache_finish(&device->default_pipeline_cache);
|
|
|
|
|
|
|
|
/* Bo cache should be removed the last, as any other object could be
|
|
|
|
* freeing their private bos
|
|
|
|
*/
|
v3dv/bo: adding a BO cache
Heavily based on the already existing for the v3d OpenGL driver, but
without references, and with some extra OOM checks (Vulkan CTS has
several OOM tests).
With this commit v3dv_bo_alloc and v3dv_bo_free became frontends to
the bo_cache. The former tries to get a BO from the cache if possible,
and the latter stores the BO on the cache if possible. The former also
adds a new parameter to point if the BO to allocate is private.
As v3d we are only caching private BOs, those created by the driver
for internal use (like CLs, tile_alloc, etc). They are the ones with
the highest change of being reused (for example, CL BOs are always
4KB, so they can always be reused). User-created BOs can have any
size, including some very large ones for buffers and images, which
makes them far less likely to be reused and would add a lot of memory
pressure if we decided to cache them.
In any case, in practice, we found that we could get a performance
improvement by caching also user-created BOs, but that would need more
care and an analysis to decide which ones makes sense. Would also
require to change how the cached BOs are stored by size. Right now
there are an array of list_head, that doesn't work well with big
BOs. If done, that would be handled on a separate commit.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
2020-06-05 11:21:54 +01:00
|
|
|
v3dv_bo_cache_destroy(device);
|
2020-01-20 09:45:06 +00:00
|
|
|
|
2021-01-23 10:29:04 +00:00
|
|
|
vk_device_finish(&device->vk);
|
2019-12-17 07:48:52 +00:00
|
|
|
vk_free2(&default_alloc, pAllocator, device);
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_GetDeviceQueue(VkDevice _device,
|
2019-12-02 08:49:50 +00:00
|
|
|
uint32_t queueFamilyIndex,
|
2019-11-25 15:29:12 +00:00
|
|
|
uint32_t queueIndex,
|
|
|
|
VkQueue *pQueue)
|
|
|
|
{
|
2019-12-02 08:49:50 +00:00
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
|
|
|
|
assert(queueIndex == 0);
|
|
|
|
assert(queueFamilyIndex == 0);
|
|
|
|
|
|
|
|
*pQueue = v3dv_queue_to_handle(&device->queue);
|
2019-11-25 15:29:12 +00:00
|
|
|
}
|
2019-11-27 10:24:22 +00:00
|
|
|
|
2019-12-03 08:15:43 +00:00
|
|
|
VkResult
|
|
|
|
v3dv_DeviceWaitIdle(VkDevice _device)
|
|
|
|
{
|
2020-01-13 07:53:26 +00:00
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
2020-05-18 09:41:11 +01:00
|
|
|
return v3dv_QueueWaitIdle(v3dv_queue_to_handle(&device->queue));
|
2020-02-21 15:18:17 +00:00
|
|
|
}
|
|
|
|
|
2019-12-04 09:39:01 +00:00
|
|
|
static VkResult
|
|
|
|
device_alloc(struct v3dv_device *device,
|
|
|
|
struct v3dv_device_memory *mem,
|
|
|
|
VkDeviceSize size)
|
|
|
|
{
|
|
|
|
/* Our kernel interface is 32-bit */
|
2020-06-29 10:56:48 +01:00
|
|
|
if (size > UINT32_MAX)
|
|
|
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
|
|
|
|
v3dv/bo: adding a BO cache
Heavily based on the already existing for the v3d OpenGL driver, but
without references, and with some extra OOM checks (Vulkan CTS has
several OOM tests).
With this commit v3dv_bo_alloc and v3dv_bo_free became frontends to
the bo_cache. The former tries to get a BO from the cache if possible,
and the latter stores the BO on the cache if possible. The former also
adds a new parameter to point if the BO to allocate is private.
As v3d we are only caching private BOs, those created by the driver
for internal use (like CLs, tile_alloc, etc). They are the ones with
the highest change of being reused (for example, CL BOs are always
4KB, so they can always be reused). User-created BOs can have any
size, including some very large ones for buffers and images, which
makes them far less likely to be reused and would add a lot of memory
pressure if we decided to cache them.
In any case, in practice, we found that we could get a performance
improvement by caching also user-created BOs, but that would need more
care and an analysis to decide which ones makes sense. Would also
require to change how the cached BOs are stored by size. Right now
there are an array of list_head, that doesn't work well with big
BOs. If done, that would be handled on a separate commit.
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
2020-06-05 11:21:54 +01:00
|
|
|
mem->bo = v3dv_bo_alloc(device, size, "device_alloc", false);
|
2019-12-12 10:02:04 +00:00
|
|
|
if (!mem->bo)
|
2019-12-04 09:39:01 +00:00
|
|
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
2020-06-29 10:56:48 +01:00
|
|
|
|
2019-12-04 09:39:01 +00:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-09-11 11:20:20 +01:00
|
|
|
static void
|
|
|
|
device_free_wsi_dumb(int32_t display_fd, int32_t dumb_handle)
|
|
|
|
{
|
|
|
|
assert(display_fd != -1);
|
|
|
|
if (dumb_handle < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
struct drm_mode_destroy_dumb destroy_dumb = {
|
|
|
|
.handle = dumb_handle,
|
|
|
|
};
|
|
|
|
v3dv_ioctl(display_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
|
|
|
|
}
|
|
|
|
|
2019-12-04 09:58:05 +00:00
|
|
|
static void
|
|
|
|
device_free(struct v3dv_device *device, struct v3dv_device_memory *mem)
|
|
|
|
{
|
2020-09-11 11:20:20 +01:00
|
|
|
/* If this memory allocation was for WSI, then we need to use the
|
|
|
|
* display device to free the allocated dumb BO.
|
|
|
|
*/
|
|
|
|
if (mem->is_for_wsi) {
|
|
|
|
assert(mem->has_bo_ownership);
|
|
|
|
device_free_wsi_dumb(device->instance->physicalDevice.display_fd,
|
|
|
|
mem->bo->dumb_handle);
|
|
|
|
}
|
|
|
|
|
2020-06-23 12:36:15 +01:00
|
|
|
if (mem->has_bo_ownership)
|
|
|
|
v3dv_bo_free(device, mem->bo);
|
|
|
|
else if (mem->bo)
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_free(&device->vk.alloc, mem->bo);
|
2019-12-04 09:58:05 +00:00
|
|
|
}
|
|
|
|
|
2020-03-11 11:56:34 +00:00
|
|
|
static void
|
|
|
|
device_unmap(struct v3dv_device *device, struct v3dv_device_memory *mem)
|
|
|
|
{
|
|
|
|
assert(mem && mem->bo->map && mem->bo->map_size > 0);
|
|
|
|
v3dv_bo_unmap(device, mem->bo);
|
|
|
|
}
|
|
|
|
|
2019-12-04 11:21:35 +00:00
|
|
|
static VkResult
|
2020-06-17 11:15:42 +01:00
|
|
|
device_map(struct v3dv_device *device, struct v3dv_device_memory *mem)
|
2019-12-04 11:21:35 +00:00
|
|
|
{
|
2020-03-11 11:56:34 +00:00
|
|
|
assert(mem && mem->bo);
|
|
|
|
|
2019-12-04 11:21:35 +00:00
|
|
|
/* From the spec:
|
|
|
|
*
|
|
|
|
* "After a successful call to vkMapMemory the memory object memory is
|
|
|
|
* considered to be currently host mapped. It is an application error to
|
|
|
|
* call vkMapMemory on a memory object that is already host mapped."
|
2020-03-11 11:56:34 +00:00
|
|
|
*
|
|
|
|
* We are not concerned with this ourselves (validation layers should
|
|
|
|
* catch these errors and warn users), however, the driver may internally
|
2020-06-17 11:15:42 +01:00
|
|
|
* map things (for example for debug CLIF dumps or some CPU-side operations)
|
|
|
|
* so by the time the user calls here the buffer might already been mapped
|
|
|
|
* internally by the driver.
|
2019-12-04 11:21:35 +00:00
|
|
|
*/
|
2020-06-17 11:15:42 +01:00
|
|
|
if (mem->bo->map) {
|
|
|
|
assert(mem->bo->map_size == mem->bo->size);
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
2019-12-04 11:21:35 +00:00
|
|
|
|
2020-06-17 11:15:42 +01:00
|
|
|
bool ok = v3dv_bo_map(device, mem->bo, mem->bo->size);
|
2019-12-10 11:00:49 +00:00
|
|
|
if (!ok)
|
2019-12-04 11:21:35 +00:00
|
|
|
return VK_ERROR_MEMORY_MAP_FAILED;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-01-15 10:32:09 +00:00
|
|
|
static VkResult
|
|
|
|
device_import_bo(struct v3dv_device *device,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
int fd, uint64_t size,
|
|
|
|
struct v3dv_bo **bo)
|
|
|
|
{
|
|
|
|
VkResult result;
|
|
|
|
|
2020-11-12 15:30:41 +00:00
|
|
|
*bo = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(struct v3dv_bo), 8,
|
2020-01-15 10:32:09 +00:00
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
if (*bo == NULL) {
|
|
|
|
result = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
off_t real_size = lseek(fd, 0, SEEK_END);
|
|
|
|
lseek(fd, 0, SEEK_SET);
|
|
|
|
if (real_size < 0 || (uint64_t) real_size < size) {
|
|
|
|
result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
int render_fd = device->pdevice->render_fd;
|
|
|
|
assert(render_fd >= 0);
|
|
|
|
|
2020-01-15 10:32:09 +00:00
|
|
|
int ret;
|
|
|
|
uint32_t handle;
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
ret = drmPrimeFDToHandle(render_fd, fd, &handle);
|
2020-01-15 10:32:09 +00:00
|
|
|
if (ret) {
|
|
|
|
result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct drm_v3d_get_bo_offset get_offset = {
|
|
|
|
.handle = handle,
|
|
|
|
};
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
ret = v3dv_ioctl(render_fd, DRM_IOCTL_V3D_GET_BO_OFFSET, &get_offset);
|
2020-01-15 10:32:09 +00:00
|
|
|
if (ret) {
|
|
|
|
result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
assert(get_offset.offset != 0);
|
|
|
|
|
2020-11-04 09:39:12 +00:00
|
|
|
v3dv_bo_init(*bo, handle, size, get_offset.offset, "import", false);
|
2020-01-15 10:32:09 +00:00
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
fail:
|
|
|
|
if (*bo) {
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_free2(&device->vk.alloc, pAllocator, *bo);
|
2020-01-15 10:32:09 +00:00
|
|
|
*bo = NULL;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-01-23 10:24:05 +00:00
|
|
|
static VkResult
|
|
|
|
device_alloc_for_wsi(struct v3dv_device *device,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
struct v3dv_device_memory *mem,
|
|
|
|
VkDeviceSize size)
|
|
|
|
{
|
|
|
|
/* In the simulator we can get away with a regular allocation since both
|
|
|
|
* allocation and rendering happen in the same DRM render node. On actual
|
|
|
|
* hardware we need to allocate our winsys BOs on the vc4 display device
|
|
|
|
* and import them into v3d.
|
|
|
|
*/
|
|
|
|
#if using_v3d_simulator
|
|
|
|
return device_alloc(device, mem, size);
|
|
|
|
#else
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
/* If we are allocating for WSI we should have a swapchain and thus,
|
|
|
|
* we should've initialized the display device. However, Zink doesn't
|
|
|
|
* use swapchains, so in that case we can get here without acquiring the
|
|
|
|
* display device and we need to do it now.
|
|
|
|
*/
|
|
|
|
VkResult result;
|
|
|
|
struct v3dv_instance *instance = device->instance;
|
|
|
|
struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
|
|
|
|
if (unlikely(pdevice->display_fd < 0)) {
|
2020-11-16 08:50:22 +00:00
|
|
|
result = v3dv_physical_device_acquire_display(instance, pdevice, NULL);
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
assert(pdevice->display_fd != -1);
|
|
|
|
|
2020-09-11 11:20:20 +01:00
|
|
|
mem->is_for_wsi = true;
|
|
|
|
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
int display_fd = pdevice->display_fd;
|
2020-01-23 10:24:05 +00:00
|
|
|
struct drm_mode_create_dumb create_dumb = {
|
|
|
|
.width = 1024, /* one page */
|
|
|
|
.height = align(size, 4096) / 4096,
|
|
|
|
.bpp = util_format_get_blocksizebits(PIPE_FORMAT_RGBA8888_UNORM),
|
|
|
|
};
|
|
|
|
|
|
|
|
int err;
|
|
|
|
err = v3dv_ioctl(display_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
|
|
|
|
if (err < 0)
|
|
|
|
goto fail_create;
|
|
|
|
|
|
|
|
int fd;
|
|
|
|
err =
|
|
|
|
drmPrimeHandleToFD(display_fd, create_dumb.handle, O_CLOEXEC, &fd);
|
|
|
|
if (err < 0)
|
|
|
|
goto fail_export;
|
|
|
|
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
result = device_import_bo(device, pAllocator, fd, size, &mem->bo);
|
2020-01-23 10:24:05 +00:00
|
|
|
close(fd);
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
goto fail_import;
|
|
|
|
|
2020-09-11 11:20:20 +01:00
|
|
|
mem->bo->dumb_handle = create_dumb.handle;
|
2020-01-23 10:24:05 +00:00
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
fail_import:
|
2020-09-11 11:20:20 +01:00
|
|
|
fail_export:
|
|
|
|
device_free_wsi_dumb(display_fd, create_dumb.handle);
|
2020-01-23 10:24:05 +00:00
|
|
|
|
|
|
|
fail_create:
|
|
|
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-11-27 21:08:51 +00:00
|
|
|
VkResult
|
|
|
|
v3dv_AllocateMemory(VkDevice _device,
|
|
|
|
const VkMemoryAllocateInfo *pAllocateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkDeviceMemory *pMem)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
struct v3dv_device_memory *mem;
|
2019-12-04 09:39:01 +00:00
|
|
|
struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
|
2019-11-27 21:08:51 +00:00
|
|
|
|
|
|
|
assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
|
|
|
|
|
|
|
|
/* The Vulkan 1.0.33 spec says "allocationSize must be greater than 0". */
|
|
|
|
assert(pAllocateInfo->allocationSize > 0);
|
|
|
|
|
2020-11-12 15:30:41 +00:00
|
|
|
mem = vk_object_zalloc(&device->vk, pAllocator, sizeof(*mem),
|
|
|
|
VK_OBJECT_TYPE_DEVICE_MEMORY);
|
2019-11-27 21:08:51 +00:00
|
|
|
if (mem == NULL)
|
|
|
|
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
2019-12-04 09:39:01 +00:00
|
|
|
assert(pAllocateInfo->memoryTypeIndex < pdevice->memory.memoryTypeCount);
|
|
|
|
mem->type = &pdevice->memory.memoryTypes[pAllocateInfo->memoryTypeIndex];
|
2020-06-23 12:36:15 +01:00
|
|
|
mem->has_bo_ownership = true;
|
2020-09-11 11:20:20 +01:00
|
|
|
mem->is_for_wsi = false;
|
2019-11-27 21:08:51 +00:00
|
|
|
|
2020-01-23 10:24:05 +00:00
|
|
|
const struct wsi_memory_allocate_info *wsi_info = NULL;
|
2020-01-15 10:32:09 +00:00
|
|
|
const VkImportMemoryFdInfoKHR *fd_info = NULL;
|
|
|
|
vk_foreach_struct_const(ext, pAllocateInfo->pNext) {
|
2020-01-23 10:24:05 +00:00
|
|
|
switch ((unsigned)ext->sType) {
|
|
|
|
case VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA:
|
|
|
|
wsi_info = (void *)ext;
|
|
|
|
break;
|
2020-01-15 10:32:09 +00:00
|
|
|
case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR:
|
|
|
|
fd_info = (void *)ext;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v3dv_debug_ignored_stype(ext->sType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult result = VK_SUCCESS;
|
2020-01-23 10:24:05 +00:00
|
|
|
if (wsi_info) {
|
|
|
|
result = device_alloc_for_wsi(device, pAllocator, mem,
|
|
|
|
pAllocateInfo->allocationSize);
|
|
|
|
} else if (fd_info && fd_info->handleType) {
|
2020-01-15 10:32:09 +00:00
|
|
|
assert(fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
|
|
|
|
fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
|
|
|
|
result = device_import_bo(device, pAllocator,
|
|
|
|
fd_info->fd, pAllocateInfo->allocationSize,
|
|
|
|
&mem->bo);
|
2020-06-23 12:36:15 +01:00
|
|
|
mem->has_bo_ownership = false;
|
2020-01-15 10:32:09 +00:00
|
|
|
if (result == VK_SUCCESS)
|
|
|
|
close(fd_info->fd);
|
|
|
|
} else {
|
|
|
|
result = device_alloc(device, mem, pAllocateInfo->allocationSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result != VK_SUCCESS) {
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_object_free(&device->vk, pAllocator, mem);
|
2020-01-15 10:32:09 +00:00
|
|
|
return vk_error(device->instance, result);
|
|
|
|
}
|
2019-11-27 21:08:51 +00:00
|
|
|
|
2019-12-04 09:39:01 +00:00
|
|
|
*pMem = v3dv_device_memory_to_handle(mem);
|
|
|
|
return result;
|
2019-11-27 21:08:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_FreeMemory(VkDevice _device,
|
|
|
|
VkDeviceMemory _mem,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device_memory, mem, _mem);
|
|
|
|
|
|
|
|
if (mem == NULL)
|
|
|
|
return;
|
|
|
|
|
2019-12-12 10:02:04 +00:00
|
|
|
if (mem->bo->map)
|
2019-11-27 21:08:51 +00:00
|
|
|
v3dv_UnmapMemory(_device, _mem);
|
|
|
|
|
2019-12-04 09:58:05 +00:00
|
|
|
device_free(device, mem);
|
2019-11-27 21:08:51 +00:00
|
|
|
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_object_free(&device->vk, pAllocator, mem);
|
2019-11-27 21:08:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_MapMemory(VkDevice _device,
|
|
|
|
VkDeviceMemory _memory,
|
|
|
|
VkDeviceSize offset,
|
|
|
|
VkDeviceSize size,
|
|
|
|
VkMemoryMapFlags flags,
|
|
|
|
void **ppData)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory);
|
|
|
|
|
|
|
|
if (mem == NULL) {
|
|
|
|
*ppData = NULL;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-12-12 10:02:04 +00:00
|
|
|
assert(offset < mem->bo->size);
|
2019-12-04 11:21:35 +00:00
|
|
|
|
2020-06-17 11:15:42 +01:00
|
|
|
/* Since the driver can map BOs internally as well and the mapped range
|
|
|
|
* required by the user or the driver might not be the same, we always map
|
|
|
|
* the entire BO and then add the requested offset to the start address
|
|
|
|
* of the mapped region.
|
2019-12-04 11:21:35 +00:00
|
|
|
*/
|
2020-06-17 11:15:42 +01:00
|
|
|
VkResult result = device_map(device, mem);
|
2019-12-04 11:21:35 +00:00
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
return vk_error(device->instance, result);
|
2019-11-27 21:08:51 +00:00
|
|
|
|
2019-12-12 10:02:04 +00:00
|
|
|
*ppData = ((uint8_t *) mem->bo->map) + offset;
|
2019-12-04 11:21:35 +00:00
|
|
|
return VK_SUCCESS;
|
2019-11-27 21:08:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_UnmapMemory(VkDevice _device,
|
|
|
|
VkDeviceMemory _memory)
|
|
|
|
{
|
2019-12-04 11:29:00 +00:00
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory);
|
|
|
|
|
|
|
|
if (mem == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
device_unmap(device, mem);
|
2019-11-27 21:08:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_FlushMappedMemoryRanges(VkDevice _device,
|
|
|
|
uint32_t memoryRangeCount,
|
|
|
|
const VkMappedMemoryRange *pMemoryRanges)
|
|
|
|
{
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_InvalidateMappedMemoryRanges(VkDevice _device,
|
|
|
|
uint32_t memoryRangeCount,
|
|
|
|
const VkMappedMemoryRange *pMemoryRanges)
|
|
|
|
{
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
2019-12-04 08:24:03 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_GetImageMemoryRequirements(VkDevice _device,
|
|
|
|
VkImage _image,
|
|
|
|
VkMemoryRequirements *pMemoryRequirements)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_image, image, _image);
|
|
|
|
|
|
|
|
assert(image->size > 0);
|
|
|
|
|
|
|
|
pMemoryRequirements->size = image->size;
|
|
|
|
pMemoryRequirements->alignment = image->alignment;
|
2020-09-23 10:28:41 +01:00
|
|
|
pMemoryRequirements->memoryTypeBits = 0x1;
|
2019-12-04 08:24:03 +00:00
|
|
|
}
|
2019-12-05 09:36:24 +00:00
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_BindImageMemory(VkDevice _device,
|
|
|
|
VkImage _image,
|
|
|
|
VkDeviceMemory _memory,
|
|
|
|
VkDeviceSize memoryOffset)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_image, image, _image);
|
|
|
|
|
|
|
|
/* Valid usage:
|
|
|
|
*
|
|
|
|
* "memoryOffset must be an integer multiple of the alignment member of
|
|
|
|
* the VkMemoryRequirements structure returned from a call to
|
|
|
|
* vkGetImageMemoryRequirements with image"
|
|
|
|
*/
|
|
|
|
assert(memoryOffset % image->alignment == 0);
|
2019-12-12 10:02:04 +00:00
|
|
|
assert(memoryOffset < mem->bo->size);
|
2019-12-05 09:36:24 +00:00
|
|
|
|
|
|
|
image->mem = mem;
|
|
|
|
image->mem_offset = memoryOffset;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
2019-12-09 09:07:36 +00:00
|
|
|
|
2019-12-09 09:35:03 +00:00
|
|
|
void
|
|
|
|
v3dv_GetBufferMemoryRequirements(VkDevice _device,
|
|
|
|
VkBuffer _buffer,
|
|
|
|
VkMemoryRequirements* pMemoryRequirements)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_buffer, buffer, _buffer);
|
|
|
|
|
2020-09-23 10:28:41 +01:00
|
|
|
pMemoryRequirements->memoryTypeBits = 0x1;
|
2019-12-09 09:35:03 +00:00
|
|
|
pMemoryRequirements->alignment = buffer->alignment;
|
|
|
|
pMemoryRequirements->size =
|
|
|
|
align64(buffer->size, pMemoryRequirements->alignment);
|
|
|
|
}
|
|
|
|
|
2019-12-09 09:40:32 +00:00
|
|
|
VkResult
|
|
|
|
v3dv_BindBufferMemory(VkDevice _device,
|
|
|
|
VkBuffer _buffer,
|
|
|
|
VkDeviceMemory _memory,
|
|
|
|
VkDeviceSize memoryOffset)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_buffer, buffer, _buffer);
|
|
|
|
|
|
|
|
/* Valid usage:
|
|
|
|
*
|
|
|
|
* "memoryOffset must be an integer multiple of the alignment member of
|
|
|
|
* the VkMemoryRequirements structure returned from a call to
|
|
|
|
* vkGetBufferMemoryRequirements with buffer"
|
|
|
|
*/
|
|
|
|
assert(memoryOffset % buffer->alignment == 0);
|
2019-12-12 10:02:04 +00:00
|
|
|
assert(memoryOffset < mem->bo->size);
|
2019-12-09 09:40:32 +00:00
|
|
|
|
|
|
|
buffer->mem = mem;
|
|
|
|
buffer->mem_offset = memoryOffset;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2019-12-09 09:07:36 +00:00
|
|
|
VkResult
|
|
|
|
v3dv_CreateBuffer(VkDevice _device,
|
|
|
|
const VkBufferCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkBuffer *pBuffer)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
struct v3dv_buffer *buffer;
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
|
|
|
|
assert(pCreateInfo->usage != 0);
|
|
|
|
|
|
|
|
/* We don't support any flags for now */
|
|
|
|
assert(pCreateInfo->flags == 0);
|
|
|
|
|
2020-11-12 15:30:41 +00:00
|
|
|
buffer = vk_object_zalloc(&device->vk, pAllocator, sizeof(*buffer),
|
|
|
|
VK_OBJECT_TYPE_BUFFER);
|
2019-12-09 09:07:36 +00:00
|
|
|
if (buffer == NULL)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
buffer->size = pCreateInfo->size;
|
|
|
|
buffer->usage = pCreateInfo->usage;
|
|
|
|
buffer->alignment = 256; /* nonCoherentAtomSize */
|
|
|
|
|
2020-06-23 10:32:04 +01:00
|
|
|
/* Limit allocations to 32-bit */
|
|
|
|
const VkDeviceSize aligned_size = align64(buffer->size, buffer->alignment);
|
|
|
|
if (aligned_size > UINT32_MAX || aligned_size < buffer->size)
|
|
|
|
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
|
2019-12-09 09:07:36 +00:00
|
|
|
|
|
|
|
*pBuffer = v3dv_buffer_to_handle(buffer);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_DestroyBuffer(VkDevice _device,
|
|
|
|
VkBuffer _buffer,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_buffer, buffer, _buffer);
|
|
|
|
|
|
|
|
if (!buffer)
|
|
|
|
return;
|
|
|
|
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_object_free(&device->vk, pAllocator, buffer);
|
2019-12-09 09:07:36 +00:00
|
|
|
}
|
2019-12-09 12:16:16 +00:00
|
|
|
|
2020-03-03 10:57:59 +00:00
|
|
|
/**
|
|
|
|
* This computes the maximum bpp used by any of the render targets used by
|
2020-07-24 09:33:16 +01:00
|
|
|
* a particular subpass and checks if any of those render targets are
|
|
|
|
* multisampled. If we don't have a subpass (when we are not inside a
|
2020-03-03 10:57:59 +00:00
|
|
|
* render pass), then we assume that all framebuffer attachments are used.
|
|
|
|
*/
|
2020-07-24 09:33:16 +01:00
|
|
|
void
|
|
|
|
v3dv_framebuffer_compute_internal_bpp_msaa(
|
|
|
|
const struct v3dv_framebuffer *framebuffer,
|
|
|
|
const struct v3dv_subpass *subpass,
|
|
|
|
uint8_t *max_bpp,
|
|
|
|
bool *msaa)
|
2020-01-07 07:42:38 +00:00
|
|
|
{
|
|
|
|
STATIC_ASSERT(RENDER_TARGET_MAXIMUM_32BPP == 0);
|
2020-07-24 09:33:16 +01:00
|
|
|
*max_bpp = RENDER_TARGET_MAXIMUM_32BPP;
|
|
|
|
*msaa = false;
|
2020-03-02 16:21:26 +00:00
|
|
|
|
|
|
|
if (subpass) {
|
|
|
|
for (uint32_t i = 0; i < subpass->color_count; i++) {
|
|
|
|
uint32_t att_idx = subpass->color_attachments[i].attachment;
|
|
|
|
if (att_idx == VK_ATTACHMENT_UNUSED)
|
|
|
|
continue;
|
|
|
|
|
2020-04-06 09:19:53 +01:00
|
|
|
const struct v3dv_image_view *att = framebuffer->attachments[att_idx];
|
2020-03-02 16:21:26 +00:00
|
|
|
assert(att);
|
|
|
|
|
|
|
|
if (att->aspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
2020-07-24 09:33:16 +01:00
|
|
|
*max_bpp = MAX2(*max_bpp, att->internal_bpp);
|
|
|
|
|
|
|
|
if (att->image->samples > VK_SAMPLE_COUNT_1_BIT)
|
|
|
|
*msaa = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!*msaa && subpass->ds_attachment.attachment != VK_ATTACHMENT_UNUSED) {
|
|
|
|
const struct v3dv_image_view *att =
|
|
|
|
framebuffer->attachments[subpass->ds_attachment.attachment];
|
|
|
|
assert(att);
|
|
|
|
|
|
|
|
if (att->image->samples > VK_SAMPLE_COUNT_1_BIT)
|
|
|
|
*msaa = true;
|
2020-03-02 16:21:26 +00:00
|
|
|
}
|
|
|
|
|
2020-07-24 09:33:16 +01:00
|
|
|
return;
|
2020-03-02 16:21:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(framebuffer->attachment_count <= 4);
|
2020-01-07 07:42:38 +00:00
|
|
|
for (uint32_t i = 0; i < framebuffer->attachment_count; i++) {
|
|
|
|
const struct v3dv_image_view *att = framebuffer->attachments[i];
|
2020-01-28 12:03:41 +00:00
|
|
|
assert(att);
|
|
|
|
|
|
|
|
if (att->aspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
2020-07-24 09:33:16 +01:00
|
|
|
*max_bpp = MAX2(*max_bpp, att->internal_bpp);
|
|
|
|
|
|
|
|
if (att->image->samples > VK_SAMPLE_COUNT_1_BIT)
|
|
|
|
*msaa = true;
|
2020-01-07 07:42:38 +00:00
|
|
|
}
|
2020-03-02 16:21:26 +00:00
|
|
|
|
2020-07-24 09:33:16 +01:00
|
|
|
return;
|
2020-01-07 07:42:38 +00:00
|
|
|
}
|
|
|
|
|
2019-12-09 12:16:16 +00:00
|
|
|
VkResult
|
|
|
|
v3dv_CreateFramebuffer(VkDevice _device,
|
|
|
|
const VkFramebufferCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkFramebuffer *pFramebuffer)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
struct v3dv_framebuffer *framebuffer;
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
|
|
|
|
|
|
|
|
size_t size = sizeof(*framebuffer) +
|
|
|
|
sizeof(struct v3dv_image_view *) * pCreateInfo->attachmentCount;
|
2020-11-12 15:30:41 +00:00
|
|
|
framebuffer = vk_object_zalloc(&device->vk, pAllocator, size,
|
|
|
|
VK_OBJECT_TYPE_FRAMEBUFFER);
|
2019-12-09 12:16:16 +00:00
|
|
|
if (framebuffer == NULL)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
framebuffer->width = pCreateInfo->width;
|
|
|
|
framebuffer->height = pCreateInfo->height;
|
|
|
|
framebuffer->layers = pCreateInfo->layers;
|
2020-10-08 12:24:13 +01:00
|
|
|
framebuffer->has_edge_padding = true;
|
|
|
|
|
2019-12-09 12:16:16 +00:00
|
|
|
framebuffer->attachment_count = pCreateInfo->attachmentCount;
|
2020-01-28 12:03:41 +00:00
|
|
|
framebuffer->color_attachment_count = 0;
|
2019-12-09 12:16:16 +00:00
|
|
|
for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
|
|
|
|
framebuffer->attachments[i] =
|
|
|
|
v3dv_image_view_from_handle(pCreateInfo->pAttachments[i]);
|
2020-01-28 12:03:41 +00:00
|
|
|
if (framebuffer->attachments[i]->aspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
|
|
|
framebuffer->color_attachment_count++;
|
2019-12-09 12:16:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*pFramebuffer = v3dv_framebuffer_to_handle(framebuffer);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_DestroyFramebuffer(VkDevice _device,
|
|
|
|
VkFramebuffer _fb,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_framebuffer, fb, _fb);
|
|
|
|
|
|
|
|
if (!fb)
|
|
|
|
return;
|
|
|
|
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_object_free(&device->vk, pAllocator, fb);
|
2019-12-09 12:16:16 +00:00
|
|
|
}
|
2020-01-15 10:32:09 +00:00
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_GetMemoryFdPropertiesKHR(VkDevice _device,
|
|
|
|
VkExternalMemoryHandleTypeFlagBits handleType,
|
|
|
|
int fd,
|
|
|
|
VkMemoryFdPropertiesKHR *pMemoryFdProperties)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
|
|
|
|
|
|
|
|
switch (handleType) {
|
|
|
|
case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
|
|
|
|
pMemoryFdProperties->memoryTypeBits =
|
|
|
|
(1 << pdevice->memory.memoryTypeCount) - 1;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
default:
|
|
|
|
return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_GetMemoryFdKHR(VkDevice _device,
|
|
|
|
const VkMemoryGetFdInfoKHR *pGetFdInfo,
|
|
|
|
int *pFd)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device_memory, mem, pGetFdInfo->memory);
|
|
|
|
|
|
|
|
assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
|
|
|
|
assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
|
|
|
|
pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
|
|
|
|
|
|
|
|
int fd, ret;
|
v3dv: move authenticated display fd acquisition to swapchain creation time
So far, we have only been supporting X11, so we assumed that we were running
inside X11 and would always try to get an authenticated fd from Xorg during
device initialization. While this works for desktop Raspbian, it is not
really correct and it is not what we want to do when we start considering
other WSIs.
Initially, one could think we can still do this by guarding the WSI code
under the proper instance extension check. This, however, doesn't work
reliably, as the Vulkan loader can call vkEnumerateDevices without enabling
surface extensions on the instance, which then can lead to us not
initializing any display_fd and failing with VK_ERROR_INITIALIZATION_FAILED,
which is not correct, so while we can try to acquire the display_fd here,
it might not always work, and we should definitely not fail initialization
of the physical device for that.
Instead, with this change we move acquisition of display_fd to swapchain
creation time where required extensions need to be enabled in the instance.
This was also suggested by Daniel Stone during review of a work-in-progress
implementation for the Wayland WSI.
There is a special case to consider though: applications like Zink that
don't use Vulkan's swapchains at all but still allocate images that they
intend to use for WSI. We need to handle these by checking that we have
indeed acquired a display_fd before doing any memory allocation for WSI,
and acquiring one at that time if that's not the case.
This change also removes the render_fd and display_fd fields from the
logical device (which we were copying from the physical device), because
now there is no guarantee that we have acquired a display_fd at the
time we create a logical device. Instead, we now put a reference to the
physical device on the logical device from which we can access these.
Finally, this also fixes a regression introduced with VK_KHR_display, where
if that extension is enabled but we are running inside a compositor, we would
acquire a display_fd that is not authenticated and try to use that instead
of acquiring an authenticated display_fd from the display server.
Fixes: b1188c9451 (v3dv: VK_KHR_display extension support)
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7546>
2020-11-11 08:45:33 +00:00
|
|
|
ret = drmPrimeHandleToFD(device->pdevice->render_fd,
|
|
|
|
mem->bo->handle,
|
|
|
|
DRM_CLOEXEC, &fd);
|
2020-01-15 10:32:09 +00:00
|
|
|
if (ret)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
*pFd = fd;
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
2020-02-26 08:36:27 +00:00
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_CreateEvent(VkDevice _device,
|
|
|
|
const VkEventCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkEvent *pEvent)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
struct v3dv_event *event =
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_object_zalloc(&device->vk, pAllocator, sizeof(*event),
|
|
|
|
VK_OBJECT_TYPE_EVENT);
|
2020-02-26 08:36:27 +00:00
|
|
|
if (!event)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
/* Events are created in the unsignaled state */
|
2020-05-18 09:41:11 +01:00
|
|
|
event->state = false;
|
2020-02-26 08:36:27 +00:00
|
|
|
*pEvent = v3dv_event_to_handle(event);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_DestroyEvent(VkDevice _device,
|
|
|
|
VkEvent _event,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_event, event, _event);
|
|
|
|
|
|
|
|
if (!event)
|
|
|
|
return;
|
|
|
|
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_object_free(&device->vk, pAllocator, event);
|
2020-02-26 08:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_GetEventStatus(VkDevice _device, VkEvent _event)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_event, event, _event);
|
2020-05-18 09:41:11 +01:00
|
|
|
return p_atomic_read(&event->state) ? VK_EVENT_SET : VK_EVENT_RESET;
|
2020-02-26 08:36:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_SetEvent(VkDevice _device, VkEvent _event)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_event, event, _event);
|
2020-05-18 09:41:11 +01:00
|
|
|
p_atomic_set(&event->state, 1);
|
2020-02-26 08:36:27 +00:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_ResetEvent(VkDevice _device, VkEvent _event)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_event, event, _event);
|
2020-05-18 09:41:11 +01:00
|
|
|
p_atomic_set(&event->state, 0);
|
2020-02-26 08:36:27 +00:00
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
2020-03-29 15:29:55 +01:00
|
|
|
|
|
|
|
static const enum V3DX(Wrap_Mode) vk_to_v3d_wrap_mode[] = {
|
|
|
|
[VK_SAMPLER_ADDRESS_MODE_REPEAT] = V3D_WRAP_MODE_REPEAT,
|
|
|
|
[VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT] = V3D_WRAP_MODE_MIRROR,
|
|
|
|
[VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE] = V3D_WRAP_MODE_CLAMP,
|
|
|
|
[VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE] = V3D_WRAP_MODE_MIRROR_ONCE,
|
|
|
|
[VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER] = V3D_WRAP_MODE_BORDER,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const enum V3DX(Compare_Function)
|
|
|
|
vk_to_v3d_compare_func[] = {
|
|
|
|
[VK_COMPARE_OP_NEVER] = V3D_COMPARE_FUNC_NEVER,
|
|
|
|
[VK_COMPARE_OP_LESS] = V3D_COMPARE_FUNC_LESS,
|
|
|
|
[VK_COMPARE_OP_EQUAL] = V3D_COMPARE_FUNC_EQUAL,
|
|
|
|
[VK_COMPARE_OP_LESS_OR_EQUAL] = V3D_COMPARE_FUNC_LEQUAL,
|
|
|
|
[VK_COMPARE_OP_GREATER] = V3D_COMPARE_FUNC_GREATER,
|
|
|
|
[VK_COMPARE_OP_NOT_EQUAL] = V3D_COMPARE_FUNC_NOTEQUAL,
|
|
|
|
[VK_COMPARE_OP_GREATER_OR_EQUAL] = V3D_COMPARE_FUNC_GEQUAL,
|
|
|
|
[VK_COMPARE_OP_ALWAYS] = V3D_COMPARE_FUNC_ALWAYS,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
pack_sampler_state(struct v3dv_sampler *sampler,
|
|
|
|
const VkSamplerCreateInfo *pCreateInfo)
|
|
|
|
{
|
|
|
|
enum V3DX(Border_Color_Mode) border_color_mode;
|
|
|
|
|
2020-07-03 09:06:28 +01:00
|
|
|
/* For now we only support the preset Vulkan border color modes. If we
|
|
|
|
* want to implement VK_EXT_custom_border_color in the future we would have
|
|
|
|
* to use V3D_BORDER_COLOR_FOLLOWS, and fill up border_color_word_[0/1/2/3]
|
|
|
|
* SAMPLER_STATE.
|
2020-03-29 15:29:55 +01:00
|
|
|
*/
|
|
|
|
switch (pCreateInfo->borderColor) {
|
|
|
|
case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
|
|
|
|
case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
|
|
|
|
border_color_mode = V3D_BORDER_COLOR_0000;
|
|
|
|
break;
|
|
|
|
case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
|
|
|
|
case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
|
|
|
|
border_color_mode = V3D_BORDER_COLOR_0001;
|
|
|
|
break;
|
|
|
|
case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
|
|
|
|
case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
|
|
|
|
border_color_mode = V3D_BORDER_COLOR_1111;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
unreachable("Unknown border color");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-07-03 09:06:28 +01:00
|
|
|
/* For some texture formats, when clamping to transparent black border the
|
|
|
|
* CTS expects alpha to be set to 1 instead of 0, but the border color mode
|
|
|
|
* will take priority over the texture state swizzle, so the only way to
|
|
|
|
* fix that is to apply a swizzle in the shader. Here we keep track of
|
|
|
|
* whether we are activating that mode and we will decide if we need to
|
|
|
|
* activate the texture swizzle lowering in the shader key at compile time
|
|
|
|
* depending on the actual texture format.
|
|
|
|
*/
|
|
|
|
if ((pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
|
|
|
|
pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER ||
|
|
|
|
pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) &&
|
|
|
|
border_color_mode == V3D_BORDER_COLOR_0000) {
|
|
|
|
sampler->clamp_to_transparent_black_border = true;
|
|
|
|
}
|
|
|
|
|
2020-06-03 00:22:48 +01:00
|
|
|
v3dv_pack(sampler->sampler_state, SAMPLER_STATE, s) {
|
2020-03-29 15:29:55 +01:00
|
|
|
if (pCreateInfo->anisotropyEnable) {
|
|
|
|
s.anisotropy_enable = true;
|
|
|
|
if (pCreateInfo->maxAnisotropy > 8)
|
|
|
|
s.maximum_anisotropy = 3;
|
|
|
|
else if (pCreateInfo->maxAnisotropy > 4)
|
|
|
|
s.maximum_anisotropy = 2;
|
|
|
|
else if (pCreateInfo->maxAnisotropy > 2)
|
|
|
|
s.maximum_anisotropy = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
s.border_color_mode = border_color_mode;
|
|
|
|
|
|
|
|
s.wrap_i_border = false; /* Also hardcoded on v3d */
|
|
|
|
s.wrap_s = vk_to_v3d_wrap_mode[pCreateInfo->addressModeU];
|
|
|
|
s.wrap_t = vk_to_v3d_wrap_mode[pCreateInfo->addressModeV];
|
|
|
|
s.wrap_r = vk_to_v3d_wrap_mode[pCreateInfo->addressModeW];
|
|
|
|
s.fixed_bias = pCreateInfo->mipLodBias;
|
|
|
|
s.max_level_of_detail = MIN2(MAX2(0, pCreateInfo->maxLod), 15);
|
|
|
|
s.min_level_of_detail = MIN2(MAX2(0, pCreateInfo->minLod), 15);
|
|
|
|
s.srgb_disable = 0; /* Not even set by v3d */
|
|
|
|
s.depth_compare_function =
|
|
|
|
vk_to_v3d_compare_func[pCreateInfo->compareEnable ?
|
|
|
|
pCreateInfo->compareOp : VK_COMPARE_OP_NEVER];
|
|
|
|
s.mip_filter_nearest = pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_NEAREST;
|
|
|
|
s.min_filter_nearest = pCreateInfo->minFilter == VK_FILTER_NEAREST;
|
|
|
|
s.mag_filter_nearest = pCreateInfo->magFilter == VK_FILTER_NEAREST;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VkResult
|
|
|
|
v3dv_CreateSampler(VkDevice _device,
|
|
|
|
const VkSamplerCreateInfo *pCreateInfo,
|
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
VkSampler *pSampler)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
struct v3dv_sampler *sampler;
|
|
|
|
|
|
|
|
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
|
|
|
|
|
2020-11-12 15:30:41 +00:00
|
|
|
sampler = vk_object_zalloc(&device->vk, pAllocator, sizeof(*sampler),
|
|
|
|
VK_OBJECT_TYPE_SAMPLER);
|
2020-03-29 15:29:55 +01:00
|
|
|
if (!sampler)
|
|
|
|
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
v3dv/descriptor_set: combine texture and sampler indices
OpenGL doesn't have the concept of individual texture and sampler, so
texture and sampler indexes have the same value. v3d compiler uses
this assumption, so for example, the texture info at the v3d key
include values that you need to use the texture format and the sampler
to fill (like the return_size).
One option would be to adapt the v3d compiler to handle both, but then
we would need to adapt to the lowerings it uses, like nir_lower_tex,
that also take the same assumption.
We deal with this on the Vulkan driver, by reassigning the texture and
sampler index to a combined one. We add a hash table to map the
combined texture idx and sampler idx to this combined idx, and a
simple array to the opposite map. On the driver we work with the
separate indices to fill up the data, while the v3d compiler works
with the combined one.
As mentioned, this is needed to properly fill up the texture return
size, so as we are here, we fix that. This gets tests like the
following working:
dEQP-VK.glsl.texture_gather.basic.2d.depth32f.base_level.level_2
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
2020-04-06 23:33:14 +01:00
|
|
|
sampler->compare_enable = pCreateInfo->compareEnable;
|
2020-07-01 13:21:09 +01:00
|
|
|
sampler->unnormalized_coordinates = pCreateInfo->unnormalizedCoordinates;
|
2020-03-29 15:29:55 +01:00
|
|
|
pack_sampler_state(sampler, pCreateInfo);
|
|
|
|
|
|
|
|
*pSampler = v3dv_sampler_to_handle(sampler);
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_DestroySampler(VkDevice _device,
|
|
|
|
VkSampler _sampler,
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
{
|
|
|
|
V3DV_FROM_HANDLE(v3dv_device, device, _device);
|
|
|
|
V3DV_FROM_HANDLE(v3dv_sampler, sampler, _sampler);
|
|
|
|
|
|
|
|
if (!sampler)
|
|
|
|
return;
|
|
|
|
|
2020-11-12 15:30:41 +00:00
|
|
|
vk_object_free(&device->vk, pAllocator, sampler);
|
2020-03-29 15:29:55 +01:00
|
|
|
}
|
|
|
|
|
2020-06-04 08:03:42 +01:00
|
|
|
void
|
|
|
|
v3dv_GetDeviceMemoryCommitment(VkDevice device,
|
|
|
|
VkDeviceMemory memory,
|
|
|
|
VkDeviceSize *pCommittedMemoryInBytes)
|
|
|
|
{
|
|
|
|
*pCommittedMemoryInBytes = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
v3dv_GetImageSparseMemoryRequirements(
|
|
|
|
VkDevice device,
|
|
|
|
VkImage image,
|
|
|
|
uint32_t *pSparseMemoryRequirementCount,
|
|
|
|
VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
|
|
|
|
{
|
|
|
|
*pSparseMemoryRequirementCount = 0;
|
|
|
|
}
|
2020-03-29 15:29:55 +01:00
|
|
|
|
2020-06-04 08:03:42 +01:00
|
|
|
void
|
|
|
|
v3dv_GetImageSparseMemoryRequirements2(
|
|
|
|
VkDevice device,
|
|
|
|
const VkImageSparseMemoryRequirementsInfo2 *pInfo,
|
|
|
|
uint32_t *pSparseMemoryRequirementCount,
|
|
|
|
VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
|
|
|
|
{
|
|
|
|
*pSparseMemoryRequirementCount = 0;
|
|
|
|
}
|
2020-10-13 22:06:35 +01:00
|
|
|
|
|
|
|
/* vk_icd.h does not declare this function, so we declare it here to
|
|
|
|
* suppress Wmissing-prototypes.
|
|
|
|
*/
|
|
|
|
PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
|
|
|
|
|
|
|
|
PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
|
|
|
|
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion)
|
|
|
|
{
|
|
|
|
/* For the full details on loader interface versioning, see
|
|
|
|
* <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
|
|
|
|
* What follows is a condensed summary, to help you navigate the large and
|
|
|
|
* confusing official doc.
|
|
|
|
*
|
|
|
|
* - Loader interface v0 is incompatible with later versions. We don't
|
|
|
|
* support it.
|
|
|
|
*
|
|
|
|
* - In loader interface v1:
|
|
|
|
* - The first ICD entrypoint called by the loader is
|
|
|
|
* vk_icdGetInstanceProcAddr(). The ICD must statically expose this
|
|
|
|
* entrypoint.
|
|
|
|
* - The ICD must statically expose no other Vulkan symbol unless it is
|
|
|
|
* linked with -Bsymbolic.
|
|
|
|
* - Each dispatchable Vulkan handle created by the ICD must be
|
|
|
|
* a pointer to a struct whose first member is VK_LOADER_DATA. The
|
|
|
|
* ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC.
|
|
|
|
* - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
|
|
|
|
* vkDestroySurfaceKHR(). The ICD must be capable of working with
|
|
|
|
* such loader-managed surfaces.
|
|
|
|
*
|
|
|
|
* - Loader interface v2 differs from v1 in:
|
|
|
|
* - The first ICD entrypoint called by the loader is
|
|
|
|
* vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
|
|
|
|
* statically expose this entrypoint.
|
|
|
|
*
|
|
|
|
* - Loader interface v3 differs from v2 in:
|
|
|
|
* - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
|
|
|
|
* vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
|
|
|
|
* because the loader no longer does so.
|
|
|
|
*
|
|
|
|
* - Loader interface v4 differs from v3 in:
|
|
|
|
* - The ICD must implement vk_icdGetPhysicalDeviceProcAddr().
|
|
|
|
*/
|
|
|
|
*pSupportedVersion = MIN2(*pSupportedVersion, 3u);
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|