1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2019 Raspberry Pi Ltd 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <assert.h> 25bf215546Sopenharmony_ci#include <fcntl.h> 26bf215546Sopenharmony_ci#include <stdbool.h> 27bf215546Sopenharmony_ci#include <string.h> 28bf215546Sopenharmony_ci#include <sys/mman.h> 29bf215546Sopenharmony_ci#include <sys/sysinfo.h> 30bf215546Sopenharmony_ci#include <unistd.h> 31bf215546Sopenharmony_ci#include <xf86drm.h> 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#ifdef MAJOR_IN_MKDEV 34bf215546Sopenharmony_ci#include <sys/mkdev.h> 35bf215546Sopenharmony_ci#endif 36bf215546Sopenharmony_ci#ifdef MAJOR_IN_SYSMACROS 37bf215546Sopenharmony_ci#include <sys/sysmacros.h> 38bf215546Sopenharmony_ci#endif 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci#include "v3dv_private.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#include "common/v3d_debug.h" 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci#include "compiler/v3d_compiler.h" 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci#include "drm-uapi/v3d_drm.h" 47bf215546Sopenharmony_ci#include "format/u_format.h" 48bf215546Sopenharmony_ci#include "vk_drm_syncobj.h" 49bf215546Sopenharmony_ci#include "vk_util.h" 50bf215546Sopenharmony_ci#include "git_sha1.h" 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci#include "util/build_id.h" 53bf215546Sopenharmony_ci#include "util/debug.h" 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XCB_KHR 56bf215546Sopenharmony_ci#include <xcb/xcb.h> 57bf215546Sopenharmony_ci#include <xcb/dri3.h> 58bf215546Sopenharmony_ci#include <X11/Xlib-xcb.h> 59bf215546Sopenharmony_ci#endif 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WAYLAND_KHR 62bf215546Sopenharmony_ci#include <wayland-client.h> 63bf215546Sopenharmony_ci#include "wayland-drm-client-protocol.h" 64bf215546Sopenharmony_ci#endif 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci#ifndef ANDROID 67bf215546Sopenharmony_ci# define V3DV_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION) 68bf215546Sopenharmony_ci#else 69bf215546Sopenharmony_ci/* Android CDD require additional extensions for API v1.1+ */ 70bf215546Sopenharmony_ci# define V3DV_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION) 71bf215546Sopenharmony_ci#endif 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 74bf215546Sopenharmony_civ3dv_EnumerateInstanceVersion(uint32_t *pApiVersion) 75bf215546Sopenharmony_ci{ 76bf215546Sopenharmony_ci *pApiVersion = V3DV_API_VERSION; 77bf215546Sopenharmony_ci return VK_SUCCESS; 78bf215546Sopenharmony_ci} 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci#if defined(VK_USE_PLATFORM_WIN32_KHR) || \ 81bf215546Sopenharmony_ci defined(VK_USE_PLATFORM_WAYLAND_KHR) || \ 82bf215546Sopenharmony_ci defined(VK_USE_PLATFORM_XCB_KHR) || \ 83bf215546Sopenharmony_ci defined(VK_USE_PLATFORM_XLIB_KHR) || \ 84bf215546Sopenharmony_ci defined(VK_USE_PLATFORM_DISPLAY_KHR) 85bf215546Sopenharmony_ci#define V3DV_USE_WSI_PLATFORM 86bf215546Sopenharmony_ci#endif 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_cistatic const struct vk_instance_extension_table instance_extensions = { 89bf215546Sopenharmony_ci .KHR_device_group_creation = true, 90bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_DISPLAY_KHR 91bf215546Sopenharmony_ci .KHR_display = true, 92bf215546Sopenharmony_ci .KHR_get_display_properties2 = true, 93bf215546Sopenharmony_ci#endif 94bf215546Sopenharmony_ci .KHR_external_fence_capabilities = true, 95bf215546Sopenharmony_ci .KHR_external_memory_capabilities = true, 96bf215546Sopenharmony_ci .KHR_external_semaphore_capabilities = true, 97bf215546Sopenharmony_ci .KHR_get_physical_device_properties2 = true, 98bf215546Sopenharmony_ci#ifdef V3DV_USE_WSI_PLATFORM 99bf215546Sopenharmony_ci .KHR_get_surface_capabilities2 = true, 100bf215546Sopenharmony_ci .KHR_surface = true, 101bf215546Sopenharmony_ci .KHR_surface_protected_capabilities = true, 102bf215546Sopenharmony_ci#endif 103bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WAYLAND_KHR 104bf215546Sopenharmony_ci .KHR_wayland_surface = true, 105bf215546Sopenharmony_ci#endif 106bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XCB_KHR 107bf215546Sopenharmony_ci .KHR_xcb_surface = true, 108bf215546Sopenharmony_ci#endif 109bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XLIB_KHR 110bf215546Sopenharmony_ci .KHR_xlib_surface = true, 111bf215546Sopenharmony_ci#endif 112bf215546Sopenharmony_ci .EXT_debug_report = true, 113bf215546Sopenharmony_ci .EXT_debug_utils = true, 114bf215546Sopenharmony_ci}; 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_cistatic void 117bf215546Sopenharmony_ciget_device_extensions(const struct v3dv_physical_device *device, 118bf215546Sopenharmony_ci struct vk_device_extension_table *ext) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci *ext = (struct vk_device_extension_table) { 121bf215546Sopenharmony_ci .KHR_8bit_storage = true, 122bf215546Sopenharmony_ci .KHR_16bit_storage = true, 123bf215546Sopenharmony_ci .KHR_bind_memory2 = true, 124bf215546Sopenharmony_ci .KHR_buffer_device_address = true, 125bf215546Sopenharmony_ci .KHR_copy_commands2 = true, 126bf215546Sopenharmony_ci .KHR_create_renderpass2 = true, 127bf215546Sopenharmony_ci .KHR_dedicated_allocation = true, 128bf215546Sopenharmony_ci .KHR_device_group = true, 129bf215546Sopenharmony_ci .KHR_driver_properties = true, 130bf215546Sopenharmony_ci .KHR_descriptor_update_template = true, 131bf215546Sopenharmony_ci .KHR_depth_stencil_resolve = true, 132bf215546Sopenharmony_ci .KHR_external_fence = true, 133bf215546Sopenharmony_ci .KHR_external_fence_fd = true, 134bf215546Sopenharmony_ci .KHR_external_memory = true, 135bf215546Sopenharmony_ci .KHR_external_memory_fd = true, 136bf215546Sopenharmony_ci .KHR_external_semaphore = true, 137bf215546Sopenharmony_ci .KHR_external_semaphore_fd = true, 138bf215546Sopenharmony_ci .KHR_format_feature_flags2 = true, 139bf215546Sopenharmony_ci .KHR_get_memory_requirements2 = true, 140bf215546Sopenharmony_ci .KHR_image_format_list = true, 141bf215546Sopenharmony_ci .KHR_imageless_framebuffer = true, 142bf215546Sopenharmony_ci .KHR_performance_query = device->caps.perfmon, 143bf215546Sopenharmony_ci .KHR_relaxed_block_layout = true, 144bf215546Sopenharmony_ci .KHR_maintenance1 = true, 145bf215546Sopenharmony_ci .KHR_maintenance2 = true, 146bf215546Sopenharmony_ci .KHR_maintenance3 = true, 147bf215546Sopenharmony_ci .KHR_multiview = true, 148bf215546Sopenharmony_ci .KHR_pipeline_executable_properties = true, 149bf215546Sopenharmony_ci .KHR_separate_depth_stencil_layouts = true, 150bf215546Sopenharmony_ci .KHR_shader_float_controls = true, 151bf215546Sopenharmony_ci .KHR_shader_non_semantic_info = true, 152bf215546Sopenharmony_ci .KHR_sampler_mirror_clamp_to_edge = true, 153bf215546Sopenharmony_ci .KHR_spirv_1_4 = true, 154bf215546Sopenharmony_ci .KHR_storage_buffer_storage_class = true, 155bf215546Sopenharmony_ci .KHR_timeline_semaphore = true, 156bf215546Sopenharmony_ci .KHR_uniform_buffer_standard_layout = true, 157bf215546Sopenharmony_ci#ifdef V3DV_USE_WSI_PLATFORM 158bf215546Sopenharmony_ci .KHR_swapchain = true, 159bf215546Sopenharmony_ci .KHR_swapchain_mutable_format = true, 160bf215546Sopenharmony_ci .KHR_incremental_present = true, 161bf215546Sopenharmony_ci#endif 162bf215546Sopenharmony_ci .KHR_variable_pointers = true, 163bf215546Sopenharmony_ci .KHR_vulkan_memory_model = true, 164bf215546Sopenharmony_ci .EXT_4444_formats = true, 165bf215546Sopenharmony_ci .EXT_color_write_enable = true, 166bf215546Sopenharmony_ci .EXT_custom_border_color = true, 167bf215546Sopenharmony_ci .EXT_inline_uniform_block = true, 168bf215546Sopenharmony_ci .EXT_external_memory_dma_buf = true, 169bf215546Sopenharmony_ci .EXT_host_query_reset = true, 170bf215546Sopenharmony_ci .EXT_image_drm_format_modifier = true, 171bf215546Sopenharmony_ci .EXT_index_type_uint8 = true, 172bf215546Sopenharmony_ci .EXT_line_rasterization = true, 173bf215546Sopenharmony_ci .EXT_physical_device_drm = true, 174bf215546Sopenharmony_ci .EXT_pipeline_creation_cache_control = true, 175bf215546Sopenharmony_ci .EXT_pipeline_creation_feedback = true, 176bf215546Sopenharmony_ci .EXT_private_data = true, 177bf215546Sopenharmony_ci .EXT_provoking_vertex = true, 178bf215546Sopenharmony_ci .EXT_separate_stencil_usage = true, 179bf215546Sopenharmony_ci .EXT_vertex_attribute_divisor = true, 180bf215546Sopenharmony_ci#ifdef ANDROID 181bf215546Sopenharmony_ci .ANDROID_native_buffer = true, 182bf215546Sopenharmony_ci#endif 183bf215546Sopenharmony_ci }; 184bf215546Sopenharmony_ci} 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 187bf215546Sopenharmony_civ3dv_EnumerateInstanceExtensionProperties(const char *pLayerName, 188bf215546Sopenharmony_ci uint32_t *pPropertyCount, 189bf215546Sopenharmony_ci VkExtensionProperties *pProperties) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci /* We don't support any layers */ 192bf215546Sopenharmony_ci if (pLayerName) 193bf215546Sopenharmony_ci return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci return vk_enumerate_instance_extension_properties( 196bf215546Sopenharmony_ci &instance_extensions, pPropertyCount, pProperties); 197bf215546Sopenharmony_ci} 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 200bf215546Sopenharmony_civ3dv_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, 201bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 202bf215546Sopenharmony_ci VkInstance *pInstance) 203bf215546Sopenharmony_ci{ 204bf215546Sopenharmony_ci struct v3dv_instance *instance; 205bf215546Sopenharmony_ci VkResult result; 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); 208bf215546Sopenharmony_ci 209bf215546Sopenharmony_ci if (pAllocator == NULL) 210bf215546Sopenharmony_ci pAllocator = vk_default_allocator(); 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci instance = vk_alloc(pAllocator, sizeof(*instance), 8, 213bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 214bf215546Sopenharmony_ci if (!instance) 215bf215546Sopenharmony_ci return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); 216bf215546Sopenharmony_ci 217bf215546Sopenharmony_ci struct vk_instance_dispatch_table dispatch_table; 218bf215546Sopenharmony_ci vk_instance_dispatch_table_from_entrypoints( 219bf215546Sopenharmony_ci &dispatch_table, &v3dv_instance_entrypoints, true); 220bf215546Sopenharmony_ci vk_instance_dispatch_table_from_entrypoints( 221bf215546Sopenharmony_ci &dispatch_table, &wsi_instance_entrypoints, false); 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci result = vk_instance_init(&instance->vk, 224bf215546Sopenharmony_ci &instance_extensions, 225bf215546Sopenharmony_ci &dispatch_table, 226bf215546Sopenharmony_ci pCreateInfo, pAllocator); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 229bf215546Sopenharmony_ci vk_free(pAllocator, instance); 230bf215546Sopenharmony_ci return vk_error(NULL, result); 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci v3d_process_debug_variable(); 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci instance->physicalDeviceCount = -1; 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci /* We start with the default values for the pipeline_cache envvars */ 238bf215546Sopenharmony_ci instance->pipeline_cache_enabled = true; 239bf215546Sopenharmony_ci instance->default_pipeline_cache_enabled = true; 240bf215546Sopenharmony_ci const char *pipeline_cache_str = getenv("V3DV_ENABLE_PIPELINE_CACHE"); 241bf215546Sopenharmony_ci if (pipeline_cache_str != NULL) { 242bf215546Sopenharmony_ci if (strncmp(pipeline_cache_str, "full", 4) == 0) { 243bf215546Sopenharmony_ci /* nothing to do, just to filter correct values */ 244bf215546Sopenharmony_ci } else if (strncmp(pipeline_cache_str, "no-default-cache", 16) == 0) { 245bf215546Sopenharmony_ci instance->default_pipeline_cache_enabled = false; 246bf215546Sopenharmony_ci } else if (strncmp(pipeline_cache_str, "off", 3) == 0) { 247bf215546Sopenharmony_ci instance->pipeline_cache_enabled = false; 248bf215546Sopenharmony_ci instance->default_pipeline_cache_enabled = false; 249bf215546Sopenharmony_ci } else { 250bf215546Sopenharmony_ci fprintf(stderr, "Wrong value for envvar V3DV_ENABLE_PIPELINE_CACHE. " 251bf215546Sopenharmony_ci "Allowed values are: full, no-default-cache, off\n"); 252bf215546Sopenharmony_ci } 253bf215546Sopenharmony_ci } 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci if (instance->pipeline_cache_enabled == false) { 256bf215546Sopenharmony_ci fprintf(stderr, "WARNING: v3dv pipeline cache is disabled. Performance " 257bf215546Sopenharmony_ci "can be affected negatively\n"); 258bf215546Sopenharmony_ci } else { 259bf215546Sopenharmony_ci if (instance->default_pipeline_cache_enabled == false) { 260bf215546Sopenharmony_ci fprintf(stderr, "WARNING: default v3dv pipeline cache is disabled. " 261bf215546Sopenharmony_ci "Performance can be affected negatively\n"); 262bf215546Sopenharmony_ci } 263bf215546Sopenharmony_ci } 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false)); 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci *pInstance = v3dv_instance_to_handle(instance); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci return VK_SUCCESS; 270bf215546Sopenharmony_ci} 271bf215546Sopenharmony_ci 272bf215546Sopenharmony_cistatic void 273bf215546Sopenharmony_civ3dv_physical_device_free_disk_cache(struct v3dv_physical_device *device) 274bf215546Sopenharmony_ci{ 275bf215546Sopenharmony_ci#ifdef ENABLE_SHADER_CACHE 276bf215546Sopenharmony_ci if (device->disk_cache) 277bf215546Sopenharmony_ci disk_cache_destroy(device->disk_cache); 278bf215546Sopenharmony_ci#else 279bf215546Sopenharmony_ci assert(device->disk_cache == NULL); 280bf215546Sopenharmony_ci#endif 281bf215546Sopenharmony_ci} 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_cistatic void 284bf215546Sopenharmony_ciphysical_device_finish(struct v3dv_physical_device *device) 285bf215546Sopenharmony_ci{ 286bf215546Sopenharmony_ci v3dv_wsi_finish(device); 287bf215546Sopenharmony_ci v3dv_physical_device_free_disk_cache(device); 288bf215546Sopenharmony_ci v3d_compiler_free(device->compiler); 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci util_sparse_array_finish(&device->bo_map); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci close(device->render_fd); 293bf215546Sopenharmony_ci if (device->display_fd >= 0) 294bf215546Sopenharmony_ci close(device->display_fd); 295bf215546Sopenharmony_ci if (device->master_fd >= 0) 296bf215546Sopenharmony_ci close(device->master_fd); 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci free(device->name); 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci#if using_v3d_simulator 301bf215546Sopenharmony_ci v3d_simulator_destroy(device->sim_file); 302bf215546Sopenharmony_ci#endif 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci vk_physical_device_finish(&device->vk); 305bf215546Sopenharmony_ci mtx_destroy(&device->mutex); 306bf215546Sopenharmony_ci} 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 309bf215546Sopenharmony_civ3dv_DestroyInstance(VkInstance _instance, 310bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 311bf215546Sopenharmony_ci{ 312bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci if (!instance) 315bf215546Sopenharmony_ci return; 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci if (instance->physicalDeviceCount > 0) { 318bf215546Sopenharmony_ci /* We support at most one physical device. */ 319bf215546Sopenharmony_ci assert(instance->physicalDeviceCount == 1); 320bf215546Sopenharmony_ci physical_device_finish(&instance->physicalDevice); 321bf215546Sopenharmony_ci } 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci VG(VALGRIND_DESTROY_MEMPOOL(instance)); 324bf215546Sopenharmony_ci 325bf215546Sopenharmony_ci vk_instance_finish(&instance->vk); 326bf215546Sopenharmony_ci vk_free(&instance->vk.alloc, instance); 327bf215546Sopenharmony_ci} 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_cistatic uint64_t 330bf215546Sopenharmony_cicompute_heap_size() 331bf215546Sopenharmony_ci{ 332bf215546Sopenharmony_ci#if !using_v3d_simulator 333bf215546Sopenharmony_ci /* Query the total ram from the system */ 334bf215546Sopenharmony_ci struct sysinfo info; 335bf215546Sopenharmony_ci sysinfo(&info); 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci uint64_t total_ram = (uint64_t)info.totalram * (uint64_t)info.mem_unit; 338bf215546Sopenharmony_ci#else 339bf215546Sopenharmony_ci uint64_t total_ram = (uint64_t) v3d_simulator_get_mem_size(); 340bf215546Sopenharmony_ci#endif 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci /* We don't want to burn too much ram with the GPU. If the user has 4GiB 343bf215546Sopenharmony_ci * or less, we use at most half. If they have more than 4GiB, we use 3/4. 344bf215546Sopenharmony_ci */ 345bf215546Sopenharmony_ci uint64_t available_ram; 346bf215546Sopenharmony_ci if (total_ram <= 4ull * 1024ull * 1024ull * 1024ull) 347bf215546Sopenharmony_ci available_ram = total_ram / 2; 348bf215546Sopenharmony_ci else 349bf215546Sopenharmony_ci available_ram = total_ram * 3 / 4; 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci return available_ram; 352bf215546Sopenharmony_ci} 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci#if !using_v3d_simulator 355bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XCB_KHR 356bf215546Sopenharmony_cistatic int 357bf215546Sopenharmony_cicreate_display_fd_xcb(VkIcdSurfaceBase *surface) 358bf215546Sopenharmony_ci{ 359bf215546Sopenharmony_ci int fd = -1; 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci xcb_connection_t *conn; 362bf215546Sopenharmony_ci xcb_dri3_open_reply_t *reply = NULL; 363bf215546Sopenharmony_ci if (surface) { 364bf215546Sopenharmony_ci if (surface->platform == VK_ICD_WSI_PLATFORM_XLIB) 365bf215546Sopenharmony_ci conn = XGetXCBConnection(((VkIcdSurfaceXlib *)surface)->dpy); 366bf215546Sopenharmony_ci else 367bf215546Sopenharmony_ci conn = ((VkIcdSurfaceXcb *)surface)->connection; 368bf215546Sopenharmony_ci } else { 369bf215546Sopenharmony_ci conn = xcb_connect(NULL, NULL); 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci if (xcb_connection_has_error(conn)) 373bf215546Sopenharmony_ci goto finish; 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci const xcb_setup_t *setup = xcb_get_setup(conn); 376bf215546Sopenharmony_ci xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); 377bf215546Sopenharmony_ci xcb_screen_t *screen = iter.data; 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci xcb_dri3_open_cookie_t cookie; 380bf215546Sopenharmony_ci cookie = xcb_dri3_open(conn, screen->root, None); 381bf215546Sopenharmony_ci reply = xcb_dri3_open_reply(conn, cookie, NULL); 382bf215546Sopenharmony_ci if (!reply) 383bf215546Sopenharmony_ci goto finish; 384bf215546Sopenharmony_ci 385bf215546Sopenharmony_ci if (reply->nfd != 1) 386bf215546Sopenharmony_ci goto finish; 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci fd = xcb_dri3_open_reply_fds(conn, reply)[0]; 389bf215546Sopenharmony_ci fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_cifinish: 392bf215546Sopenharmony_ci if (!surface) 393bf215546Sopenharmony_ci xcb_disconnect(conn); 394bf215546Sopenharmony_ci if (reply) 395bf215546Sopenharmony_ci free(reply); 396bf215546Sopenharmony_ci 397bf215546Sopenharmony_ci return fd; 398bf215546Sopenharmony_ci} 399bf215546Sopenharmony_ci#endif 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WAYLAND_KHR 402bf215546Sopenharmony_cistruct v3dv_wayland_info { 403bf215546Sopenharmony_ci struct wl_drm *wl_drm; 404bf215546Sopenharmony_ci int fd; 405bf215546Sopenharmony_ci bool is_set; 406bf215546Sopenharmony_ci bool authenticated; 407bf215546Sopenharmony_ci}; 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_cistatic void 410bf215546Sopenharmony_civ3dv_drm_handle_device(void *data, struct wl_drm *drm, const char *device) 411bf215546Sopenharmony_ci{ 412bf215546Sopenharmony_ci struct v3dv_wayland_info *info = data; 413bf215546Sopenharmony_ci info->fd = open(device, O_RDWR | O_CLOEXEC); 414bf215546Sopenharmony_ci info->is_set = info->fd != -1; 415bf215546Sopenharmony_ci if (!info->is_set) { 416bf215546Sopenharmony_ci fprintf(stderr, "v3dv_drm_handle_device: could not open %s (%s)\n", 417bf215546Sopenharmony_ci device, strerror(errno)); 418bf215546Sopenharmony_ci return; 419bf215546Sopenharmony_ci } 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci drm_magic_t magic; 422bf215546Sopenharmony_ci if (drmGetMagic(info->fd, &magic)) { 423bf215546Sopenharmony_ci fprintf(stderr, "v3dv_drm_handle_device: drmGetMagic failed\n"); 424bf215546Sopenharmony_ci close(info->fd); 425bf215546Sopenharmony_ci info->fd = -1; 426bf215546Sopenharmony_ci info->is_set = false; 427bf215546Sopenharmony_ci return; 428bf215546Sopenharmony_ci } 429bf215546Sopenharmony_ci wl_drm_authenticate(info->wl_drm, magic); 430bf215546Sopenharmony_ci} 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_cistatic void 433bf215546Sopenharmony_civ3dv_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format) 434bf215546Sopenharmony_ci{ 435bf215546Sopenharmony_ci} 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_cistatic void 438bf215546Sopenharmony_civ3dv_drm_handle_authenticated(void *data, struct wl_drm *drm) 439bf215546Sopenharmony_ci{ 440bf215546Sopenharmony_ci struct v3dv_wayland_info *info = data; 441bf215546Sopenharmony_ci info->authenticated = true; 442bf215546Sopenharmony_ci} 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_cistatic void 445bf215546Sopenharmony_civ3dv_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value) 446bf215546Sopenharmony_ci{ 447bf215546Sopenharmony_ci} 448bf215546Sopenharmony_ci 449bf215546Sopenharmony_cistruct wl_drm_listener v3dv_drm_listener = { 450bf215546Sopenharmony_ci .device = v3dv_drm_handle_device, 451bf215546Sopenharmony_ci .format = v3dv_drm_handle_format, 452bf215546Sopenharmony_ci .authenticated = v3dv_drm_handle_authenticated, 453bf215546Sopenharmony_ci .capabilities = v3dv_drm_handle_capabilities 454bf215546Sopenharmony_ci}; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_cistatic void 457bf215546Sopenharmony_civ3dv_registry_global(void *data, 458bf215546Sopenharmony_ci struct wl_registry *registry, 459bf215546Sopenharmony_ci uint32_t name, 460bf215546Sopenharmony_ci const char *interface, 461bf215546Sopenharmony_ci uint32_t version) 462bf215546Sopenharmony_ci{ 463bf215546Sopenharmony_ci struct v3dv_wayland_info *info = data; 464bf215546Sopenharmony_ci if (strcmp(interface, "wl_drm") == 0) { 465bf215546Sopenharmony_ci info->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface, 466bf215546Sopenharmony_ci MIN2(version, 2)); 467bf215546Sopenharmony_ci wl_drm_add_listener(info->wl_drm, &v3dv_drm_listener, data); 468bf215546Sopenharmony_ci }; 469bf215546Sopenharmony_ci} 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_cistatic void 472bf215546Sopenharmony_civ3dv_registry_global_remove_cb(void *data, 473bf215546Sopenharmony_ci struct wl_registry *registry, 474bf215546Sopenharmony_ci uint32_t name) 475bf215546Sopenharmony_ci{ 476bf215546Sopenharmony_ci} 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_cistatic int 479bf215546Sopenharmony_cicreate_display_fd_wayland(VkIcdSurfaceBase *surface) 480bf215546Sopenharmony_ci{ 481bf215546Sopenharmony_ci struct wl_display *display; 482bf215546Sopenharmony_ci struct wl_registry *registry = NULL; 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci struct v3dv_wayland_info info = { 485bf215546Sopenharmony_ci .wl_drm = NULL, 486bf215546Sopenharmony_ci .fd = -1, 487bf215546Sopenharmony_ci .is_set = false, 488bf215546Sopenharmony_ci .authenticated = false 489bf215546Sopenharmony_ci }; 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci if (surface) 492bf215546Sopenharmony_ci display = ((VkIcdSurfaceWayland *) surface)->display; 493bf215546Sopenharmony_ci else 494bf215546Sopenharmony_ci display = wl_display_connect(NULL); 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci if (!display) 497bf215546Sopenharmony_ci return -1; 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci registry = wl_display_get_registry(display); 500bf215546Sopenharmony_ci if (!registry) { 501bf215546Sopenharmony_ci if (!surface) 502bf215546Sopenharmony_ci wl_display_disconnect(display); 503bf215546Sopenharmony_ci return -1; 504bf215546Sopenharmony_ci } 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_ci static const struct wl_registry_listener registry_listener = { 507bf215546Sopenharmony_ci v3dv_registry_global, 508bf215546Sopenharmony_ci v3dv_registry_global_remove_cb 509bf215546Sopenharmony_ci }; 510bf215546Sopenharmony_ci wl_registry_add_listener(registry, ®istry_listener, &info); 511bf215546Sopenharmony_ci 512bf215546Sopenharmony_ci wl_display_roundtrip(display); /* For the registry advertisement */ 513bf215546Sopenharmony_ci wl_display_roundtrip(display); /* For the DRM device event */ 514bf215546Sopenharmony_ci wl_display_roundtrip(display); /* For the authentication event */ 515bf215546Sopenharmony_ci 516bf215546Sopenharmony_ci wl_drm_destroy(info.wl_drm); 517bf215546Sopenharmony_ci wl_registry_destroy(registry); 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci if (!surface) 520bf215546Sopenharmony_ci wl_display_disconnect(display); 521bf215546Sopenharmony_ci 522bf215546Sopenharmony_ci if (!info.is_set) 523bf215546Sopenharmony_ci return -1; 524bf215546Sopenharmony_ci 525bf215546Sopenharmony_ci if (!info.authenticated) 526bf215546Sopenharmony_ci return -1; 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci return info.fd; 529bf215546Sopenharmony_ci} 530bf215546Sopenharmony_ci#endif 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci/* Acquire an authenticated display fd without a surface reference. This is the 533bf215546Sopenharmony_ci * case where the application is making WSI allocations outside the Vulkan 534bf215546Sopenharmony_ci * swapchain context (only Zink, for now). Since we lack information about the 535bf215546Sopenharmony_ci * underlying surface we just try our best to figure out the correct display 536bf215546Sopenharmony_ci * and platform to use. It should work in most cases. 537bf215546Sopenharmony_ci */ 538bf215546Sopenharmony_cistatic void 539bf215546Sopenharmony_ciacquire_display_device_no_surface(struct v3dv_instance *instance, 540bf215546Sopenharmony_ci struct v3dv_physical_device *pdevice) 541bf215546Sopenharmony_ci{ 542bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WAYLAND_KHR 543bf215546Sopenharmony_ci pdevice->display_fd = create_display_fd_wayland(NULL); 544bf215546Sopenharmony_ci#endif 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XCB_KHR 547bf215546Sopenharmony_ci if (pdevice->display_fd == -1) 548bf215546Sopenharmony_ci pdevice->display_fd = create_display_fd_xcb(NULL); 549bf215546Sopenharmony_ci#endif 550bf215546Sopenharmony_ci 551bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_DISPLAY_KHR 552bf215546Sopenharmony_ci if (pdevice->display_fd == - 1 && pdevice->master_fd >= 0) 553bf215546Sopenharmony_ci pdevice->display_fd = dup(pdevice->master_fd); 554bf215546Sopenharmony_ci#endif 555bf215546Sopenharmony_ci} 556bf215546Sopenharmony_ci 557bf215546Sopenharmony_ci/* Acquire an authenticated display fd from the surface. This is the regular 558bf215546Sopenharmony_ci * case where the application is using swapchains to create WSI allocations. 559bf215546Sopenharmony_ci * In this case we use the surface information to figure out the correct 560bf215546Sopenharmony_ci * display and platform combination. 561bf215546Sopenharmony_ci */ 562bf215546Sopenharmony_cistatic void 563bf215546Sopenharmony_ciacquire_display_device_surface(struct v3dv_instance *instance, 564bf215546Sopenharmony_ci struct v3dv_physical_device *pdevice, 565bf215546Sopenharmony_ci VkIcdSurfaceBase *surface) 566bf215546Sopenharmony_ci{ 567bf215546Sopenharmony_ci /* Mesa will set both of VK_USE_PLATFORM_{XCB,XLIB} when building with 568bf215546Sopenharmony_ci * platform X11, so only check for XCB and rely on XCB to get an 569bf215546Sopenharmony_ci * authenticated device also for Xlib. 570bf215546Sopenharmony_ci */ 571bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XCB_KHR 572bf215546Sopenharmony_ci if (surface->platform == VK_ICD_WSI_PLATFORM_XCB || 573bf215546Sopenharmony_ci surface->platform == VK_ICD_WSI_PLATFORM_XLIB) { 574bf215546Sopenharmony_ci pdevice->display_fd = create_display_fd_xcb(surface); 575bf215546Sopenharmony_ci } 576bf215546Sopenharmony_ci#endif 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WAYLAND_KHR 579bf215546Sopenharmony_ci if (surface->platform == VK_ICD_WSI_PLATFORM_WAYLAND) 580bf215546Sopenharmony_ci pdevice->display_fd = create_display_fd_wayland(surface); 581bf215546Sopenharmony_ci#endif 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_DISPLAY_KHR 584bf215546Sopenharmony_ci if (surface->platform == VK_ICD_WSI_PLATFORM_DISPLAY && 585bf215546Sopenharmony_ci pdevice->master_fd >= 0) { 586bf215546Sopenharmony_ci pdevice->display_fd = dup(pdevice->master_fd); 587bf215546Sopenharmony_ci } 588bf215546Sopenharmony_ci#endif 589bf215546Sopenharmony_ci} 590bf215546Sopenharmony_ci#endif /* !using_v3d_simulator */ 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci/* Attempts to get an authenticated display fd from the display server that 593bf215546Sopenharmony_ci * we can use to allocate BOs for presentable images. 594bf215546Sopenharmony_ci */ 595bf215546Sopenharmony_ciVkResult 596bf215546Sopenharmony_civ3dv_physical_device_acquire_display(struct v3dv_instance *instance, 597bf215546Sopenharmony_ci struct v3dv_physical_device *pdevice, 598bf215546Sopenharmony_ci VkIcdSurfaceBase *surface) 599bf215546Sopenharmony_ci{ 600bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 601bf215546Sopenharmony_ci mtx_lock(&pdevice->mutex); 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci if (pdevice->display_fd != -1) 604bf215546Sopenharmony_ci goto done; 605bf215546Sopenharmony_ci 606bf215546Sopenharmony_ci /* When running on the simulator we do everything on a single render node so 607bf215546Sopenharmony_ci * we don't need to get an authenticated display fd from the display server. 608bf215546Sopenharmony_ci */ 609bf215546Sopenharmony_ci#if !using_v3d_simulator 610bf215546Sopenharmony_ci if (surface) 611bf215546Sopenharmony_ci acquire_display_device_surface(instance, pdevice, surface); 612bf215546Sopenharmony_ci else 613bf215546Sopenharmony_ci acquire_display_device_no_surface(instance, pdevice); 614bf215546Sopenharmony_ci 615bf215546Sopenharmony_ci if (pdevice->display_fd == -1) 616bf215546Sopenharmony_ci result = VK_ERROR_INITIALIZATION_FAILED; 617bf215546Sopenharmony_ci#endif 618bf215546Sopenharmony_ci 619bf215546Sopenharmony_cidone: 620bf215546Sopenharmony_ci mtx_unlock(&pdevice->mutex); 621bf215546Sopenharmony_ci return result; 622bf215546Sopenharmony_ci} 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_cistatic bool 625bf215546Sopenharmony_civ3d_has_feature(struct v3dv_physical_device *device, enum drm_v3d_param feature) 626bf215546Sopenharmony_ci{ 627bf215546Sopenharmony_ci struct drm_v3d_get_param p = { 628bf215546Sopenharmony_ci .param = feature, 629bf215546Sopenharmony_ci }; 630bf215546Sopenharmony_ci if (v3dv_ioctl(device->render_fd, DRM_IOCTL_V3D_GET_PARAM, &p) != 0) 631bf215546Sopenharmony_ci return false; 632bf215546Sopenharmony_ci return p.value; 633bf215546Sopenharmony_ci} 634bf215546Sopenharmony_ci 635bf215546Sopenharmony_cistatic bool 636bf215546Sopenharmony_cidevice_has_expected_features(struct v3dv_physical_device *device) 637bf215546Sopenharmony_ci{ 638bf215546Sopenharmony_ci return v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_TFU) && 639bf215546Sopenharmony_ci v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_CSD) && 640bf215546Sopenharmony_ci v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH); 641bf215546Sopenharmony_ci} 642bf215546Sopenharmony_ci 643bf215546Sopenharmony_ci 644bf215546Sopenharmony_cistatic VkResult 645bf215546Sopenharmony_ciinit_uuids(struct v3dv_physical_device *device) 646bf215546Sopenharmony_ci{ 647bf215546Sopenharmony_ci const struct build_id_note *note = 648bf215546Sopenharmony_ci build_id_find_nhdr_for_addr(init_uuids); 649bf215546Sopenharmony_ci if (!note) { 650bf215546Sopenharmony_ci return vk_errorf(device->vk.instance, 651bf215546Sopenharmony_ci VK_ERROR_INITIALIZATION_FAILED, 652bf215546Sopenharmony_ci "Failed to find build-id"); 653bf215546Sopenharmony_ci } 654bf215546Sopenharmony_ci 655bf215546Sopenharmony_ci unsigned build_id_len = build_id_length(note); 656bf215546Sopenharmony_ci if (build_id_len < 20) { 657bf215546Sopenharmony_ci return vk_errorf(device->vk.instance, 658bf215546Sopenharmony_ci VK_ERROR_INITIALIZATION_FAILED, 659bf215546Sopenharmony_ci "build-id too short. It needs to be a SHA"); 660bf215546Sopenharmony_ci } 661bf215546Sopenharmony_ci 662bf215546Sopenharmony_ci memcpy(device->driver_build_sha1, build_id_data(note), 20); 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci uint32_t vendor_id = v3dv_physical_device_vendor_id(device); 665bf215546Sopenharmony_ci uint32_t device_id = v3dv_physical_device_device_id(device); 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_ci struct mesa_sha1 sha1_ctx; 668bf215546Sopenharmony_ci uint8_t sha1[20]; 669bf215546Sopenharmony_ci STATIC_ASSERT(VK_UUID_SIZE <= sizeof(sha1)); 670bf215546Sopenharmony_ci 671bf215546Sopenharmony_ci /* The pipeline cache UUID is used for determining when a pipeline cache is 672bf215546Sopenharmony_ci * invalid. It needs both a driver build and the PCI ID of the device. 673bf215546Sopenharmony_ci */ 674bf215546Sopenharmony_ci _mesa_sha1_init(&sha1_ctx); 675bf215546Sopenharmony_ci _mesa_sha1_update(&sha1_ctx, build_id_data(note), build_id_len); 676bf215546Sopenharmony_ci _mesa_sha1_update(&sha1_ctx, &device_id, sizeof(device_id)); 677bf215546Sopenharmony_ci _mesa_sha1_final(&sha1_ctx, sha1); 678bf215546Sopenharmony_ci memcpy(device->pipeline_cache_uuid, sha1, VK_UUID_SIZE); 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci /* The driver UUID is used for determining sharability of images and memory 681bf215546Sopenharmony_ci * between two Vulkan instances in separate processes. People who want to 682bf215546Sopenharmony_ci * share memory need to also check the device UUID (below) so all this 683bf215546Sopenharmony_ci * needs to be is the build-id. 684bf215546Sopenharmony_ci */ 685bf215546Sopenharmony_ci memcpy(device->driver_uuid, build_id_data(note), VK_UUID_SIZE); 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci /* The device UUID uniquely identifies the given device within the machine. 688bf215546Sopenharmony_ci * Since we never have more than one device, this doesn't need to be a real 689bf215546Sopenharmony_ci * UUID. 690bf215546Sopenharmony_ci */ 691bf215546Sopenharmony_ci _mesa_sha1_init(&sha1_ctx); 692bf215546Sopenharmony_ci _mesa_sha1_update(&sha1_ctx, &vendor_id, sizeof(vendor_id)); 693bf215546Sopenharmony_ci _mesa_sha1_update(&sha1_ctx, &device_id, sizeof(device_id)); 694bf215546Sopenharmony_ci _mesa_sha1_final(&sha1_ctx, sha1); 695bf215546Sopenharmony_ci memcpy(device->device_uuid, sha1, VK_UUID_SIZE); 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_ci return VK_SUCCESS; 698bf215546Sopenharmony_ci} 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_cistatic void 701bf215546Sopenharmony_civ3dv_physical_device_init_disk_cache(struct v3dv_physical_device *device) 702bf215546Sopenharmony_ci{ 703bf215546Sopenharmony_ci#ifdef ENABLE_SHADER_CACHE 704bf215546Sopenharmony_ci char timestamp[41]; 705bf215546Sopenharmony_ci _mesa_sha1_format(timestamp, device->driver_build_sha1); 706bf215546Sopenharmony_ci 707bf215546Sopenharmony_ci assert(device->name); 708bf215546Sopenharmony_ci device->disk_cache = disk_cache_create(device->name, timestamp, 0); 709bf215546Sopenharmony_ci#else 710bf215546Sopenharmony_ci device->disk_cache = NULL; 711bf215546Sopenharmony_ci#endif 712bf215546Sopenharmony_ci} 713bf215546Sopenharmony_ci 714bf215546Sopenharmony_cistatic VkResult 715bf215546Sopenharmony_ciphysical_device_init(struct v3dv_physical_device *device, 716bf215546Sopenharmony_ci struct v3dv_instance *instance, 717bf215546Sopenharmony_ci drmDevicePtr drm_render_device, 718bf215546Sopenharmony_ci drmDevicePtr drm_primary_device) 719bf215546Sopenharmony_ci{ 720bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 721bf215546Sopenharmony_ci int32_t master_fd = -1; 722bf215546Sopenharmony_ci int32_t render_fd = -1; 723bf215546Sopenharmony_ci 724bf215546Sopenharmony_ci struct vk_physical_device_dispatch_table dispatch_table; 725bf215546Sopenharmony_ci vk_physical_device_dispatch_table_from_entrypoints 726bf215546Sopenharmony_ci (&dispatch_table, &v3dv_physical_device_entrypoints, true); 727bf215546Sopenharmony_ci vk_physical_device_dispatch_table_from_entrypoints( 728bf215546Sopenharmony_ci &dispatch_table, &wsi_physical_device_entrypoints, false); 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci result = vk_physical_device_init(&device->vk, &instance->vk, NULL, 731bf215546Sopenharmony_ci &dispatch_table); 732bf215546Sopenharmony_ci 733bf215546Sopenharmony_ci if (result != VK_SUCCESS) 734bf215546Sopenharmony_ci goto fail; 735bf215546Sopenharmony_ci 736bf215546Sopenharmony_ci assert(drm_render_device); 737bf215546Sopenharmony_ci const char *path = drm_render_device->nodes[DRM_NODE_RENDER]; 738bf215546Sopenharmony_ci render_fd = open(path, O_RDWR | O_CLOEXEC); 739bf215546Sopenharmony_ci if (render_fd < 0) { 740bf215546Sopenharmony_ci fprintf(stderr, "Opening %s failed: %s\n", path, strerror(errno)); 741bf215546Sopenharmony_ci result = VK_ERROR_INCOMPATIBLE_DRIVER; 742bf215546Sopenharmony_ci goto fail; 743bf215546Sopenharmony_ci } 744bf215546Sopenharmony_ci 745bf215546Sopenharmony_ci /* If we are running on VK_KHR_display we need to acquire the master 746bf215546Sopenharmony_ci * display device now for the v3dv_wsi_init() call below. For anything else 747bf215546Sopenharmony_ci * we postpone that until a swapchain is created. 748bf215546Sopenharmony_ci */ 749bf215546Sopenharmony_ci 750bf215546Sopenharmony_ci const char *primary_path; 751bf215546Sopenharmony_ci#if !using_v3d_simulator 752bf215546Sopenharmony_ci if (drm_primary_device) 753bf215546Sopenharmony_ci primary_path = drm_primary_device->nodes[DRM_NODE_PRIMARY]; 754bf215546Sopenharmony_ci else 755bf215546Sopenharmony_ci primary_path = NULL; 756bf215546Sopenharmony_ci#else 757bf215546Sopenharmony_ci primary_path = drm_render_device->nodes[DRM_NODE_PRIMARY]; 758bf215546Sopenharmony_ci#endif 759bf215546Sopenharmony_ci 760bf215546Sopenharmony_ci struct stat primary_stat = {0}, render_stat = {0}; 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci device->has_primary = primary_path; 763bf215546Sopenharmony_ci if (device->has_primary) { 764bf215546Sopenharmony_ci if (stat(primary_path, &primary_stat) != 0) { 765bf215546Sopenharmony_ci result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED, 766bf215546Sopenharmony_ci "failed to stat DRM primary node %s", 767bf215546Sopenharmony_ci primary_path); 768bf215546Sopenharmony_ci goto fail; 769bf215546Sopenharmony_ci } 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci device->primary_devid = primary_stat.st_rdev; 772bf215546Sopenharmony_ci } 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci if (fstat(render_fd, &render_stat) != 0) { 775bf215546Sopenharmony_ci result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED, 776bf215546Sopenharmony_ci "failed to stat DRM render node %s", 777bf215546Sopenharmony_ci path); 778bf215546Sopenharmony_ci goto fail; 779bf215546Sopenharmony_ci } 780bf215546Sopenharmony_ci device->has_render = true; 781bf215546Sopenharmony_ci device->render_devid = render_stat.st_rdev; 782bf215546Sopenharmony_ci 783bf215546Sopenharmony_ci#if using_v3d_simulator 784bf215546Sopenharmony_ci device->device_id = drm_render_device->deviceinfo.pci->device_id; 785bf215546Sopenharmony_ci#endif 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_ci if (instance->vk.enabled_extensions.KHR_display) { 788bf215546Sopenharmony_ci#if !using_v3d_simulator 789bf215546Sopenharmony_ci /* Open the primary node on the vc4 display device */ 790bf215546Sopenharmony_ci assert(drm_primary_device); 791bf215546Sopenharmony_ci master_fd = open(primary_path, O_RDWR | O_CLOEXEC); 792bf215546Sopenharmony_ci#else 793bf215546Sopenharmony_ci /* There is only one device with primary and render nodes. 794bf215546Sopenharmony_ci * Open its primary node. 795bf215546Sopenharmony_ci */ 796bf215546Sopenharmony_ci master_fd = open(primary_path, O_RDWR | O_CLOEXEC); 797bf215546Sopenharmony_ci#endif 798bf215546Sopenharmony_ci } 799bf215546Sopenharmony_ci 800bf215546Sopenharmony_ci#if using_v3d_simulator 801bf215546Sopenharmony_ci device->sim_file = v3d_simulator_init(render_fd); 802bf215546Sopenharmony_ci#endif 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci device->render_fd = render_fd; /* The v3d render node */ 805bf215546Sopenharmony_ci device->display_fd = -1; /* Authenticated vc4 primary node */ 806bf215546Sopenharmony_ci device->master_fd = master_fd; /* Master vc4 primary node */ 807bf215546Sopenharmony_ci 808bf215546Sopenharmony_ci if (!v3d_get_device_info(device->render_fd, &device->devinfo, &v3dv_ioctl)) { 809bf215546Sopenharmony_ci result = VK_ERROR_INCOMPATIBLE_DRIVER; 810bf215546Sopenharmony_ci goto fail; 811bf215546Sopenharmony_ci } 812bf215546Sopenharmony_ci 813bf215546Sopenharmony_ci if (device->devinfo.ver < 42) { 814bf215546Sopenharmony_ci result = VK_ERROR_INCOMPATIBLE_DRIVER; 815bf215546Sopenharmony_ci goto fail; 816bf215546Sopenharmony_ci } 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_ci if (!device_has_expected_features(device)) { 819bf215546Sopenharmony_ci result = VK_ERROR_INCOMPATIBLE_DRIVER; 820bf215546Sopenharmony_ci goto fail; 821bf215546Sopenharmony_ci } 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci device->caps.multisync = 824bf215546Sopenharmony_ci v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT); 825bf215546Sopenharmony_ci 826bf215546Sopenharmony_ci device->caps.perfmon = 827bf215546Sopenharmony_ci v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_PERFMON); 828bf215546Sopenharmony_ci 829bf215546Sopenharmony_ci result = init_uuids(device); 830bf215546Sopenharmony_ci if (result != VK_SUCCESS) 831bf215546Sopenharmony_ci goto fail; 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_ci device->compiler = v3d_compiler_init(&device->devinfo, 834bf215546Sopenharmony_ci MAX_INLINE_UNIFORM_BUFFERS); 835bf215546Sopenharmony_ci device->next_program_id = 0; 836bf215546Sopenharmony_ci 837bf215546Sopenharmony_ci ASSERTED int len = 838bf215546Sopenharmony_ci asprintf(&device->name, "V3D %d.%d", 839bf215546Sopenharmony_ci device->devinfo.ver / 10, device->devinfo.ver % 10); 840bf215546Sopenharmony_ci assert(len != -1); 841bf215546Sopenharmony_ci 842bf215546Sopenharmony_ci v3dv_physical_device_init_disk_cache(device); 843bf215546Sopenharmony_ci 844bf215546Sopenharmony_ci /* Setup available memory heaps and types */ 845bf215546Sopenharmony_ci VkPhysicalDeviceMemoryProperties *mem = &device->memory; 846bf215546Sopenharmony_ci mem->memoryHeapCount = 1; 847bf215546Sopenharmony_ci mem->memoryHeaps[0].size = compute_heap_size(); 848bf215546Sopenharmony_ci mem->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; 849bf215546Sopenharmony_ci 850bf215546Sopenharmony_ci /* This is the only combination required by the spec */ 851bf215546Sopenharmony_ci mem->memoryTypeCount = 1; 852bf215546Sopenharmony_ci mem->memoryTypes[0].propertyFlags = 853bf215546Sopenharmony_ci VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | 854bf215546Sopenharmony_ci VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 855bf215546Sopenharmony_ci VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; 856bf215546Sopenharmony_ci mem->memoryTypes[0].heapIndex = 0; 857bf215546Sopenharmony_ci 858bf215546Sopenharmony_ci /* Initialize sparse array for refcounting imported BOs */ 859bf215546Sopenharmony_ci util_sparse_array_init(&device->bo_map, sizeof(struct v3dv_bo), 512); 860bf215546Sopenharmony_ci 861bf215546Sopenharmony_ci device->options.merge_jobs = !(V3D_DEBUG & V3D_DEBUG_NO_MERGE_JOBS); 862bf215546Sopenharmony_ci 863bf215546Sopenharmony_ci device->drm_syncobj_type = vk_drm_syncobj_get_type(device->render_fd); 864bf215546Sopenharmony_ci 865bf215546Sopenharmony_ci /* We don't support timelines in the uAPI yet and we don't want it getting 866bf215546Sopenharmony_ci * suddenly turned on by vk_drm_syncobj_get_type() without us adding v3dv 867bf215546Sopenharmony_ci * code for it first. 868bf215546Sopenharmony_ci */ 869bf215546Sopenharmony_ci device->drm_syncobj_type.features &= ~VK_SYNC_FEATURE_TIMELINE; 870bf215546Sopenharmony_ci 871bf215546Sopenharmony_ci#ifndef ANDROID 872bf215546Sopenharmony_ci /* Sync file export is incompatible with the current model of execution 873bf215546Sopenharmony_ci * where some jobs may run on the CPU. There are CTS tests which do the 874bf215546Sopenharmony_ci * following: 875bf215546Sopenharmony_ci * 876bf215546Sopenharmony_ci * 1. Create a command buffer with a vkCmdWaitEvents() 877bf215546Sopenharmony_ci * 2. Submit the command buffer 878bf215546Sopenharmony_ci * 3. vkGetSemaphoreFdKHR() to try to get a sync_file 879bf215546Sopenharmony_ci * 4. vkSetEvent() 880bf215546Sopenharmony_ci * 881bf215546Sopenharmony_ci * This deadlocks because we have to wait for the syncobj to get a real 882bf215546Sopenharmony_ci * fence in vkGetSemaphoreFdKHR() which only happens after all the work 883bf215546Sopenharmony_ci * from the command buffer is complete which only happens after 884bf215546Sopenharmony_ci * vkSetEvent(). No amount of CPU threading in userspace will ever fix 885bf215546Sopenharmony_ci * this. Sadly, this is pretty explicitly allowed by the Vulkan spec: 886bf215546Sopenharmony_ci * 887bf215546Sopenharmony_ci * VUID-vkCmdWaitEvents-pEvents-01163 888bf215546Sopenharmony_ci * 889bf215546Sopenharmony_ci * "If pEvents includes one or more events that will be signaled by 890bf215546Sopenharmony_ci * vkSetEvent after commandBuffer has been submitted to a queue, then 891bf215546Sopenharmony_ci * vkCmdWaitEvents must not be called inside a render pass instance" 892bf215546Sopenharmony_ci * 893bf215546Sopenharmony_ci * Disable sync file support for now. 894bf215546Sopenharmony_ci */ 895bf215546Sopenharmony_ci device->drm_syncobj_type.import_sync_file = NULL; 896bf215546Sopenharmony_ci device->drm_syncobj_type.export_sync_file = NULL; 897bf215546Sopenharmony_ci#endif 898bf215546Sopenharmony_ci 899bf215546Sopenharmony_ci /* Multiwait is required for emulated timeline semaphores and is supported 900bf215546Sopenharmony_ci * by the v3d kernel interface. 901bf215546Sopenharmony_ci */ 902bf215546Sopenharmony_ci device->drm_syncobj_type.features |= VK_SYNC_FEATURE_GPU_MULTI_WAIT; 903bf215546Sopenharmony_ci 904bf215546Sopenharmony_ci device->sync_timeline_type = 905bf215546Sopenharmony_ci vk_sync_timeline_get_type(&device->drm_syncobj_type); 906bf215546Sopenharmony_ci 907bf215546Sopenharmony_ci device->sync_types[0] = &device->drm_syncobj_type; 908bf215546Sopenharmony_ci device->sync_types[1] = &device->sync_timeline_type.sync; 909bf215546Sopenharmony_ci device->sync_types[2] = NULL; 910bf215546Sopenharmony_ci device->vk.supported_sync_types = device->sync_types; 911bf215546Sopenharmony_ci 912bf215546Sopenharmony_ci result = v3dv_wsi_init(device); 913bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 914bf215546Sopenharmony_ci vk_error(instance, result); 915bf215546Sopenharmony_ci goto fail; 916bf215546Sopenharmony_ci } 917bf215546Sopenharmony_ci 918bf215546Sopenharmony_ci get_device_extensions(device, &device->vk.supported_extensions); 919bf215546Sopenharmony_ci 920bf215546Sopenharmony_ci mtx_init(&device->mutex, mtx_plain); 921bf215546Sopenharmony_ci 922bf215546Sopenharmony_ci return VK_SUCCESS; 923bf215546Sopenharmony_ci 924bf215546Sopenharmony_cifail: 925bf215546Sopenharmony_ci vk_physical_device_finish(&device->vk); 926bf215546Sopenharmony_ci 927bf215546Sopenharmony_ci if (render_fd >= 0) 928bf215546Sopenharmony_ci close(render_fd); 929bf215546Sopenharmony_ci if (master_fd >= 0) 930bf215546Sopenharmony_ci close(master_fd); 931bf215546Sopenharmony_ci 932bf215546Sopenharmony_ci return result; 933bf215546Sopenharmony_ci} 934bf215546Sopenharmony_ci 935bf215546Sopenharmony_cistatic VkResult 936bf215546Sopenharmony_cienumerate_devices(struct v3dv_instance *instance) 937bf215546Sopenharmony_ci{ 938bf215546Sopenharmony_ci /* TODO: Check for more devices? */ 939bf215546Sopenharmony_ci drmDevicePtr devices[8]; 940bf215546Sopenharmony_ci VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER; 941bf215546Sopenharmony_ci int max_devices; 942bf215546Sopenharmony_ci 943bf215546Sopenharmony_ci instance->physicalDeviceCount = 0; 944bf215546Sopenharmony_ci 945bf215546Sopenharmony_ci max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices)); 946bf215546Sopenharmony_ci if (max_devices < 1) 947bf215546Sopenharmony_ci return VK_ERROR_INCOMPATIBLE_DRIVER; 948bf215546Sopenharmony_ci 949bf215546Sopenharmony_ci#if !using_v3d_simulator 950bf215546Sopenharmony_ci int32_t v3d_idx = -1; 951bf215546Sopenharmony_ci int32_t vc4_idx = -1; 952bf215546Sopenharmony_ci#endif 953bf215546Sopenharmony_ci for (unsigned i = 0; i < (unsigned)max_devices; i++) { 954bf215546Sopenharmony_ci#if using_v3d_simulator 955bf215546Sopenharmony_ci /* In the simulator, we look for an Intel/AMD render node */ 956bf215546Sopenharmony_ci const int required_nodes = (1 << DRM_NODE_RENDER) | (1 << DRM_NODE_PRIMARY); 957bf215546Sopenharmony_ci if ((devices[i]->available_nodes & required_nodes) == required_nodes && 958bf215546Sopenharmony_ci devices[i]->bustype == DRM_BUS_PCI && 959bf215546Sopenharmony_ci (devices[i]->deviceinfo.pci->vendor_id == 0x8086 || 960bf215546Sopenharmony_ci devices[i]->deviceinfo.pci->vendor_id == 0x1002)) { 961bf215546Sopenharmony_ci result = physical_device_init(&instance->physicalDevice, instance, 962bf215546Sopenharmony_ci devices[i], NULL); 963bf215546Sopenharmony_ci if (result != VK_ERROR_INCOMPATIBLE_DRIVER) 964bf215546Sopenharmony_ci break; 965bf215546Sopenharmony_ci } 966bf215546Sopenharmony_ci#else 967bf215546Sopenharmony_ci /* On actual hardware, we should have a render node (v3d) 968bf215546Sopenharmony_ci * and a primary node (vc4). We will need to use the primary 969bf215546Sopenharmony_ci * to allocate WSI buffers and share them with the render node 970bf215546Sopenharmony_ci * via prime, but that is a privileged operation so we need the 971bf215546Sopenharmony_ci * primary node to be authenticated, and for that we need the 972bf215546Sopenharmony_ci * display server to provide the device fd (with DRI3), so we 973bf215546Sopenharmony_ci * here we only check that the device is present but we don't 974bf215546Sopenharmony_ci * try to open it. 975bf215546Sopenharmony_ci */ 976bf215546Sopenharmony_ci if (devices[i]->bustype != DRM_BUS_PLATFORM) 977bf215546Sopenharmony_ci continue; 978bf215546Sopenharmony_ci 979bf215546Sopenharmony_ci if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER) { 980bf215546Sopenharmony_ci char **compat = devices[i]->deviceinfo.platform->compatible; 981bf215546Sopenharmony_ci while (*compat) { 982bf215546Sopenharmony_ci if (strncmp(*compat, "brcm,2711-v3d", 13) == 0) { 983bf215546Sopenharmony_ci v3d_idx = i; 984bf215546Sopenharmony_ci break; 985bf215546Sopenharmony_ci } 986bf215546Sopenharmony_ci compat++; 987bf215546Sopenharmony_ci } 988bf215546Sopenharmony_ci } else if (devices[i]->available_nodes & 1 << DRM_NODE_PRIMARY) { 989bf215546Sopenharmony_ci char **compat = devices[i]->deviceinfo.platform->compatible; 990bf215546Sopenharmony_ci while (*compat) { 991bf215546Sopenharmony_ci if (strncmp(*compat, "brcm,bcm2711-vc5", 16) == 0 || 992bf215546Sopenharmony_ci strncmp(*compat, "brcm,bcm2835-vc4", 16) == 0 ) { 993bf215546Sopenharmony_ci vc4_idx = i; 994bf215546Sopenharmony_ci break; 995bf215546Sopenharmony_ci } 996bf215546Sopenharmony_ci compat++; 997bf215546Sopenharmony_ci } 998bf215546Sopenharmony_ci } 999bf215546Sopenharmony_ci#endif 1000bf215546Sopenharmony_ci } 1001bf215546Sopenharmony_ci 1002bf215546Sopenharmony_ci#if !using_v3d_simulator 1003bf215546Sopenharmony_ci if (v3d_idx == -1 || vc4_idx == -1) 1004bf215546Sopenharmony_ci result = VK_ERROR_INCOMPATIBLE_DRIVER; 1005bf215546Sopenharmony_ci else 1006bf215546Sopenharmony_ci result = physical_device_init(&instance->physicalDevice, instance, 1007bf215546Sopenharmony_ci devices[v3d_idx], devices[vc4_idx]); 1008bf215546Sopenharmony_ci#endif 1009bf215546Sopenharmony_ci 1010bf215546Sopenharmony_ci drmFreeDevices(devices, max_devices); 1011bf215546Sopenharmony_ci 1012bf215546Sopenharmony_ci if (result == VK_SUCCESS) 1013bf215546Sopenharmony_ci instance->physicalDeviceCount = 1; 1014bf215546Sopenharmony_ci 1015bf215546Sopenharmony_ci return result; 1016bf215546Sopenharmony_ci} 1017bf215546Sopenharmony_ci 1018bf215546Sopenharmony_cistatic VkResult 1019bf215546Sopenharmony_ciinstance_ensure_physical_device(struct v3dv_instance *instance) 1020bf215546Sopenharmony_ci{ 1021bf215546Sopenharmony_ci if (instance->physicalDeviceCount < 0) { 1022bf215546Sopenharmony_ci VkResult result = enumerate_devices(instance); 1023bf215546Sopenharmony_ci if (result != VK_SUCCESS && 1024bf215546Sopenharmony_ci result != VK_ERROR_INCOMPATIBLE_DRIVER) 1025bf215546Sopenharmony_ci return result; 1026bf215546Sopenharmony_ci } 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_ci return VK_SUCCESS; 1029bf215546Sopenharmony_ci} 1030bf215546Sopenharmony_ci 1031bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 1032bf215546Sopenharmony_civ3dv_EnumeratePhysicalDevices(VkInstance _instance, 1033bf215546Sopenharmony_ci uint32_t *pPhysicalDeviceCount, 1034bf215546Sopenharmony_ci VkPhysicalDevice *pPhysicalDevices) 1035bf215546Sopenharmony_ci{ 1036bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 1037bf215546Sopenharmony_ci VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out, 1038bf215546Sopenharmony_ci pPhysicalDevices, pPhysicalDeviceCount); 1039bf215546Sopenharmony_ci 1040bf215546Sopenharmony_ci VkResult result = instance_ensure_physical_device(instance); 1041bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1042bf215546Sopenharmony_ci return result; 1043bf215546Sopenharmony_ci 1044bf215546Sopenharmony_ci if (instance->physicalDeviceCount == 0) 1045bf215546Sopenharmony_ci return VK_SUCCESS; 1046bf215546Sopenharmony_ci 1047bf215546Sopenharmony_ci assert(instance->physicalDeviceCount == 1); 1048bf215546Sopenharmony_ci vk_outarray_append_typed(VkPhysicalDevice, &out, i) { 1049bf215546Sopenharmony_ci *i = v3dv_physical_device_to_handle(&instance->physicalDevice); 1050bf215546Sopenharmony_ci } 1051bf215546Sopenharmony_ci 1052bf215546Sopenharmony_ci return vk_outarray_status(&out); 1053bf215546Sopenharmony_ci} 1054bf215546Sopenharmony_ci 1055bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 1056bf215546Sopenharmony_civ3dv_EnumeratePhysicalDeviceGroups( 1057bf215546Sopenharmony_ci VkInstance _instance, 1058bf215546Sopenharmony_ci uint32_t *pPhysicalDeviceGroupCount, 1059bf215546Sopenharmony_ci VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties) 1060bf215546Sopenharmony_ci{ 1061bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 1062bf215546Sopenharmony_ci VK_OUTARRAY_MAKE_TYPED(VkPhysicalDeviceGroupProperties, out, 1063bf215546Sopenharmony_ci pPhysicalDeviceGroupProperties, 1064bf215546Sopenharmony_ci pPhysicalDeviceGroupCount); 1065bf215546Sopenharmony_ci 1066bf215546Sopenharmony_ci VkResult result = instance_ensure_physical_device(instance); 1067bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1068bf215546Sopenharmony_ci return result; 1069bf215546Sopenharmony_ci 1070bf215546Sopenharmony_ci assert(instance->physicalDeviceCount == 1); 1071bf215546Sopenharmony_ci 1072bf215546Sopenharmony_ci vk_outarray_append_typed(VkPhysicalDeviceGroupProperties, &out, p) { 1073bf215546Sopenharmony_ci p->physicalDeviceCount = 1; 1074bf215546Sopenharmony_ci memset(p->physicalDevices, 0, sizeof(p->physicalDevices)); 1075bf215546Sopenharmony_ci p->physicalDevices[0] = 1076bf215546Sopenharmony_ci v3dv_physical_device_to_handle(&instance->physicalDevice); 1077bf215546Sopenharmony_ci p->subsetAllocation = false; 1078bf215546Sopenharmony_ci 1079bf215546Sopenharmony_ci vk_foreach_struct(ext, p->pNext) 1080bf215546Sopenharmony_ci v3dv_debug_ignored_stype(ext->sType); 1081bf215546Sopenharmony_ci } 1082bf215546Sopenharmony_ci 1083bf215546Sopenharmony_ci return vk_outarray_status(&out); 1084bf215546Sopenharmony_ci} 1085bf215546Sopenharmony_ci 1086bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1087bf215546Sopenharmony_civ3dv_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, 1088bf215546Sopenharmony_ci VkPhysicalDeviceFeatures *pFeatures) 1089bf215546Sopenharmony_ci{ 1090bf215546Sopenharmony_ci memset(pFeatures, 0, sizeof(*pFeatures)); 1091bf215546Sopenharmony_ci 1092bf215546Sopenharmony_ci *pFeatures = (VkPhysicalDeviceFeatures) { 1093bf215546Sopenharmony_ci .robustBufferAccess = true, /* This feature is mandatory */ 1094bf215546Sopenharmony_ci .fullDrawIndexUint32 = false, /* Only available since V3D 4.4.9.1 */ 1095bf215546Sopenharmony_ci .imageCubeArray = true, 1096bf215546Sopenharmony_ci .independentBlend = true, 1097bf215546Sopenharmony_ci .geometryShader = true, 1098bf215546Sopenharmony_ci .tessellationShader = false, 1099bf215546Sopenharmony_ci .sampleRateShading = true, 1100bf215546Sopenharmony_ci .dualSrcBlend = false, 1101bf215546Sopenharmony_ci .logicOp = true, 1102bf215546Sopenharmony_ci .multiDrawIndirect = false, 1103bf215546Sopenharmony_ci .drawIndirectFirstInstance = true, 1104bf215546Sopenharmony_ci .depthClamp = false, /* Only available since V3D 4.5.1.1 */ 1105bf215546Sopenharmony_ci .depthBiasClamp = true, 1106bf215546Sopenharmony_ci .fillModeNonSolid = true, 1107bf215546Sopenharmony_ci .depthBounds = false, /* Only available since V3D 4.3.16.2 */ 1108bf215546Sopenharmony_ci .wideLines = true, 1109bf215546Sopenharmony_ci .largePoints = true, 1110bf215546Sopenharmony_ci .alphaToOne = true, 1111bf215546Sopenharmony_ci .multiViewport = false, 1112bf215546Sopenharmony_ci .samplerAnisotropy = true, 1113bf215546Sopenharmony_ci .textureCompressionETC2 = true, 1114bf215546Sopenharmony_ci .textureCompressionASTC_LDR = true, 1115bf215546Sopenharmony_ci /* Note that textureCompressionBC requires that the driver support all 1116bf215546Sopenharmony_ci * the BC formats. V3D 4.2 only support the BC1-3, so we can't claim 1117bf215546Sopenharmony_ci * that we support it. 1118bf215546Sopenharmony_ci */ 1119bf215546Sopenharmony_ci .textureCompressionBC = false, 1120bf215546Sopenharmony_ci .occlusionQueryPrecise = true, 1121bf215546Sopenharmony_ci .pipelineStatisticsQuery = false, 1122bf215546Sopenharmony_ci .vertexPipelineStoresAndAtomics = true, 1123bf215546Sopenharmony_ci .fragmentStoresAndAtomics = true, 1124bf215546Sopenharmony_ci .shaderTessellationAndGeometryPointSize = true, 1125bf215546Sopenharmony_ci .shaderImageGatherExtended = false, 1126bf215546Sopenharmony_ci .shaderStorageImageExtendedFormats = true, 1127bf215546Sopenharmony_ci .shaderStorageImageMultisample = false, 1128bf215546Sopenharmony_ci .shaderStorageImageReadWithoutFormat = false, 1129bf215546Sopenharmony_ci .shaderStorageImageWriteWithoutFormat = false, 1130bf215546Sopenharmony_ci .shaderUniformBufferArrayDynamicIndexing = false, 1131bf215546Sopenharmony_ci .shaderSampledImageArrayDynamicIndexing = false, 1132bf215546Sopenharmony_ci .shaderStorageBufferArrayDynamicIndexing = false, 1133bf215546Sopenharmony_ci .shaderStorageImageArrayDynamicIndexing = false, 1134bf215546Sopenharmony_ci .shaderClipDistance = true, 1135bf215546Sopenharmony_ci .shaderCullDistance = false, 1136bf215546Sopenharmony_ci .shaderFloat64 = false, 1137bf215546Sopenharmony_ci .shaderInt64 = false, 1138bf215546Sopenharmony_ci .shaderInt16 = false, 1139bf215546Sopenharmony_ci .shaderResourceResidency = false, 1140bf215546Sopenharmony_ci .shaderResourceMinLod = false, 1141bf215546Sopenharmony_ci .sparseBinding = false, 1142bf215546Sopenharmony_ci .sparseResidencyBuffer = false, 1143bf215546Sopenharmony_ci .sparseResidencyImage2D = false, 1144bf215546Sopenharmony_ci .sparseResidencyImage3D = false, 1145bf215546Sopenharmony_ci .sparseResidency2Samples = false, 1146bf215546Sopenharmony_ci .sparseResidency4Samples = false, 1147bf215546Sopenharmony_ci .sparseResidency8Samples = false, 1148bf215546Sopenharmony_ci .sparseResidency16Samples = false, 1149bf215546Sopenharmony_ci .sparseResidencyAliased = false, 1150bf215546Sopenharmony_ci .variableMultisampleRate = false, 1151bf215546Sopenharmony_ci .inheritedQueries = true, 1152bf215546Sopenharmony_ci }; 1153bf215546Sopenharmony_ci} 1154bf215546Sopenharmony_ci 1155bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1156bf215546Sopenharmony_civ3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, 1157bf215546Sopenharmony_ci VkPhysicalDeviceFeatures2 *pFeatures) 1158bf215546Sopenharmony_ci{ 1159bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice); 1160bf215546Sopenharmony_ci v3dv_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features); 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_ci VkPhysicalDeviceVulkan13Features vk13 = { 1163bf215546Sopenharmony_ci .inlineUniformBlock = true, 1164bf215546Sopenharmony_ci /* Inline buffers work like push constants, so after their are bound 1165bf215546Sopenharmony_ci * some of their contents may be copied into the uniform stream as soon 1166bf215546Sopenharmony_ci * as the next draw/dispatch is recorded in the command buffer. This means 1167bf215546Sopenharmony_ci * that if the client updates the buffer contents after binding it to 1168bf215546Sopenharmony_ci * a command buffer, the next queue submit of that command buffer may 1169bf215546Sopenharmony_ci * not use the latest update to the buffer contents, but the data that 1170bf215546Sopenharmony_ci * was present in the buffer at the time it was bound to the command 1171bf215546Sopenharmony_ci * buffer. 1172bf215546Sopenharmony_ci */ 1173bf215546Sopenharmony_ci .descriptorBindingInlineUniformBlockUpdateAfterBind = false, 1174bf215546Sopenharmony_ci .pipelineCreationCacheControl = true, 1175bf215546Sopenharmony_ci .privateData = true, 1176bf215546Sopenharmony_ci }; 1177bf215546Sopenharmony_ci 1178bf215546Sopenharmony_ci VkPhysicalDeviceVulkan12Features vk12 = { 1179bf215546Sopenharmony_ci .hostQueryReset = true, 1180bf215546Sopenharmony_ci .uniformAndStorageBuffer8BitAccess = true, 1181bf215546Sopenharmony_ci .uniformBufferStandardLayout = true, 1182bf215546Sopenharmony_ci /* V3D 4.2 wraps TMU vector accesses to 16-byte boundaries, so loads and 1183bf215546Sopenharmony_ci * stores of vectors that cross these boundaries would not work correcly 1184bf215546Sopenharmony_ci * with scalarBlockLayout and would need to be split into smaller vectors 1185bf215546Sopenharmony_ci * (and/or scalars) that don't cross these boundaries. For load/stores 1186bf215546Sopenharmony_ci * with dynamic offsets where we can't identify if the offset is 1187bf215546Sopenharmony_ci * problematic, we would always have to scalarize. Overall, this would 1188bf215546Sopenharmony_ci * not lead to best performance so let's just not support it. 1189bf215546Sopenharmony_ci */ 1190bf215546Sopenharmony_ci .scalarBlockLayout = false, 1191bf215546Sopenharmony_ci /* This tells applications 2 things: 1192bf215546Sopenharmony_ci * 1193bf215546Sopenharmony_ci * 1. If they can select just one aspect for barriers. For us barriers 1194bf215546Sopenharmony_ci * decide if we need to split a job and we don't care if it is only 1195bf215546Sopenharmony_ci * for one of the aspects of the image or both, so we don't really 1196bf215546Sopenharmony_ci * benefit from seeing barriers that select just one aspect. 1197bf215546Sopenharmony_ci * 1198bf215546Sopenharmony_ci * 2. If they can program different layouts for each aspect. We 1199bf215546Sopenharmony_ci * generally don't care about layouts, so again, we don't get any 1200bf215546Sopenharmony_ci * benefits from this to limit the scope of image layout transitions. 1201bf215546Sopenharmony_ci * 1202bf215546Sopenharmony_ci * Still, Vulkan 1.2 requires this feature to be supported so we 1203bf215546Sopenharmony_ci * advertise it even though we don't really take advantage of it. 1204bf215546Sopenharmony_ci */ 1205bf215546Sopenharmony_ci .separateDepthStencilLayouts = true, 1206bf215546Sopenharmony_ci .storageBuffer8BitAccess = true, 1207bf215546Sopenharmony_ci .storagePushConstant8 = true, 1208bf215546Sopenharmony_ci .imagelessFramebuffer = true, 1209bf215546Sopenharmony_ci .timelineSemaphore = true, 1210bf215546Sopenharmony_ci 1211bf215546Sopenharmony_ci .samplerMirrorClampToEdge = true, 1212bf215546Sopenharmony_ci 1213bf215546Sopenharmony_ci /* These are mandatory by Vulkan 1.2, however, we don't support any of 1214bf215546Sopenharmony_ci * the optional features affected by them (non 32-bit types for 1215bf215546Sopenharmony_ci * shaderSubgroupExtendedTypes and additional subgroup ballot for 1216bf215546Sopenharmony_ci * subgroupBroadcastDynamicId), so in practice setting them to true 1217bf215546Sopenharmony_ci * doesn't have any implications for us until we implement any of these 1218bf215546Sopenharmony_ci * optional features. 1219bf215546Sopenharmony_ci */ 1220bf215546Sopenharmony_ci .shaderSubgroupExtendedTypes = true, 1221bf215546Sopenharmony_ci .subgroupBroadcastDynamicId = true, 1222bf215546Sopenharmony_ci 1223bf215546Sopenharmony_ci .vulkanMemoryModel = true, 1224bf215546Sopenharmony_ci .vulkanMemoryModelDeviceScope = true, 1225bf215546Sopenharmony_ci .vulkanMemoryModelAvailabilityVisibilityChains = true, 1226bf215546Sopenharmony_ci 1227bf215546Sopenharmony_ci .bufferDeviceAddress = true, 1228bf215546Sopenharmony_ci .bufferDeviceAddressCaptureReplay = false, 1229bf215546Sopenharmony_ci .bufferDeviceAddressMultiDevice = false, 1230bf215546Sopenharmony_ci }; 1231bf215546Sopenharmony_ci 1232bf215546Sopenharmony_ci VkPhysicalDeviceVulkan11Features vk11 = { 1233bf215546Sopenharmony_ci .storageBuffer16BitAccess = true, 1234bf215546Sopenharmony_ci .uniformAndStorageBuffer16BitAccess = true, 1235bf215546Sopenharmony_ci .storagePushConstant16 = true, 1236bf215546Sopenharmony_ci .storageInputOutput16 = false, 1237bf215546Sopenharmony_ci .multiview = true, 1238bf215546Sopenharmony_ci .multiviewGeometryShader = false, 1239bf215546Sopenharmony_ci .multiviewTessellationShader = false, 1240bf215546Sopenharmony_ci .variablePointersStorageBuffer = true, 1241bf215546Sopenharmony_ci /* FIXME: this needs support for non-constant index on UBO/SSBO */ 1242bf215546Sopenharmony_ci .variablePointers = false, 1243bf215546Sopenharmony_ci .protectedMemory = false, 1244bf215546Sopenharmony_ci .samplerYcbcrConversion = false, 1245bf215546Sopenharmony_ci .shaderDrawParameters = false, 1246bf215546Sopenharmony_ci }; 1247bf215546Sopenharmony_ci 1248bf215546Sopenharmony_ci vk_foreach_struct(ext, pFeatures->pNext) { 1249bf215546Sopenharmony_ci if (vk_get_physical_device_core_1_1_feature_ext(ext, &vk11)) 1250bf215546Sopenharmony_ci continue; 1251bf215546Sopenharmony_ci if (vk_get_physical_device_core_1_2_feature_ext(ext, &vk12)) 1252bf215546Sopenharmony_ci continue; 1253bf215546Sopenharmony_ci if (vk_get_physical_device_core_1_3_feature_ext(ext, &vk13)) 1254bf215546Sopenharmony_ci continue; 1255bf215546Sopenharmony_ci 1256bf215546Sopenharmony_ci switch (ext->sType) { 1257bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: { 1258bf215546Sopenharmony_ci VkPhysicalDevice4444FormatsFeaturesEXT *features = 1259bf215546Sopenharmony_ci (VkPhysicalDevice4444FormatsFeaturesEXT *)ext; 1260bf215546Sopenharmony_ci features->formatA4R4G4B4 = true; 1261bf215546Sopenharmony_ci features->formatA4B4G4R4 = true; 1262bf215546Sopenharmony_ci break; 1263bf215546Sopenharmony_ci } 1264bf215546Sopenharmony_ci 1265bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: { 1266bf215546Sopenharmony_ci VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = 1267bf215546Sopenharmony_ci (VkPhysicalDeviceCustomBorderColorFeaturesEXT *)ext; 1268bf215546Sopenharmony_ci features->customBorderColors = true; 1269bf215546Sopenharmony_ci features->customBorderColorWithoutFormat = false; 1270bf215546Sopenharmony_ci break; 1271bf215546Sopenharmony_ci } 1272bf215546Sopenharmony_ci 1273bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: { 1274bf215546Sopenharmony_ci VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features = 1275bf215546Sopenharmony_ci (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext; 1276bf215546Sopenharmony_ci features->indexTypeUint8 = true; 1277bf215546Sopenharmony_ci break; 1278bf215546Sopenharmony_ci } 1279bf215546Sopenharmony_ci 1280bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: { 1281bf215546Sopenharmony_ci VkPhysicalDeviceLineRasterizationFeaturesEXT *features = 1282bf215546Sopenharmony_ci (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext; 1283bf215546Sopenharmony_ci features->rectangularLines = true; 1284bf215546Sopenharmony_ci features->bresenhamLines = true; 1285bf215546Sopenharmony_ci features->smoothLines = false; 1286bf215546Sopenharmony_ci features->stippledRectangularLines = false; 1287bf215546Sopenharmony_ci features->stippledBresenhamLines = false; 1288bf215546Sopenharmony_ci features->stippledSmoothLines = false; 1289bf215546Sopenharmony_ci break; 1290bf215546Sopenharmony_ci } 1291bf215546Sopenharmony_ci 1292bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT: { 1293bf215546Sopenharmony_ci VkPhysicalDeviceColorWriteEnableFeaturesEXT *features = (void *) ext; 1294bf215546Sopenharmony_ci features->colorWriteEnable = true; 1295bf215546Sopenharmony_ci break; 1296bf215546Sopenharmony_ci } 1297bf215546Sopenharmony_ci 1298bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: { 1299bf215546Sopenharmony_ci VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *features = 1300bf215546Sopenharmony_ci (VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *) ext; 1301bf215546Sopenharmony_ci features->pipelineExecutableInfo = true; 1302bf215546Sopenharmony_ci break; 1303bf215546Sopenharmony_ci } 1304bf215546Sopenharmony_ci 1305bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: { 1306bf215546Sopenharmony_ci VkPhysicalDeviceProvokingVertexFeaturesEXT *features = (void *) ext; 1307bf215546Sopenharmony_ci features->provokingVertexLast = true; 1308bf215546Sopenharmony_ci /* FIXME: update when supporting EXT_transform_feedback */ 1309bf215546Sopenharmony_ci features->transformFeedbackPreservesProvokingVertex = false; 1310bf215546Sopenharmony_ci break; 1311bf215546Sopenharmony_ci } 1312bf215546Sopenharmony_ci 1313bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: { 1314bf215546Sopenharmony_ci VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features = 1315bf215546Sopenharmony_ci (void *) ext; 1316bf215546Sopenharmony_ci features->vertexAttributeInstanceRateDivisor = true; 1317bf215546Sopenharmony_ci features->vertexAttributeInstanceRateZeroDivisor = false; 1318bf215546Sopenharmony_ci break; 1319bf215546Sopenharmony_ci } 1320bf215546Sopenharmony_ci 1321bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: { 1322bf215546Sopenharmony_ci VkPhysicalDevicePerformanceQueryFeaturesKHR *features = 1323bf215546Sopenharmony_ci (void *) ext; 1324bf215546Sopenharmony_ci 1325bf215546Sopenharmony_ci features->performanceCounterQueryPools = 1326bf215546Sopenharmony_ci physical_device->caps.perfmon; 1327bf215546Sopenharmony_ci features->performanceCounterMultipleQueryPools = false; 1328bf215546Sopenharmony_ci break; 1329bf215546Sopenharmony_ci } 1330bf215546Sopenharmony_ci 1331bf215546Sopenharmony_ci default: 1332bf215546Sopenharmony_ci v3dv_debug_ignored_stype(ext->sType); 1333bf215546Sopenharmony_ci break; 1334bf215546Sopenharmony_ci } 1335bf215546Sopenharmony_ci } 1336bf215546Sopenharmony_ci} 1337bf215546Sopenharmony_ci 1338bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1339bf215546Sopenharmony_civ3dv_GetDeviceGroupPeerMemoryFeatures(VkDevice device, 1340bf215546Sopenharmony_ci uint32_t heapIndex, 1341bf215546Sopenharmony_ci uint32_t localDeviceIndex, 1342bf215546Sopenharmony_ci uint32_t remoteDeviceIndex, 1343bf215546Sopenharmony_ci VkPeerMemoryFeatureFlags *pPeerMemoryFeatures) 1344bf215546Sopenharmony_ci{ 1345bf215546Sopenharmony_ci assert(localDeviceIndex == 0 && remoteDeviceIndex == 0); 1346bf215546Sopenharmony_ci *pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT | 1347bf215546Sopenharmony_ci VK_PEER_MEMORY_FEATURE_COPY_DST_BIT | 1348bf215546Sopenharmony_ci VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT | 1349bf215546Sopenharmony_ci VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT; 1350bf215546Sopenharmony_ci} 1351bf215546Sopenharmony_ci 1352bf215546Sopenharmony_ciuint32_t 1353bf215546Sopenharmony_civ3dv_physical_device_vendor_id(struct v3dv_physical_device *dev) 1354bf215546Sopenharmony_ci{ 1355bf215546Sopenharmony_ci return 0x14E4; /* Broadcom */ 1356bf215546Sopenharmony_ci} 1357bf215546Sopenharmony_ci 1358bf215546Sopenharmony_ciuint32_t 1359bf215546Sopenharmony_civ3dv_physical_device_device_id(struct v3dv_physical_device *dev) 1360bf215546Sopenharmony_ci{ 1361bf215546Sopenharmony_ci#if using_v3d_simulator 1362bf215546Sopenharmony_ci return dev->device_id; 1363bf215546Sopenharmony_ci#else 1364bf215546Sopenharmony_ci switch (dev->devinfo.ver) { 1365bf215546Sopenharmony_ci case 42: 1366bf215546Sopenharmony_ci return 0xBE485FD3; /* Broadcom deviceID for 2711 */ 1367bf215546Sopenharmony_ci default: 1368bf215546Sopenharmony_ci unreachable("Unsupported V3D version"); 1369bf215546Sopenharmony_ci } 1370bf215546Sopenharmony_ci#endif 1371bf215546Sopenharmony_ci} 1372bf215546Sopenharmony_ci 1373bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1374bf215546Sopenharmony_civ3dv_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, 1375bf215546Sopenharmony_ci VkPhysicalDeviceProperties *pProperties) 1376bf215546Sopenharmony_ci{ 1377bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice); 1378bf215546Sopenharmony_ci 1379bf215546Sopenharmony_ci STATIC_ASSERT(MAX_SAMPLED_IMAGES + MAX_STORAGE_IMAGES + MAX_INPUT_ATTACHMENTS 1380bf215546Sopenharmony_ci <= V3D_MAX_TEXTURE_SAMPLERS); 1381bf215546Sopenharmony_ci STATIC_ASSERT(MAX_UNIFORM_BUFFERS >= MAX_DYNAMIC_UNIFORM_BUFFERS); 1382bf215546Sopenharmony_ci STATIC_ASSERT(MAX_STORAGE_BUFFERS >= MAX_DYNAMIC_STORAGE_BUFFERS); 1383bf215546Sopenharmony_ci 1384bf215546Sopenharmony_ci const uint32_t page_size = 4096; 1385bf215546Sopenharmony_ci const uint32_t mem_size = compute_heap_size(); 1386bf215546Sopenharmony_ci 1387bf215546Sopenharmony_ci const uint32_t max_varying_components = 16 * 4; 1388bf215546Sopenharmony_ci 1389bf215546Sopenharmony_ci const float v3d_point_line_granularity = 2.0f / (1 << V3D_COORD_SHIFT); 1390bf215546Sopenharmony_ci const uint32_t max_fb_size = V3D_MAX_IMAGE_DIMENSION; 1391bf215546Sopenharmony_ci 1392bf215546Sopenharmony_ci const VkSampleCountFlags supported_sample_counts = 1393bf215546Sopenharmony_ci VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT; 1394bf215546Sopenharmony_ci 1395bf215546Sopenharmony_ci struct timespec clock_res; 1396bf215546Sopenharmony_ci clock_getres(CLOCK_MONOTONIC, &clock_res); 1397bf215546Sopenharmony_ci const float timestamp_period = 1398bf215546Sopenharmony_ci clock_res.tv_sec * 1000000000.0f + clock_res.tv_nsec; 1399bf215546Sopenharmony_ci 1400bf215546Sopenharmony_ci /* FIXME: this will probably require an in-depth review */ 1401bf215546Sopenharmony_ci VkPhysicalDeviceLimits limits = { 1402bf215546Sopenharmony_ci .maxImageDimension1D = V3D_MAX_IMAGE_DIMENSION, 1403bf215546Sopenharmony_ci .maxImageDimension2D = V3D_MAX_IMAGE_DIMENSION, 1404bf215546Sopenharmony_ci .maxImageDimension3D = V3D_MAX_IMAGE_DIMENSION, 1405bf215546Sopenharmony_ci .maxImageDimensionCube = V3D_MAX_IMAGE_DIMENSION, 1406bf215546Sopenharmony_ci .maxImageArrayLayers = V3D_MAX_ARRAY_LAYERS, 1407bf215546Sopenharmony_ci .maxTexelBufferElements = (1ul << 28), 1408bf215546Sopenharmony_ci .maxUniformBufferRange = V3D_MAX_BUFFER_RANGE, 1409bf215546Sopenharmony_ci .maxStorageBufferRange = V3D_MAX_BUFFER_RANGE, 1410bf215546Sopenharmony_ci .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE, 1411bf215546Sopenharmony_ci .maxMemoryAllocationCount = mem_size / page_size, 1412bf215546Sopenharmony_ci .maxSamplerAllocationCount = 64 * 1024, 1413bf215546Sopenharmony_ci .bufferImageGranularity = V3D_NON_COHERENT_ATOM_SIZE, 1414bf215546Sopenharmony_ci .sparseAddressSpaceSize = 0, 1415bf215546Sopenharmony_ci .maxBoundDescriptorSets = MAX_SETS, 1416bf215546Sopenharmony_ci .maxPerStageDescriptorSamplers = V3D_MAX_TEXTURE_SAMPLERS, 1417bf215546Sopenharmony_ci .maxPerStageDescriptorUniformBuffers = MAX_UNIFORM_BUFFERS, 1418bf215546Sopenharmony_ci .maxPerStageDescriptorStorageBuffers = MAX_STORAGE_BUFFERS, 1419bf215546Sopenharmony_ci .maxPerStageDescriptorSampledImages = MAX_SAMPLED_IMAGES, 1420bf215546Sopenharmony_ci .maxPerStageDescriptorStorageImages = MAX_STORAGE_IMAGES, 1421bf215546Sopenharmony_ci .maxPerStageDescriptorInputAttachments = MAX_INPUT_ATTACHMENTS, 1422bf215546Sopenharmony_ci .maxPerStageResources = 128, 1423bf215546Sopenharmony_ci 1424bf215546Sopenharmony_ci /* Some of these limits are multiplied by 6 because they need to 1425bf215546Sopenharmony_ci * include all possible shader stages (even if not supported). See 1426bf215546Sopenharmony_ci * 'Required Limits' table in the Vulkan spec. 1427bf215546Sopenharmony_ci */ 1428bf215546Sopenharmony_ci .maxDescriptorSetSamplers = 6 * V3D_MAX_TEXTURE_SAMPLERS, 1429bf215546Sopenharmony_ci .maxDescriptorSetUniformBuffers = 6 * MAX_UNIFORM_BUFFERS, 1430bf215546Sopenharmony_ci .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS, 1431bf215546Sopenharmony_ci .maxDescriptorSetStorageBuffers = 6 * MAX_STORAGE_BUFFERS, 1432bf215546Sopenharmony_ci .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS, 1433bf215546Sopenharmony_ci .maxDescriptorSetSampledImages = 6 * MAX_SAMPLED_IMAGES, 1434bf215546Sopenharmony_ci .maxDescriptorSetStorageImages = 6 * MAX_STORAGE_IMAGES, 1435bf215546Sopenharmony_ci .maxDescriptorSetInputAttachments = MAX_INPUT_ATTACHMENTS, 1436bf215546Sopenharmony_ci 1437bf215546Sopenharmony_ci /* Vertex limits */ 1438bf215546Sopenharmony_ci .maxVertexInputAttributes = MAX_VERTEX_ATTRIBS, 1439bf215546Sopenharmony_ci .maxVertexInputBindings = MAX_VBS, 1440bf215546Sopenharmony_ci .maxVertexInputAttributeOffset = 0xffffffff, 1441bf215546Sopenharmony_ci .maxVertexInputBindingStride = 0xffffffff, 1442bf215546Sopenharmony_ci .maxVertexOutputComponents = max_varying_components, 1443bf215546Sopenharmony_ci 1444bf215546Sopenharmony_ci /* Tessellation limits */ 1445bf215546Sopenharmony_ci .maxTessellationGenerationLevel = 0, 1446bf215546Sopenharmony_ci .maxTessellationPatchSize = 0, 1447bf215546Sopenharmony_ci .maxTessellationControlPerVertexInputComponents = 0, 1448bf215546Sopenharmony_ci .maxTessellationControlPerVertexOutputComponents = 0, 1449bf215546Sopenharmony_ci .maxTessellationControlPerPatchOutputComponents = 0, 1450bf215546Sopenharmony_ci .maxTessellationControlTotalOutputComponents = 0, 1451bf215546Sopenharmony_ci .maxTessellationEvaluationInputComponents = 0, 1452bf215546Sopenharmony_ci .maxTessellationEvaluationOutputComponents = 0, 1453bf215546Sopenharmony_ci 1454bf215546Sopenharmony_ci /* Geometry limits */ 1455bf215546Sopenharmony_ci .maxGeometryShaderInvocations = 32, 1456bf215546Sopenharmony_ci .maxGeometryInputComponents = 64, 1457bf215546Sopenharmony_ci .maxGeometryOutputComponents = 64, 1458bf215546Sopenharmony_ci .maxGeometryOutputVertices = 256, 1459bf215546Sopenharmony_ci .maxGeometryTotalOutputComponents = 1024, 1460bf215546Sopenharmony_ci 1461bf215546Sopenharmony_ci /* Fragment limits */ 1462bf215546Sopenharmony_ci .maxFragmentInputComponents = max_varying_components, 1463bf215546Sopenharmony_ci .maxFragmentOutputAttachments = 4, 1464bf215546Sopenharmony_ci .maxFragmentDualSrcAttachments = 0, 1465bf215546Sopenharmony_ci .maxFragmentCombinedOutputResources = MAX_RENDER_TARGETS + 1466bf215546Sopenharmony_ci MAX_STORAGE_BUFFERS + 1467bf215546Sopenharmony_ci MAX_STORAGE_IMAGES, 1468bf215546Sopenharmony_ci 1469bf215546Sopenharmony_ci /* Compute limits */ 1470bf215546Sopenharmony_ci .maxComputeSharedMemorySize = 16384, 1471bf215546Sopenharmony_ci .maxComputeWorkGroupCount = { 65535, 65535, 65535 }, 1472bf215546Sopenharmony_ci .maxComputeWorkGroupInvocations = 256, 1473bf215546Sopenharmony_ci .maxComputeWorkGroupSize = { 256, 256, 256 }, 1474bf215546Sopenharmony_ci 1475bf215546Sopenharmony_ci .subPixelPrecisionBits = V3D_COORD_SHIFT, 1476bf215546Sopenharmony_ci .subTexelPrecisionBits = 8, 1477bf215546Sopenharmony_ci .mipmapPrecisionBits = 8, 1478bf215546Sopenharmony_ci .maxDrawIndexedIndexValue = 0x00ffffff, 1479bf215546Sopenharmony_ci .maxDrawIndirectCount = 0x7fffffff, 1480bf215546Sopenharmony_ci .maxSamplerLodBias = 14.0f, 1481bf215546Sopenharmony_ci .maxSamplerAnisotropy = 16.0f, 1482bf215546Sopenharmony_ci .maxViewports = MAX_VIEWPORTS, 1483bf215546Sopenharmony_ci .maxViewportDimensions = { max_fb_size, max_fb_size }, 1484bf215546Sopenharmony_ci .viewportBoundsRange = { -2.0 * max_fb_size, 1485bf215546Sopenharmony_ci 2.0 * max_fb_size - 1 }, 1486bf215546Sopenharmony_ci .viewportSubPixelBits = 0, 1487bf215546Sopenharmony_ci .minMemoryMapAlignment = page_size, 1488bf215546Sopenharmony_ci .minTexelBufferOffsetAlignment = V3D_UIFBLOCK_SIZE, 1489bf215546Sopenharmony_ci .minUniformBufferOffsetAlignment = 32, 1490bf215546Sopenharmony_ci .minStorageBufferOffsetAlignment = 32, 1491bf215546Sopenharmony_ci .minTexelOffset = -8, 1492bf215546Sopenharmony_ci .maxTexelOffset = 7, 1493bf215546Sopenharmony_ci .minTexelGatherOffset = -8, 1494bf215546Sopenharmony_ci .maxTexelGatherOffset = 7, 1495bf215546Sopenharmony_ci .minInterpolationOffset = -0.5, 1496bf215546Sopenharmony_ci .maxInterpolationOffset = 0.5, 1497bf215546Sopenharmony_ci .subPixelInterpolationOffsetBits = V3D_COORD_SHIFT, 1498bf215546Sopenharmony_ci .maxFramebufferWidth = max_fb_size, 1499bf215546Sopenharmony_ci .maxFramebufferHeight = max_fb_size, 1500bf215546Sopenharmony_ci .maxFramebufferLayers = 256, 1501bf215546Sopenharmony_ci .framebufferColorSampleCounts = supported_sample_counts, 1502bf215546Sopenharmony_ci .framebufferDepthSampleCounts = supported_sample_counts, 1503bf215546Sopenharmony_ci .framebufferStencilSampleCounts = supported_sample_counts, 1504bf215546Sopenharmony_ci .framebufferNoAttachmentsSampleCounts = supported_sample_counts, 1505bf215546Sopenharmony_ci .maxColorAttachments = MAX_RENDER_TARGETS, 1506bf215546Sopenharmony_ci .sampledImageColorSampleCounts = supported_sample_counts, 1507bf215546Sopenharmony_ci .sampledImageIntegerSampleCounts = supported_sample_counts, 1508bf215546Sopenharmony_ci .sampledImageDepthSampleCounts = supported_sample_counts, 1509bf215546Sopenharmony_ci .sampledImageStencilSampleCounts = supported_sample_counts, 1510bf215546Sopenharmony_ci .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT, 1511bf215546Sopenharmony_ci .maxSampleMaskWords = 1, 1512bf215546Sopenharmony_ci .timestampComputeAndGraphics = true, 1513bf215546Sopenharmony_ci .timestampPeriod = timestamp_period, 1514bf215546Sopenharmony_ci .maxClipDistances = 8, 1515bf215546Sopenharmony_ci .maxCullDistances = 0, 1516bf215546Sopenharmony_ci .maxCombinedClipAndCullDistances = 8, 1517bf215546Sopenharmony_ci .discreteQueuePriorities = 2, 1518bf215546Sopenharmony_ci .pointSizeRange = { v3d_point_line_granularity, 1519bf215546Sopenharmony_ci V3D_MAX_POINT_SIZE }, 1520bf215546Sopenharmony_ci .lineWidthRange = { 1.0f, V3D_MAX_LINE_WIDTH }, 1521bf215546Sopenharmony_ci .pointSizeGranularity = v3d_point_line_granularity, 1522bf215546Sopenharmony_ci .lineWidthGranularity = v3d_point_line_granularity, 1523bf215546Sopenharmony_ci .strictLines = true, 1524bf215546Sopenharmony_ci .standardSampleLocations = false, 1525bf215546Sopenharmony_ci .optimalBufferCopyOffsetAlignment = 32, 1526bf215546Sopenharmony_ci .optimalBufferCopyRowPitchAlignment = 32, 1527bf215546Sopenharmony_ci .nonCoherentAtomSize = V3D_NON_COHERENT_ATOM_SIZE, 1528bf215546Sopenharmony_ci }; 1529bf215546Sopenharmony_ci 1530bf215546Sopenharmony_ci *pProperties = (VkPhysicalDeviceProperties) { 1531bf215546Sopenharmony_ci .apiVersion = V3DV_API_VERSION, 1532bf215546Sopenharmony_ci .driverVersion = vk_get_driver_version(), 1533bf215546Sopenharmony_ci .vendorID = v3dv_physical_device_vendor_id(pdevice), 1534bf215546Sopenharmony_ci .deviceID = v3dv_physical_device_device_id(pdevice), 1535bf215546Sopenharmony_ci .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU, 1536bf215546Sopenharmony_ci .limits = limits, 1537bf215546Sopenharmony_ci .sparseProperties = { 0 }, 1538bf215546Sopenharmony_ci }; 1539bf215546Sopenharmony_ci 1540bf215546Sopenharmony_ci snprintf(pProperties->deviceName, sizeof(pProperties->deviceName), 1541bf215546Sopenharmony_ci "%s", pdevice->name); 1542bf215546Sopenharmony_ci memcpy(pProperties->pipelineCacheUUID, 1543bf215546Sopenharmony_ci pdevice->pipeline_cache_uuid, VK_UUID_SIZE); 1544bf215546Sopenharmony_ci} 1545bf215546Sopenharmony_ci 1546bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1547bf215546Sopenharmony_civ3dv_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, 1548bf215546Sopenharmony_ci VkPhysicalDeviceProperties2 *pProperties) 1549bf215546Sopenharmony_ci{ 1550bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice); 1551bf215546Sopenharmony_ci 1552bf215546Sopenharmony_ci v3dv_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties); 1553bf215546Sopenharmony_ci 1554bf215546Sopenharmony_ci /* We don't really have special restrictions for the maximum 1555bf215546Sopenharmony_ci * descriptors per set, other than maybe not exceeding the limits 1556bf215546Sopenharmony_ci * of addressable memory in a single allocation on either the host 1557bf215546Sopenharmony_ci * or the GPU. This will be a much larger limit than any of the 1558bf215546Sopenharmony_ci * per-stage limits already available in Vulkan though, so in practice, 1559bf215546Sopenharmony_ci * it is not expected to limit anything beyond what is already 1560bf215546Sopenharmony_ci * constrained through per-stage limits. 1561bf215546Sopenharmony_ci */ 1562bf215546Sopenharmony_ci const uint32_t max_host_descriptors = 1563bf215546Sopenharmony_ci (UINT32_MAX - sizeof(struct v3dv_descriptor_set)) / 1564bf215546Sopenharmony_ci sizeof(struct v3dv_descriptor); 1565bf215546Sopenharmony_ci const uint32_t max_gpu_descriptors = 1566bf215546Sopenharmony_ci (UINT32_MAX / v3dv_X(pdevice, max_descriptor_bo_size)()); 1567bf215546Sopenharmony_ci 1568bf215546Sopenharmony_ci VkPhysicalDeviceVulkan13Properties vk13 = { 1569bf215546Sopenharmony_ci .maxInlineUniformBlockSize = 4096, 1570bf215546Sopenharmony_ci .maxPerStageDescriptorInlineUniformBlocks = MAX_INLINE_UNIFORM_BUFFERS, 1571bf215546Sopenharmony_ci .maxDescriptorSetInlineUniformBlocks = MAX_INLINE_UNIFORM_BUFFERS, 1572bf215546Sopenharmony_ci .maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks = 1573bf215546Sopenharmony_ci MAX_INLINE_UNIFORM_BUFFERS, 1574bf215546Sopenharmony_ci .maxDescriptorSetUpdateAfterBindInlineUniformBlocks = 1575bf215546Sopenharmony_ci MAX_INLINE_UNIFORM_BUFFERS, 1576bf215546Sopenharmony_ci }; 1577bf215546Sopenharmony_ci 1578bf215546Sopenharmony_ci VkPhysicalDeviceVulkan12Properties vk12 = { 1579bf215546Sopenharmony_ci .driverID = VK_DRIVER_ID_MESA_V3DV, 1580bf215546Sopenharmony_ci .conformanceVersion = { 1581bf215546Sopenharmony_ci .major = 1, 1582bf215546Sopenharmony_ci .minor = 2, 1583bf215546Sopenharmony_ci .subminor = 7, 1584bf215546Sopenharmony_ci .patch = 1, 1585bf215546Sopenharmony_ci }, 1586bf215546Sopenharmony_ci .supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, 1587bf215546Sopenharmony_ci .supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, 1588bf215546Sopenharmony_ci /* FIXME: if we want to support independentResolveNone then we would 1589bf215546Sopenharmony_ci * need to honor attachment load operations on resolve attachments, 1590bf215546Sopenharmony_ci * which we currently ignore because the resolve makes them irrelevant, 1591bf215546Sopenharmony_ci * as it unconditionally writes all pixels in the render area. However, 1592bf215546Sopenharmony_ci * with independentResolveNone, it is possible to have one aspect of a 1593bf215546Sopenharmony_ci * D/S resolve attachment stay unresolved, in which case the attachment 1594bf215546Sopenharmony_ci * load operation is relevant. 1595bf215546Sopenharmony_ci * 1596bf215546Sopenharmony_ci * NOTE: implementing attachment load for resolve attachments isn't 1597bf215546Sopenharmony_ci * immediately trivial because these attachments are not part of the 1598bf215546Sopenharmony_ci * framebuffer and therefore we can't use the same mechanism we use 1599bf215546Sopenharmony_ci * for framebuffer attachments. Instead, we should probably have to 1600bf215546Sopenharmony_ci * emit a meta operation for that right at the start of the render 1601bf215546Sopenharmony_ci * pass (or subpass). 1602bf215546Sopenharmony_ci */ 1603bf215546Sopenharmony_ci .independentResolveNone = false, 1604bf215546Sopenharmony_ci .independentResolve = false, 1605bf215546Sopenharmony_ci .maxTimelineSemaphoreValueDifference = UINT64_MAX, 1606bf215546Sopenharmony_ci 1607bf215546Sopenharmony_ci .denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, 1608bf215546Sopenharmony_ci .roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, 1609bf215546Sopenharmony_ci .shaderSignedZeroInfNanPreserveFloat16 = true, 1610bf215546Sopenharmony_ci .shaderSignedZeroInfNanPreserveFloat32 = true, 1611bf215546Sopenharmony_ci .shaderSignedZeroInfNanPreserveFloat64 = false, 1612bf215546Sopenharmony_ci .shaderDenormPreserveFloat16 = true, 1613bf215546Sopenharmony_ci .shaderDenormPreserveFloat32 = true, 1614bf215546Sopenharmony_ci .shaderDenormPreserveFloat64 = false, 1615bf215546Sopenharmony_ci .shaderDenormFlushToZeroFloat16 = false, 1616bf215546Sopenharmony_ci .shaderDenormFlushToZeroFloat32 = false, 1617bf215546Sopenharmony_ci .shaderDenormFlushToZeroFloat64 = false, 1618bf215546Sopenharmony_ci .shaderRoundingModeRTEFloat16 = true, 1619bf215546Sopenharmony_ci .shaderRoundingModeRTEFloat32 = true, 1620bf215546Sopenharmony_ci .shaderRoundingModeRTEFloat64 = false, 1621bf215546Sopenharmony_ci .shaderRoundingModeRTZFloat16 = false, 1622bf215546Sopenharmony_ci .shaderRoundingModeRTZFloat32 = false, 1623bf215546Sopenharmony_ci .shaderRoundingModeRTZFloat64 = false, 1624bf215546Sopenharmony_ci 1625bf215546Sopenharmony_ci /* V3D doesn't support min/max filtering */ 1626bf215546Sopenharmony_ci .filterMinmaxSingleComponentFormats = false, 1627bf215546Sopenharmony_ci .filterMinmaxImageComponentMapping = false, 1628bf215546Sopenharmony_ci 1629bf215546Sopenharmony_ci .framebufferIntegerColorSampleCounts = 1630bf215546Sopenharmony_ci VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT, 1631bf215546Sopenharmony_ci }; 1632bf215546Sopenharmony_ci memset(vk12.driverName, 0, VK_MAX_DRIVER_NAME_SIZE); 1633bf215546Sopenharmony_ci snprintf(vk12.driverName, VK_MAX_DRIVER_NAME_SIZE, "V3DV Mesa"); 1634bf215546Sopenharmony_ci memset(vk12.driverInfo, 0, VK_MAX_DRIVER_INFO_SIZE); 1635bf215546Sopenharmony_ci snprintf(vk12.driverInfo, VK_MAX_DRIVER_INFO_SIZE, 1636bf215546Sopenharmony_ci "Mesa " PACKAGE_VERSION MESA_GIT_SHA1); 1637bf215546Sopenharmony_ci 1638bf215546Sopenharmony_ci VkPhysicalDeviceVulkan11Properties vk11 = { 1639bf215546Sopenharmony_ci .deviceLUIDValid = false, 1640bf215546Sopenharmony_ci .subgroupSize = V3D_CHANNELS, 1641bf215546Sopenharmony_ci .subgroupSupportedStages = VK_SHADER_STAGE_COMPUTE_BIT, 1642bf215546Sopenharmony_ci .subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT, 1643bf215546Sopenharmony_ci .subgroupQuadOperationsInAllStages = false, 1644bf215546Sopenharmony_ci .pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES, 1645bf215546Sopenharmony_ci .maxMultiviewViewCount = MAX_MULTIVIEW_VIEW_COUNT, 1646bf215546Sopenharmony_ci .maxMultiviewInstanceIndex = UINT32_MAX - 1, 1647bf215546Sopenharmony_ci .protectedNoFault = false, 1648bf215546Sopenharmony_ci .maxPerSetDescriptors = MIN2(max_host_descriptors, max_gpu_descriptors), 1649bf215546Sopenharmony_ci /* Minimum required by the spec */ 1650bf215546Sopenharmony_ci .maxMemoryAllocationSize = MAX_MEMORY_ALLOCATION_SIZE, 1651bf215546Sopenharmony_ci }; 1652bf215546Sopenharmony_ci memcpy(vk11.deviceUUID, pdevice->device_uuid, VK_UUID_SIZE); 1653bf215546Sopenharmony_ci memcpy(vk11.driverUUID, pdevice->driver_uuid, VK_UUID_SIZE); 1654bf215546Sopenharmony_ci 1655bf215546Sopenharmony_ci 1656bf215546Sopenharmony_ci vk_foreach_struct(ext, pProperties->pNext) { 1657bf215546Sopenharmony_ci if (vk_get_physical_device_core_1_1_property_ext(ext, &vk11)) 1658bf215546Sopenharmony_ci continue; 1659bf215546Sopenharmony_ci if (vk_get_physical_device_core_1_2_property_ext(ext, &vk12)) 1660bf215546Sopenharmony_ci continue; 1661bf215546Sopenharmony_ci if (vk_get_physical_device_core_1_3_property_ext(ext, &vk13)) 1662bf215546Sopenharmony_ci continue; 1663bf215546Sopenharmony_ci 1664bf215546Sopenharmony_ci switch (ext->sType) { 1665bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: { 1666bf215546Sopenharmony_ci VkPhysicalDeviceCustomBorderColorPropertiesEXT *props = 1667bf215546Sopenharmony_ci (VkPhysicalDeviceCustomBorderColorPropertiesEXT *)ext; 1668bf215546Sopenharmony_ci props->maxCustomBorderColorSamplers = V3D_MAX_TEXTURE_SAMPLERS; 1669bf215546Sopenharmony_ci break; 1670bf215546Sopenharmony_ci } 1671bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: { 1672bf215546Sopenharmony_ci VkPhysicalDeviceProvokingVertexPropertiesEXT *props = 1673bf215546Sopenharmony_ci (VkPhysicalDeviceProvokingVertexPropertiesEXT *)ext; 1674bf215546Sopenharmony_ci props->provokingVertexModePerPipeline = true; 1675bf215546Sopenharmony_ci /* FIXME: update when supporting EXT_transform_feedback */ 1676bf215546Sopenharmony_ci props->transformFeedbackPreservesTriangleFanProvokingVertex = false; 1677bf215546Sopenharmony_ci break; 1678bf215546Sopenharmony_ci } 1679bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: { 1680bf215546Sopenharmony_ci VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props = 1681bf215546Sopenharmony_ci (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext; 1682bf215546Sopenharmony_ci props->maxVertexAttribDivisor = 0xffff; 1683bf215546Sopenharmony_ci break; 1684bf215546Sopenharmony_ci } 1685bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR : { 1686bf215546Sopenharmony_ci VkPhysicalDevicePerformanceQueryPropertiesKHR *props = 1687bf215546Sopenharmony_ci (VkPhysicalDevicePerformanceQueryPropertiesKHR *)ext; 1688bf215546Sopenharmony_ci 1689bf215546Sopenharmony_ci props->allowCommandBufferQueryCopies = true; 1690bf215546Sopenharmony_ci break; 1691bf215546Sopenharmony_ci } 1692bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT: { 1693bf215546Sopenharmony_ci VkPhysicalDeviceDrmPropertiesEXT *props = 1694bf215546Sopenharmony_ci (VkPhysicalDeviceDrmPropertiesEXT *)ext; 1695bf215546Sopenharmony_ci props->hasPrimary = pdevice->has_primary; 1696bf215546Sopenharmony_ci if (props->hasPrimary) { 1697bf215546Sopenharmony_ci props->primaryMajor = (int64_t) major(pdevice->primary_devid); 1698bf215546Sopenharmony_ci props->primaryMinor = (int64_t) minor(pdevice->primary_devid); 1699bf215546Sopenharmony_ci } 1700bf215546Sopenharmony_ci props->hasRender = pdevice->has_render; 1701bf215546Sopenharmony_ci if (props->hasRender) { 1702bf215546Sopenharmony_ci props->renderMajor = (int64_t) major(pdevice->render_devid); 1703bf215546Sopenharmony_ci props->renderMinor = (int64_t) minor(pdevice->render_devid); 1704bf215546Sopenharmony_ci } 1705bf215546Sopenharmony_ci break; 1706bf215546Sopenharmony_ci } 1707bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: { 1708bf215546Sopenharmony_ci VkPhysicalDeviceLineRasterizationPropertiesEXT *props = 1709bf215546Sopenharmony_ci (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext; 1710bf215546Sopenharmony_ci props->lineSubPixelPrecisionBits = V3D_COORD_SHIFT; 1711bf215546Sopenharmony_ci break; 1712bf215546Sopenharmony_ci } 1713bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT: 1714bf215546Sopenharmony_ci /* Do nothing, not even logging. This is a non-PCI device, so we will 1715bf215546Sopenharmony_ci * never provide this extension. 1716bf215546Sopenharmony_ci */ 1717bf215546Sopenharmony_ci break; 1718bf215546Sopenharmony_ci default: 1719bf215546Sopenharmony_ci v3dv_debug_ignored_stype(ext->sType); 1720bf215546Sopenharmony_ci break; 1721bf215546Sopenharmony_ci } 1722bf215546Sopenharmony_ci } 1723bf215546Sopenharmony_ci} 1724bf215546Sopenharmony_ci 1725bf215546Sopenharmony_ci/* We support exactly one queue family. */ 1726bf215546Sopenharmony_cistatic const VkQueueFamilyProperties 1727bf215546Sopenharmony_civ3dv_queue_family_properties = { 1728bf215546Sopenharmony_ci .queueFlags = VK_QUEUE_GRAPHICS_BIT | 1729bf215546Sopenharmony_ci VK_QUEUE_COMPUTE_BIT | 1730bf215546Sopenharmony_ci VK_QUEUE_TRANSFER_BIT, 1731bf215546Sopenharmony_ci .queueCount = 1, 1732bf215546Sopenharmony_ci .timestampValidBits = 64, 1733bf215546Sopenharmony_ci .minImageTransferGranularity = { 1, 1, 1 }, 1734bf215546Sopenharmony_ci}; 1735bf215546Sopenharmony_ci 1736bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1737bf215546Sopenharmony_civ3dv_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice, 1738bf215546Sopenharmony_ci uint32_t *pQueueFamilyPropertyCount, 1739bf215546Sopenharmony_ci VkQueueFamilyProperties2 *pQueueFamilyProperties) 1740bf215546Sopenharmony_ci{ 1741bf215546Sopenharmony_ci VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, out, 1742bf215546Sopenharmony_ci pQueueFamilyProperties, pQueueFamilyPropertyCount); 1743bf215546Sopenharmony_ci 1744bf215546Sopenharmony_ci vk_outarray_append_typed(VkQueueFamilyProperties2, &out, p) { 1745bf215546Sopenharmony_ci p->queueFamilyProperties = v3dv_queue_family_properties; 1746bf215546Sopenharmony_ci 1747bf215546Sopenharmony_ci vk_foreach_struct(s, p->pNext) { 1748bf215546Sopenharmony_ci v3dv_debug_ignored_stype(s->sType); 1749bf215546Sopenharmony_ci } 1750bf215546Sopenharmony_ci } 1751bf215546Sopenharmony_ci} 1752bf215546Sopenharmony_ci 1753bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1754bf215546Sopenharmony_civ3dv_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, 1755bf215546Sopenharmony_ci VkPhysicalDeviceMemoryProperties *pMemoryProperties) 1756bf215546Sopenharmony_ci{ 1757bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice); 1758bf215546Sopenharmony_ci *pMemoryProperties = device->memory; 1759bf215546Sopenharmony_ci} 1760bf215546Sopenharmony_ci 1761bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1762bf215546Sopenharmony_civ3dv_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice, 1763bf215546Sopenharmony_ci VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) 1764bf215546Sopenharmony_ci{ 1765bf215546Sopenharmony_ci v3dv_GetPhysicalDeviceMemoryProperties(physicalDevice, 1766bf215546Sopenharmony_ci &pMemoryProperties->memoryProperties); 1767bf215546Sopenharmony_ci 1768bf215546Sopenharmony_ci vk_foreach_struct(ext, pMemoryProperties->pNext) { 1769bf215546Sopenharmony_ci switch (ext->sType) { 1770bf215546Sopenharmony_ci default: 1771bf215546Sopenharmony_ci v3dv_debug_ignored_stype(ext->sType); 1772bf215546Sopenharmony_ci break; 1773bf215546Sopenharmony_ci } 1774bf215546Sopenharmony_ci } 1775bf215546Sopenharmony_ci} 1776bf215546Sopenharmony_ci 1777bf215546Sopenharmony_ciVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1778bf215546Sopenharmony_civ3dv_GetInstanceProcAddr(VkInstance _instance, 1779bf215546Sopenharmony_ci const char *pName) 1780bf215546Sopenharmony_ci{ 1781bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 1782bf215546Sopenharmony_ci return vk_instance_get_proc_addr(&instance->vk, 1783bf215546Sopenharmony_ci &v3dv_instance_entrypoints, 1784bf215546Sopenharmony_ci pName); 1785bf215546Sopenharmony_ci} 1786bf215546Sopenharmony_ci 1787bf215546Sopenharmony_ci/* With version 1+ of the loader interface the ICD should expose 1788bf215546Sopenharmony_ci * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps. 1789bf215546Sopenharmony_ci */ 1790bf215546Sopenharmony_ciPUBLIC 1791bf215546Sopenharmony_ciVKAPI_ATTR PFN_vkVoidFunction 1792bf215546Sopenharmony_ciVKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance, 1793bf215546Sopenharmony_ci const char *pName); 1794bf215546Sopenharmony_ci 1795bf215546Sopenharmony_ciPUBLIC 1796bf215546Sopenharmony_ciVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1797bf215546Sopenharmony_civk_icdGetInstanceProcAddr(VkInstance instance, 1798bf215546Sopenharmony_ci const char* pName) 1799bf215546Sopenharmony_ci{ 1800bf215546Sopenharmony_ci return v3dv_GetInstanceProcAddr(instance, pName); 1801bf215546Sopenharmony_ci} 1802bf215546Sopenharmony_ci 1803bf215546Sopenharmony_ci/* With version 4+ of the loader interface the ICD should expose 1804bf215546Sopenharmony_ci * vk_icdGetPhysicalDeviceProcAddr() 1805bf215546Sopenharmony_ci */ 1806bf215546Sopenharmony_ciPUBLIC 1807bf215546Sopenharmony_ciVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL 1808bf215546Sopenharmony_civk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, 1809bf215546Sopenharmony_ci const char* pName); 1810bf215546Sopenharmony_ci 1811bf215546Sopenharmony_ciPFN_vkVoidFunction 1812bf215546Sopenharmony_civk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, 1813bf215546Sopenharmony_ci const char* pName) 1814bf215546Sopenharmony_ci{ 1815bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_instance, instance, _instance); 1816bf215546Sopenharmony_ci 1817bf215546Sopenharmony_ci return vk_instance_get_physical_device_proc_addr(&instance->vk, pName); 1818bf215546Sopenharmony_ci} 1819bf215546Sopenharmony_ci 1820bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 1821bf215546Sopenharmony_civ3dv_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount, 1822bf215546Sopenharmony_ci VkLayerProperties *pProperties) 1823bf215546Sopenharmony_ci{ 1824bf215546Sopenharmony_ci if (pProperties == NULL) { 1825bf215546Sopenharmony_ci *pPropertyCount = 0; 1826bf215546Sopenharmony_ci return VK_SUCCESS; 1827bf215546Sopenharmony_ci } 1828bf215546Sopenharmony_ci 1829bf215546Sopenharmony_ci return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); 1830bf215546Sopenharmony_ci} 1831bf215546Sopenharmony_ci 1832bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 1833bf215546Sopenharmony_civ3dv_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, 1834bf215546Sopenharmony_ci uint32_t *pPropertyCount, 1835bf215546Sopenharmony_ci VkLayerProperties *pProperties) 1836bf215546Sopenharmony_ci{ 1837bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice); 1838bf215546Sopenharmony_ci 1839bf215546Sopenharmony_ci if (pProperties == NULL) { 1840bf215546Sopenharmony_ci *pPropertyCount = 0; 1841bf215546Sopenharmony_ci return VK_SUCCESS; 1842bf215546Sopenharmony_ci } 1843bf215546Sopenharmony_ci 1844bf215546Sopenharmony_ci return vk_error(physical_device, VK_ERROR_LAYER_NOT_PRESENT); 1845bf215546Sopenharmony_ci} 1846bf215546Sopenharmony_ci 1847bf215546Sopenharmony_cistatic void 1848bf215546Sopenharmony_cidestroy_queue_syncs(struct v3dv_queue *queue) 1849bf215546Sopenharmony_ci{ 1850bf215546Sopenharmony_ci for (int i = 0; i < V3DV_QUEUE_COUNT; i++) { 1851bf215546Sopenharmony_ci if (queue->last_job_syncs.syncs[i]) { 1852bf215546Sopenharmony_ci drmSyncobjDestroy(queue->device->pdevice->render_fd, 1853bf215546Sopenharmony_ci queue->last_job_syncs.syncs[i]); 1854bf215546Sopenharmony_ci } 1855bf215546Sopenharmony_ci } 1856bf215546Sopenharmony_ci} 1857bf215546Sopenharmony_ci 1858bf215546Sopenharmony_cistatic VkResult 1859bf215546Sopenharmony_ciqueue_init(struct v3dv_device *device, struct v3dv_queue *queue, 1860bf215546Sopenharmony_ci const VkDeviceQueueCreateInfo *create_info, 1861bf215546Sopenharmony_ci uint32_t index_in_family) 1862bf215546Sopenharmony_ci{ 1863bf215546Sopenharmony_ci VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info, 1864bf215546Sopenharmony_ci index_in_family); 1865bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1866bf215546Sopenharmony_ci return result; 1867bf215546Sopenharmony_ci 1868bf215546Sopenharmony_ci result = vk_queue_enable_submit_thread(&queue->vk); 1869bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1870bf215546Sopenharmony_ci goto fail_submit_thread; 1871bf215546Sopenharmony_ci 1872bf215546Sopenharmony_ci queue->device = device; 1873bf215546Sopenharmony_ci queue->vk.driver_submit = v3dv_queue_driver_submit; 1874bf215546Sopenharmony_ci 1875bf215546Sopenharmony_ci for (int i = 0; i < V3DV_QUEUE_COUNT; i++) { 1876bf215546Sopenharmony_ci queue->last_job_syncs.first[i] = true; 1877bf215546Sopenharmony_ci int ret = drmSyncobjCreate(device->pdevice->render_fd, 1878bf215546Sopenharmony_ci DRM_SYNCOBJ_CREATE_SIGNALED, 1879bf215546Sopenharmony_ci &queue->last_job_syncs.syncs[i]); 1880bf215546Sopenharmony_ci if (ret) { 1881bf215546Sopenharmony_ci result = vk_errorf(device, VK_ERROR_INITIALIZATION_FAILED, 1882bf215546Sopenharmony_ci "syncobj create failed: %m"); 1883bf215546Sopenharmony_ci goto fail_last_job_syncs; 1884bf215546Sopenharmony_ci } 1885bf215546Sopenharmony_ci } 1886bf215546Sopenharmony_ci 1887bf215546Sopenharmony_ci queue->noop_job = NULL; 1888bf215546Sopenharmony_ci return VK_SUCCESS; 1889bf215546Sopenharmony_ci 1890bf215546Sopenharmony_cifail_last_job_syncs: 1891bf215546Sopenharmony_ci destroy_queue_syncs(queue); 1892bf215546Sopenharmony_cifail_submit_thread: 1893bf215546Sopenharmony_ci vk_queue_finish(&queue->vk); 1894bf215546Sopenharmony_ci return result; 1895bf215546Sopenharmony_ci} 1896bf215546Sopenharmony_ci 1897bf215546Sopenharmony_cistatic void 1898bf215546Sopenharmony_ciqueue_finish(struct v3dv_queue *queue) 1899bf215546Sopenharmony_ci{ 1900bf215546Sopenharmony_ci if (queue->noop_job) 1901bf215546Sopenharmony_ci v3dv_job_destroy(queue->noop_job); 1902bf215546Sopenharmony_ci destroy_queue_syncs(queue); 1903bf215546Sopenharmony_ci vk_queue_finish(&queue->vk); 1904bf215546Sopenharmony_ci} 1905bf215546Sopenharmony_ci 1906bf215546Sopenharmony_cistatic void 1907bf215546Sopenharmony_ciinit_device_meta(struct v3dv_device *device) 1908bf215546Sopenharmony_ci{ 1909bf215546Sopenharmony_ci mtx_init(&device->meta.mtx, mtx_plain); 1910bf215546Sopenharmony_ci v3dv_meta_clear_init(device); 1911bf215546Sopenharmony_ci v3dv_meta_blit_init(device); 1912bf215546Sopenharmony_ci v3dv_meta_texel_buffer_copy_init(device); 1913bf215546Sopenharmony_ci} 1914bf215546Sopenharmony_ci 1915bf215546Sopenharmony_cistatic void 1916bf215546Sopenharmony_cidestroy_device_meta(struct v3dv_device *device) 1917bf215546Sopenharmony_ci{ 1918bf215546Sopenharmony_ci mtx_destroy(&device->meta.mtx); 1919bf215546Sopenharmony_ci v3dv_meta_clear_finish(device); 1920bf215546Sopenharmony_ci v3dv_meta_blit_finish(device); 1921bf215546Sopenharmony_ci v3dv_meta_texel_buffer_copy_finish(device); 1922bf215546Sopenharmony_ci} 1923bf215546Sopenharmony_ci 1924bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 1925bf215546Sopenharmony_civ3dv_CreateDevice(VkPhysicalDevice physicalDevice, 1926bf215546Sopenharmony_ci const VkDeviceCreateInfo *pCreateInfo, 1927bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 1928bf215546Sopenharmony_ci VkDevice *pDevice) 1929bf215546Sopenharmony_ci{ 1930bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice); 1931bf215546Sopenharmony_ci struct v3dv_instance *instance = (struct v3dv_instance*) physical_device->vk.instance; 1932bf215546Sopenharmony_ci VkResult result; 1933bf215546Sopenharmony_ci struct v3dv_device *device; 1934bf215546Sopenharmony_ci 1935bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO); 1936bf215546Sopenharmony_ci 1937bf215546Sopenharmony_ci /* Check requested queues (we only expose one queue ) */ 1938bf215546Sopenharmony_ci assert(pCreateInfo->queueCreateInfoCount == 1); 1939bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) { 1940bf215546Sopenharmony_ci assert(pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex == 0); 1941bf215546Sopenharmony_ci assert(pCreateInfo->pQueueCreateInfos[i].queueCount == 1); 1942bf215546Sopenharmony_ci if (pCreateInfo->pQueueCreateInfos[i].flags != 0) 1943bf215546Sopenharmony_ci return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED); 1944bf215546Sopenharmony_ci } 1945bf215546Sopenharmony_ci 1946bf215546Sopenharmony_ci device = vk_zalloc2(&physical_device->vk.instance->alloc, pAllocator, 1947bf215546Sopenharmony_ci sizeof(*device), 8, 1948bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 1949bf215546Sopenharmony_ci if (!device) 1950bf215546Sopenharmony_ci return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 1951bf215546Sopenharmony_ci 1952bf215546Sopenharmony_ci struct vk_device_dispatch_table dispatch_table; 1953bf215546Sopenharmony_ci vk_device_dispatch_table_from_entrypoints(&dispatch_table, 1954bf215546Sopenharmony_ci &v3dv_device_entrypoints, true); 1955bf215546Sopenharmony_ci vk_device_dispatch_table_from_entrypoints(&dispatch_table, 1956bf215546Sopenharmony_ci &wsi_device_entrypoints, false); 1957bf215546Sopenharmony_ci result = vk_device_init(&device->vk, &physical_device->vk, 1958bf215546Sopenharmony_ci &dispatch_table, pCreateInfo, pAllocator); 1959bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1960bf215546Sopenharmony_ci vk_free(&device->vk.alloc, device); 1961bf215546Sopenharmony_ci return vk_error(NULL, result); 1962bf215546Sopenharmony_ci } 1963bf215546Sopenharmony_ci 1964bf215546Sopenharmony_ci device->instance = instance; 1965bf215546Sopenharmony_ci device->pdevice = physical_device; 1966bf215546Sopenharmony_ci 1967bf215546Sopenharmony_ci mtx_init(&device->query_mutex, mtx_plain); 1968bf215546Sopenharmony_ci cnd_init(&device->query_ended); 1969bf215546Sopenharmony_ci 1970bf215546Sopenharmony_ci vk_device_set_drm_fd(&device->vk, physical_device->render_fd); 1971bf215546Sopenharmony_ci vk_device_enable_threaded_submit(&device->vk); 1972bf215546Sopenharmony_ci 1973bf215546Sopenharmony_ci result = queue_init(device, &device->queue, 1974bf215546Sopenharmony_ci pCreateInfo->pQueueCreateInfos, 0); 1975bf215546Sopenharmony_ci if (result != VK_SUCCESS) 1976bf215546Sopenharmony_ci goto fail; 1977bf215546Sopenharmony_ci 1978bf215546Sopenharmony_ci device->devinfo = physical_device->devinfo; 1979bf215546Sopenharmony_ci 1980bf215546Sopenharmony_ci /* Vulkan 1.1 and VK_KHR_get_physical_device_properties2 added 1981bf215546Sopenharmony_ci * VkPhysicalDeviceFeatures2 which can be used in the pNext chain of 1982bf215546Sopenharmony_ci * vkDeviceCreateInfo, in which case it should be used instead of 1983bf215546Sopenharmony_ci * pEnabledFeatures. 1984bf215546Sopenharmony_ci */ 1985bf215546Sopenharmony_ci const VkPhysicalDeviceFeatures2 *features2 = 1986bf215546Sopenharmony_ci vk_find_struct_const(pCreateInfo->pNext, PHYSICAL_DEVICE_FEATURES_2); 1987bf215546Sopenharmony_ci if (features2) { 1988bf215546Sopenharmony_ci memcpy(&device->features, &features2->features, 1989bf215546Sopenharmony_ci sizeof(device->features)); 1990bf215546Sopenharmony_ci } else if (pCreateInfo->pEnabledFeatures) { 1991bf215546Sopenharmony_ci memcpy(&device->features, pCreateInfo->pEnabledFeatures, 1992bf215546Sopenharmony_ci sizeof(device->features)); 1993bf215546Sopenharmony_ci } 1994bf215546Sopenharmony_ci 1995bf215546Sopenharmony_ci if (device->features.robustBufferAccess) 1996bf215546Sopenharmony_ci perf_debug("Device created with Robust Buffer Access enabled.\n"); 1997bf215546Sopenharmony_ci 1998bf215546Sopenharmony_ci#ifdef DEBUG 1999bf215546Sopenharmony_ci v3dv_X(device, device_check_prepacked_sizes)(); 2000bf215546Sopenharmony_ci#endif 2001bf215546Sopenharmony_ci init_device_meta(device); 2002bf215546Sopenharmony_ci v3dv_bo_cache_init(device); 2003bf215546Sopenharmony_ci v3dv_pipeline_cache_init(&device->default_pipeline_cache, device, 0, 2004bf215546Sopenharmony_ci device->instance->default_pipeline_cache_enabled); 2005bf215546Sopenharmony_ci device->default_attribute_float = 2006bf215546Sopenharmony_ci v3dv_pipeline_create_default_attribute_values(device, NULL); 2007bf215546Sopenharmony_ci 2008bf215546Sopenharmony_ci device->device_address_mem_ctx = ralloc_context(NULL); 2009bf215546Sopenharmony_ci util_dynarray_init(&device->device_address_bo_list, 2010bf215546Sopenharmony_ci device->device_address_mem_ctx); 2011bf215546Sopenharmony_ci 2012bf215546Sopenharmony_ci *pDevice = v3dv_device_to_handle(device); 2013bf215546Sopenharmony_ci 2014bf215546Sopenharmony_ci return VK_SUCCESS; 2015bf215546Sopenharmony_ci 2016bf215546Sopenharmony_cifail: 2017bf215546Sopenharmony_ci cnd_destroy(&device->query_ended); 2018bf215546Sopenharmony_ci mtx_destroy(&device->query_mutex); 2019bf215546Sopenharmony_ci queue_finish(&device->queue); 2020bf215546Sopenharmony_ci destroy_device_meta(device); 2021bf215546Sopenharmony_ci v3dv_pipeline_cache_finish(&device->default_pipeline_cache); 2022bf215546Sopenharmony_ci vk_device_finish(&device->vk); 2023bf215546Sopenharmony_ci vk_free(&device->vk.alloc, device); 2024bf215546Sopenharmony_ci 2025bf215546Sopenharmony_ci return result; 2026bf215546Sopenharmony_ci} 2027bf215546Sopenharmony_ci 2028bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2029bf215546Sopenharmony_civ3dv_DestroyDevice(VkDevice _device, 2030bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 2031bf215546Sopenharmony_ci{ 2032bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2033bf215546Sopenharmony_ci 2034bf215546Sopenharmony_ci device->vk.dispatch_table.DeviceWaitIdle(_device); 2035bf215546Sopenharmony_ci queue_finish(&device->queue); 2036bf215546Sopenharmony_ci destroy_device_meta(device); 2037bf215546Sopenharmony_ci v3dv_pipeline_cache_finish(&device->default_pipeline_cache); 2038bf215546Sopenharmony_ci 2039bf215546Sopenharmony_ci if (device->default_attribute_float) { 2040bf215546Sopenharmony_ci v3dv_bo_free(device, device->default_attribute_float); 2041bf215546Sopenharmony_ci device->default_attribute_float = NULL; 2042bf215546Sopenharmony_ci } 2043bf215546Sopenharmony_ci 2044bf215546Sopenharmony_ci ralloc_free(device->device_address_mem_ctx); 2045bf215546Sopenharmony_ci 2046bf215546Sopenharmony_ci /* Bo cache should be removed the last, as any other object could be 2047bf215546Sopenharmony_ci * freeing their private bos 2048bf215546Sopenharmony_ci */ 2049bf215546Sopenharmony_ci v3dv_bo_cache_destroy(device); 2050bf215546Sopenharmony_ci 2051bf215546Sopenharmony_ci cnd_destroy(&device->query_ended); 2052bf215546Sopenharmony_ci mtx_destroy(&device->query_mutex); 2053bf215546Sopenharmony_ci 2054bf215546Sopenharmony_ci vk_device_finish(&device->vk); 2055bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, pAllocator, device); 2056bf215546Sopenharmony_ci} 2057bf215546Sopenharmony_ci 2058bf215546Sopenharmony_cistatic VkResult 2059bf215546Sopenharmony_cidevice_alloc(struct v3dv_device *device, 2060bf215546Sopenharmony_ci struct v3dv_device_memory *mem, 2061bf215546Sopenharmony_ci VkDeviceSize size) 2062bf215546Sopenharmony_ci{ 2063bf215546Sopenharmony_ci /* Our kernel interface is 32-bit */ 2064bf215546Sopenharmony_ci assert(size <= UINT32_MAX); 2065bf215546Sopenharmony_ci 2066bf215546Sopenharmony_ci mem->bo = v3dv_bo_alloc(device, size, "device_alloc", false); 2067bf215546Sopenharmony_ci if (!mem->bo) 2068bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_DEVICE_MEMORY; 2069bf215546Sopenharmony_ci 2070bf215546Sopenharmony_ci return VK_SUCCESS; 2071bf215546Sopenharmony_ci} 2072bf215546Sopenharmony_ci 2073bf215546Sopenharmony_cistatic void 2074bf215546Sopenharmony_cidevice_free_wsi_dumb(int32_t display_fd, int32_t dumb_handle) 2075bf215546Sopenharmony_ci{ 2076bf215546Sopenharmony_ci assert(display_fd != -1); 2077bf215546Sopenharmony_ci if (dumb_handle < 0) 2078bf215546Sopenharmony_ci return; 2079bf215546Sopenharmony_ci 2080bf215546Sopenharmony_ci struct drm_mode_destroy_dumb destroy_dumb = { 2081bf215546Sopenharmony_ci .handle = dumb_handle, 2082bf215546Sopenharmony_ci }; 2083bf215546Sopenharmony_ci if (v3dv_ioctl(display_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb)) { 2084bf215546Sopenharmony_ci fprintf(stderr, "destroy dumb object %d: %s\n", dumb_handle, strerror(errno)); 2085bf215546Sopenharmony_ci } 2086bf215546Sopenharmony_ci} 2087bf215546Sopenharmony_ci 2088bf215546Sopenharmony_cistatic void 2089bf215546Sopenharmony_cidevice_free(struct v3dv_device *device, struct v3dv_device_memory *mem) 2090bf215546Sopenharmony_ci{ 2091bf215546Sopenharmony_ci /* If this memory allocation was for WSI, then we need to use the 2092bf215546Sopenharmony_ci * display device to free the allocated dumb BO. 2093bf215546Sopenharmony_ci */ 2094bf215546Sopenharmony_ci if (mem->is_for_wsi) { 2095bf215546Sopenharmony_ci device_free_wsi_dumb(device->instance->physicalDevice.display_fd, 2096bf215546Sopenharmony_ci mem->bo->dumb_handle); 2097bf215546Sopenharmony_ci } 2098bf215546Sopenharmony_ci 2099bf215546Sopenharmony_ci v3dv_bo_free(device, mem->bo); 2100bf215546Sopenharmony_ci} 2101bf215546Sopenharmony_ci 2102bf215546Sopenharmony_cistatic void 2103bf215546Sopenharmony_cidevice_unmap(struct v3dv_device *device, struct v3dv_device_memory *mem) 2104bf215546Sopenharmony_ci{ 2105bf215546Sopenharmony_ci assert(mem && mem->bo->map && mem->bo->map_size > 0); 2106bf215546Sopenharmony_ci v3dv_bo_unmap(device, mem->bo); 2107bf215546Sopenharmony_ci} 2108bf215546Sopenharmony_ci 2109bf215546Sopenharmony_cistatic VkResult 2110bf215546Sopenharmony_cidevice_map(struct v3dv_device *device, struct v3dv_device_memory *mem) 2111bf215546Sopenharmony_ci{ 2112bf215546Sopenharmony_ci assert(mem && mem->bo); 2113bf215546Sopenharmony_ci 2114bf215546Sopenharmony_ci /* From the spec: 2115bf215546Sopenharmony_ci * 2116bf215546Sopenharmony_ci * "After a successful call to vkMapMemory the memory object memory is 2117bf215546Sopenharmony_ci * considered to be currently host mapped. It is an application error to 2118bf215546Sopenharmony_ci * call vkMapMemory on a memory object that is already host mapped." 2119bf215546Sopenharmony_ci * 2120bf215546Sopenharmony_ci * We are not concerned with this ourselves (validation layers should 2121bf215546Sopenharmony_ci * catch these errors and warn users), however, the driver may internally 2122bf215546Sopenharmony_ci * map things (for example for debug CLIF dumps or some CPU-side operations) 2123bf215546Sopenharmony_ci * so by the time the user calls here the buffer might already been mapped 2124bf215546Sopenharmony_ci * internally by the driver. 2125bf215546Sopenharmony_ci */ 2126bf215546Sopenharmony_ci if (mem->bo->map) { 2127bf215546Sopenharmony_ci assert(mem->bo->map_size == mem->bo->size); 2128bf215546Sopenharmony_ci return VK_SUCCESS; 2129bf215546Sopenharmony_ci } 2130bf215546Sopenharmony_ci 2131bf215546Sopenharmony_ci bool ok = v3dv_bo_map(device, mem->bo, mem->bo->size); 2132bf215546Sopenharmony_ci if (!ok) 2133bf215546Sopenharmony_ci return VK_ERROR_MEMORY_MAP_FAILED; 2134bf215546Sopenharmony_ci 2135bf215546Sopenharmony_ci return VK_SUCCESS; 2136bf215546Sopenharmony_ci} 2137bf215546Sopenharmony_ci 2138bf215546Sopenharmony_cistatic VkResult 2139bf215546Sopenharmony_cidevice_import_bo(struct v3dv_device *device, 2140bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 2141bf215546Sopenharmony_ci int fd, uint64_t size, 2142bf215546Sopenharmony_ci struct v3dv_bo **bo) 2143bf215546Sopenharmony_ci{ 2144bf215546Sopenharmony_ci *bo = NULL; 2145bf215546Sopenharmony_ci 2146bf215546Sopenharmony_ci off_t real_size = lseek(fd, 0, SEEK_END); 2147bf215546Sopenharmony_ci lseek(fd, 0, SEEK_SET); 2148bf215546Sopenharmony_ci if (real_size < 0 || (uint64_t) real_size < size) 2149bf215546Sopenharmony_ci return VK_ERROR_INVALID_EXTERNAL_HANDLE; 2150bf215546Sopenharmony_ci 2151bf215546Sopenharmony_ci int render_fd = device->pdevice->render_fd; 2152bf215546Sopenharmony_ci assert(render_fd >= 0); 2153bf215546Sopenharmony_ci 2154bf215546Sopenharmony_ci int ret; 2155bf215546Sopenharmony_ci uint32_t handle; 2156bf215546Sopenharmony_ci ret = drmPrimeFDToHandle(render_fd, fd, &handle); 2157bf215546Sopenharmony_ci if (ret) 2158bf215546Sopenharmony_ci return VK_ERROR_INVALID_EXTERNAL_HANDLE; 2159bf215546Sopenharmony_ci 2160bf215546Sopenharmony_ci struct drm_v3d_get_bo_offset get_offset = { 2161bf215546Sopenharmony_ci .handle = handle, 2162bf215546Sopenharmony_ci }; 2163bf215546Sopenharmony_ci ret = v3dv_ioctl(render_fd, DRM_IOCTL_V3D_GET_BO_OFFSET, &get_offset); 2164bf215546Sopenharmony_ci if (ret) 2165bf215546Sopenharmony_ci return VK_ERROR_INVALID_EXTERNAL_HANDLE; 2166bf215546Sopenharmony_ci assert(get_offset.offset != 0); 2167bf215546Sopenharmony_ci 2168bf215546Sopenharmony_ci *bo = v3dv_device_lookup_bo(device->pdevice, handle); 2169bf215546Sopenharmony_ci assert(*bo); 2170bf215546Sopenharmony_ci 2171bf215546Sopenharmony_ci if ((*bo)->refcnt == 0) 2172bf215546Sopenharmony_ci v3dv_bo_init(*bo, handle, size, get_offset.offset, "import", false); 2173bf215546Sopenharmony_ci else 2174bf215546Sopenharmony_ci p_atomic_inc(&(*bo)->refcnt); 2175bf215546Sopenharmony_ci 2176bf215546Sopenharmony_ci return VK_SUCCESS; 2177bf215546Sopenharmony_ci} 2178bf215546Sopenharmony_ci 2179bf215546Sopenharmony_cistatic VkResult 2180bf215546Sopenharmony_cidevice_alloc_for_wsi(struct v3dv_device *device, 2181bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 2182bf215546Sopenharmony_ci struct v3dv_device_memory *mem, 2183bf215546Sopenharmony_ci VkDeviceSize size) 2184bf215546Sopenharmony_ci{ 2185bf215546Sopenharmony_ci /* In the simulator we can get away with a regular allocation since both 2186bf215546Sopenharmony_ci * allocation and rendering happen in the same DRM render node. On actual 2187bf215546Sopenharmony_ci * hardware we need to allocate our winsys BOs on the vc4 display device 2188bf215546Sopenharmony_ci * and import them into v3d. 2189bf215546Sopenharmony_ci */ 2190bf215546Sopenharmony_ci#if using_v3d_simulator 2191bf215546Sopenharmony_ci return device_alloc(device, mem, size); 2192bf215546Sopenharmony_ci#else 2193bf215546Sopenharmony_ci /* If we are allocating for WSI we should have a swapchain and thus, 2194bf215546Sopenharmony_ci * we should've initialized the display device. However, Zink doesn't 2195bf215546Sopenharmony_ci * use swapchains, so in that case we can get here without acquiring the 2196bf215546Sopenharmony_ci * display device and we need to do it now. 2197bf215546Sopenharmony_ci */ 2198bf215546Sopenharmony_ci VkResult result; 2199bf215546Sopenharmony_ci struct v3dv_instance *instance = device->instance; 2200bf215546Sopenharmony_ci struct v3dv_physical_device *pdevice = &device->instance->physicalDevice; 2201bf215546Sopenharmony_ci if (unlikely(pdevice->display_fd < 0)) { 2202bf215546Sopenharmony_ci result = v3dv_physical_device_acquire_display(instance, pdevice, NULL); 2203bf215546Sopenharmony_ci if (result != VK_SUCCESS) 2204bf215546Sopenharmony_ci return result; 2205bf215546Sopenharmony_ci } 2206bf215546Sopenharmony_ci assert(pdevice->display_fd != -1); 2207bf215546Sopenharmony_ci 2208bf215546Sopenharmony_ci mem->is_for_wsi = true; 2209bf215546Sopenharmony_ci 2210bf215546Sopenharmony_ci int display_fd = pdevice->display_fd; 2211bf215546Sopenharmony_ci struct drm_mode_create_dumb create_dumb = { 2212bf215546Sopenharmony_ci .width = 1024, /* one page */ 2213bf215546Sopenharmony_ci .height = align(size, 4096) / 4096, 2214bf215546Sopenharmony_ci .bpp = util_format_get_blocksizebits(PIPE_FORMAT_RGBA8888_UNORM), 2215bf215546Sopenharmony_ci }; 2216bf215546Sopenharmony_ci 2217bf215546Sopenharmony_ci int err; 2218bf215546Sopenharmony_ci err = v3dv_ioctl(display_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb); 2219bf215546Sopenharmony_ci if (err < 0) 2220bf215546Sopenharmony_ci goto fail_create; 2221bf215546Sopenharmony_ci 2222bf215546Sopenharmony_ci int fd; 2223bf215546Sopenharmony_ci err = 2224bf215546Sopenharmony_ci drmPrimeHandleToFD(display_fd, create_dumb.handle, O_CLOEXEC, &fd); 2225bf215546Sopenharmony_ci if (err < 0) 2226bf215546Sopenharmony_ci goto fail_export; 2227bf215546Sopenharmony_ci 2228bf215546Sopenharmony_ci result = device_import_bo(device, pAllocator, fd, size, &mem->bo); 2229bf215546Sopenharmony_ci close(fd); 2230bf215546Sopenharmony_ci if (result != VK_SUCCESS) 2231bf215546Sopenharmony_ci goto fail_import; 2232bf215546Sopenharmony_ci 2233bf215546Sopenharmony_ci mem->bo->dumb_handle = create_dumb.handle; 2234bf215546Sopenharmony_ci return VK_SUCCESS; 2235bf215546Sopenharmony_ci 2236bf215546Sopenharmony_cifail_import: 2237bf215546Sopenharmony_cifail_export: 2238bf215546Sopenharmony_ci device_free_wsi_dumb(display_fd, create_dumb.handle); 2239bf215546Sopenharmony_ci 2240bf215546Sopenharmony_cifail_create: 2241bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_DEVICE_MEMORY; 2242bf215546Sopenharmony_ci#endif 2243bf215546Sopenharmony_ci} 2244bf215546Sopenharmony_ci 2245bf215546Sopenharmony_cistatic void 2246bf215546Sopenharmony_cidevice_add_device_address_bo(struct v3dv_device *device, 2247bf215546Sopenharmony_ci struct v3dv_bo *bo) 2248bf215546Sopenharmony_ci{ 2249bf215546Sopenharmony_ci util_dynarray_append(&device->device_address_bo_list, 2250bf215546Sopenharmony_ci struct v3dv_bo *, 2251bf215546Sopenharmony_ci bo); 2252bf215546Sopenharmony_ci} 2253bf215546Sopenharmony_ci 2254bf215546Sopenharmony_cistatic void 2255bf215546Sopenharmony_cidevice_remove_device_address_bo(struct v3dv_device *device, 2256bf215546Sopenharmony_ci struct v3dv_bo *bo) 2257bf215546Sopenharmony_ci{ 2258bf215546Sopenharmony_ci util_dynarray_delete_unordered(&device->device_address_bo_list, 2259bf215546Sopenharmony_ci struct v3dv_bo *, 2260bf215546Sopenharmony_ci bo); 2261bf215546Sopenharmony_ci} 2262bf215546Sopenharmony_ci 2263bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2264bf215546Sopenharmony_civ3dv_AllocateMemory(VkDevice _device, 2265bf215546Sopenharmony_ci const VkMemoryAllocateInfo *pAllocateInfo, 2266bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 2267bf215546Sopenharmony_ci VkDeviceMemory *pMem) 2268bf215546Sopenharmony_ci{ 2269bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2270bf215546Sopenharmony_ci struct v3dv_device_memory *mem; 2271bf215546Sopenharmony_ci struct v3dv_physical_device *pdevice = &device->instance->physicalDevice; 2272bf215546Sopenharmony_ci 2273bf215546Sopenharmony_ci assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); 2274bf215546Sopenharmony_ci 2275bf215546Sopenharmony_ci /* The Vulkan 1.0.33 spec says "allocationSize must be greater than 0". */ 2276bf215546Sopenharmony_ci assert(pAllocateInfo->allocationSize > 0); 2277bf215546Sopenharmony_ci 2278bf215546Sopenharmony_ci mem = vk_object_zalloc(&device->vk, pAllocator, sizeof(*mem), 2279bf215546Sopenharmony_ci VK_OBJECT_TYPE_DEVICE_MEMORY); 2280bf215546Sopenharmony_ci if (mem == NULL) 2281bf215546Sopenharmony_ci return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); 2282bf215546Sopenharmony_ci 2283bf215546Sopenharmony_ci assert(pAllocateInfo->memoryTypeIndex < pdevice->memory.memoryTypeCount); 2284bf215546Sopenharmony_ci mem->type = &pdevice->memory.memoryTypes[pAllocateInfo->memoryTypeIndex]; 2285bf215546Sopenharmony_ci mem->is_for_wsi = false; 2286bf215546Sopenharmony_ci 2287bf215546Sopenharmony_ci const struct wsi_memory_allocate_info *wsi_info = NULL; 2288bf215546Sopenharmony_ci const VkImportMemoryFdInfoKHR *fd_info = NULL; 2289bf215546Sopenharmony_ci const VkMemoryAllocateFlagsInfo *flags_info = NULL; 2290bf215546Sopenharmony_ci vk_foreach_struct_const(ext, pAllocateInfo->pNext) { 2291bf215546Sopenharmony_ci switch ((unsigned)ext->sType) { 2292bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA: 2293bf215546Sopenharmony_ci wsi_info = (void *)ext; 2294bf215546Sopenharmony_ci break; 2295bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR: 2296bf215546Sopenharmony_ci fd_info = (void *)ext; 2297bf215546Sopenharmony_ci break; 2298bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO: 2299bf215546Sopenharmony_ci flags_info = (void *)ext; 2300bf215546Sopenharmony_ci break; 2301bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: 2302bf215546Sopenharmony_ci /* We don't have particular optimizations associated with memory 2303bf215546Sopenharmony_ci * allocations that won't be suballocated to multiple resources. 2304bf215546Sopenharmony_ci */ 2305bf215546Sopenharmony_ci break; 2306bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: 2307bf215546Sopenharmony_ci /* The mask of handle types specified here must be supported 2308bf215546Sopenharmony_ci * according to VkExternalImageFormatProperties, so it must be 2309bf215546Sopenharmony_ci * fd or dmabuf, which don't have special requirements for us. 2310bf215546Sopenharmony_ci */ 2311bf215546Sopenharmony_ci break; 2312bf215546Sopenharmony_ci default: 2313bf215546Sopenharmony_ci v3dv_debug_ignored_stype(ext->sType); 2314bf215546Sopenharmony_ci break; 2315bf215546Sopenharmony_ci } 2316bf215546Sopenharmony_ci } 2317bf215546Sopenharmony_ci 2318bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 2319bf215546Sopenharmony_ci 2320bf215546Sopenharmony_ci /* We always allocate device memory in multiples of a page, so round up 2321bf215546Sopenharmony_ci * requested size to that. 2322bf215546Sopenharmony_ci */ 2323bf215546Sopenharmony_ci VkDeviceSize alloc_size = ALIGN(pAllocateInfo->allocationSize, 4096); 2324bf215546Sopenharmony_ci 2325bf215546Sopenharmony_ci if (unlikely(alloc_size > MAX_MEMORY_ALLOCATION_SIZE)) { 2326bf215546Sopenharmony_ci result = VK_ERROR_OUT_OF_DEVICE_MEMORY; 2327bf215546Sopenharmony_ci } else { 2328bf215546Sopenharmony_ci if (wsi_info) { 2329bf215546Sopenharmony_ci result = device_alloc_for_wsi(device, pAllocator, mem, alloc_size); 2330bf215546Sopenharmony_ci } else if (fd_info && fd_info->handleType) { 2331bf215546Sopenharmony_ci assert(fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || 2332bf215546Sopenharmony_ci fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); 2333bf215546Sopenharmony_ci result = device_import_bo(device, pAllocator, 2334bf215546Sopenharmony_ci fd_info->fd, alloc_size, &mem->bo); 2335bf215546Sopenharmony_ci if (result == VK_SUCCESS) 2336bf215546Sopenharmony_ci close(fd_info->fd); 2337bf215546Sopenharmony_ci } else { 2338bf215546Sopenharmony_ci result = device_alloc(device, mem, alloc_size); 2339bf215546Sopenharmony_ci } 2340bf215546Sopenharmony_ci } 2341bf215546Sopenharmony_ci 2342bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 2343bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, mem); 2344bf215546Sopenharmony_ci return vk_error(device, result); 2345bf215546Sopenharmony_ci } 2346bf215546Sopenharmony_ci 2347bf215546Sopenharmony_ci /* If this memory can be used via VK_KHR_buffer_device_address then we 2348bf215546Sopenharmony_ci * will need to manually add the BO to any job submit that makes use of 2349bf215546Sopenharmony_ci * VK_KHR_buffer_device_address, since such jobs may produde buffer 2350bf215546Sopenharmony_ci * load/store operations that may access any buffer memory allocated with 2351bf215546Sopenharmony_ci * this flag and we don't have any means to tell which buffers will be 2352bf215546Sopenharmony_ci * accessed through this mechanism since they don't even have to be bound 2353bf215546Sopenharmony_ci * through descriptor state. 2354bf215546Sopenharmony_ci */ 2355bf215546Sopenharmony_ci if (flags_info && 2356bf215546Sopenharmony_ci (flags_info->flags & VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR)) { 2357bf215546Sopenharmony_ci mem->is_for_device_address = true; 2358bf215546Sopenharmony_ci device_add_device_address_bo(device, mem->bo); 2359bf215546Sopenharmony_ci } 2360bf215546Sopenharmony_ci 2361bf215546Sopenharmony_ci *pMem = v3dv_device_memory_to_handle(mem); 2362bf215546Sopenharmony_ci return result; 2363bf215546Sopenharmony_ci} 2364bf215546Sopenharmony_ci 2365bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2366bf215546Sopenharmony_civ3dv_FreeMemory(VkDevice _device, 2367bf215546Sopenharmony_ci VkDeviceMemory _mem, 2368bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 2369bf215546Sopenharmony_ci{ 2370bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2371bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device_memory, mem, _mem); 2372bf215546Sopenharmony_ci 2373bf215546Sopenharmony_ci if (mem == NULL) 2374bf215546Sopenharmony_ci return; 2375bf215546Sopenharmony_ci 2376bf215546Sopenharmony_ci if (mem->bo->map) 2377bf215546Sopenharmony_ci v3dv_UnmapMemory(_device, _mem); 2378bf215546Sopenharmony_ci 2379bf215546Sopenharmony_ci if (mem->is_for_device_address) 2380bf215546Sopenharmony_ci device_remove_device_address_bo(device, mem->bo); 2381bf215546Sopenharmony_ci 2382bf215546Sopenharmony_ci device_free(device, mem); 2383bf215546Sopenharmony_ci 2384bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, mem); 2385bf215546Sopenharmony_ci} 2386bf215546Sopenharmony_ci 2387bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2388bf215546Sopenharmony_civ3dv_MapMemory(VkDevice _device, 2389bf215546Sopenharmony_ci VkDeviceMemory _memory, 2390bf215546Sopenharmony_ci VkDeviceSize offset, 2391bf215546Sopenharmony_ci VkDeviceSize size, 2392bf215546Sopenharmony_ci VkMemoryMapFlags flags, 2393bf215546Sopenharmony_ci void **ppData) 2394bf215546Sopenharmony_ci{ 2395bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2396bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory); 2397bf215546Sopenharmony_ci 2398bf215546Sopenharmony_ci if (mem == NULL) { 2399bf215546Sopenharmony_ci *ppData = NULL; 2400bf215546Sopenharmony_ci return VK_SUCCESS; 2401bf215546Sopenharmony_ci } 2402bf215546Sopenharmony_ci 2403bf215546Sopenharmony_ci assert(offset < mem->bo->size); 2404bf215546Sopenharmony_ci 2405bf215546Sopenharmony_ci /* Since the driver can map BOs internally as well and the mapped range 2406bf215546Sopenharmony_ci * required by the user or the driver might not be the same, we always map 2407bf215546Sopenharmony_ci * the entire BO and then add the requested offset to the start address 2408bf215546Sopenharmony_ci * of the mapped region. 2409bf215546Sopenharmony_ci */ 2410bf215546Sopenharmony_ci VkResult result = device_map(device, mem); 2411bf215546Sopenharmony_ci if (result != VK_SUCCESS) 2412bf215546Sopenharmony_ci return vk_error(device, result); 2413bf215546Sopenharmony_ci 2414bf215546Sopenharmony_ci *ppData = ((uint8_t *) mem->bo->map) + offset; 2415bf215546Sopenharmony_ci return VK_SUCCESS; 2416bf215546Sopenharmony_ci} 2417bf215546Sopenharmony_ci 2418bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2419bf215546Sopenharmony_civ3dv_UnmapMemory(VkDevice _device, 2420bf215546Sopenharmony_ci VkDeviceMemory _memory) 2421bf215546Sopenharmony_ci{ 2422bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2423bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory); 2424bf215546Sopenharmony_ci 2425bf215546Sopenharmony_ci if (mem == NULL) 2426bf215546Sopenharmony_ci return; 2427bf215546Sopenharmony_ci 2428bf215546Sopenharmony_ci device_unmap(device, mem); 2429bf215546Sopenharmony_ci} 2430bf215546Sopenharmony_ci 2431bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2432bf215546Sopenharmony_civ3dv_FlushMappedMemoryRanges(VkDevice _device, 2433bf215546Sopenharmony_ci uint32_t memoryRangeCount, 2434bf215546Sopenharmony_ci const VkMappedMemoryRange *pMemoryRanges) 2435bf215546Sopenharmony_ci{ 2436bf215546Sopenharmony_ci return VK_SUCCESS; 2437bf215546Sopenharmony_ci} 2438bf215546Sopenharmony_ci 2439bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2440bf215546Sopenharmony_civ3dv_InvalidateMappedMemoryRanges(VkDevice _device, 2441bf215546Sopenharmony_ci uint32_t memoryRangeCount, 2442bf215546Sopenharmony_ci const VkMappedMemoryRange *pMemoryRanges) 2443bf215546Sopenharmony_ci{ 2444bf215546Sopenharmony_ci return VK_SUCCESS; 2445bf215546Sopenharmony_ci} 2446bf215546Sopenharmony_ci 2447bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2448bf215546Sopenharmony_civ3dv_GetImageMemoryRequirements2(VkDevice device, 2449bf215546Sopenharmony_ci const VkImageMemoryRequirementsInfo2 *pInfo, 2450bf215546Sopenharmony_ci VkMemoryRequirements2 *pMemoryRequirements) 2451bf215546Sopenharmony_ci{ 2452bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_image, image, pInfo->image); 2453bf215546Sopenharmony_ci 2454bf215546Sopenharmony_ci pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) { 2455bf215546Sopenharmony_ci .memoryTypeBits = 0x1, 2456bf215546Sopenharmony_ci .alignment = image->alignment, 2457bf215546Sopenharmony_ci .size = image->size 2458bf215546Sopenharmony_ci }; 2459bf215546Sopenharmony_ci 2460bf215546Sopenharmony_ci vk_foreach_struct(ext, pMemoryRequirements->pNext) { 2461bf215546Sopenharmony_ci switch (ext->sType) { 2462bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { 2463bf215546Sopenharmony_ci VkMemoryDedicatedRequirements *req = 2464bf215546Sopenharmony_ci (VkMemoryDedicatedRequirements *) ext; 2465bf215546Sopenharmony_ci req->requiresDedicatedAllocation = image->vk.external_handle_types != 0; 2466bf215546Sopenharmony_ci req->prefersDedicatedAllocation = image->vk.external_handle_types != 0; 2467bf215546Sopenharmony_ci break; 2468bf215546Sopenharmony_ci } 2469bf215546Sopenharmony_ci default: 2470bf215546Sopenharmony_ci v3dv_debug_ignored_stype(ext->sType); 2471bf215546Sopenharmony_ci break; 2472bf215546Sopenharmony_ci } 2473bf215546Sopenharmony_ci } 2474bf215546Sopenharmony_ci} 2475bf215546Sopenharmony_ci 2476bf215546Sopenharmony_cistatic void 2477bf215546Sopenharmony_cibind_image_memory(const VkBindImageMemoryInfo *info) 2478bf215546Sopenharmony_ci{ 2479bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_image, image, info->image); 2480bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device_memory, mem, info->memory); 2481bf215546Sopenharmony_ci 2482bf215546Sopenharmony_ci /* Valid usage: 2483bf215546Sopenharmony_ci * 2484bf215546Sopenharmony_ci * "memoryOffset must be an integer multiple of the alignment member of 2485bf215546Sopenharmony_ci * the VkMemoryRequirements structure returned from a call to 2486bf215546Sopenharmony_ci * vkGetImageMemoryRequirements with image" 2487bf215546Sopenharmony_ci */ 2488bf215546Sopenharmony_ci assert(info->memoryOffset % image->alignment == 0); 2489bf215546Sopenharmony_ci assert(info->memoryOffset < mem->bo->size); 2490bf215546Sopenharmony_ci 2491bf215546Sopenharmony_ci image->mem = mem; 2492bf215546Sopenharmony_ci image->mem_offset = info->memoryOffset; 2493bf215546Sopenharmony_ci} 2494bf215546Sopenharmony_ci 2495bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2496bf215546Sopenharmony_civ3dv_BindImageMemory2(VkDevice _device, 2497bf215546Sopenharmony_ci uint32_t bindInfoCount, 2498bf215546Sopenharmony_ci const VkBindImageMemoryInfo *pBindInfos) 2499bf215546Sopenharmony_ci{ 2500bf215546Sopenharmony_ci for (uint32_t i = 0; i < bindInfoCount; i++) { 2501bf215546Sopenharmony_ci const VkBindImageMemorySwapchainInfoKHR *swapchain_info = 2502bf215546Sopenharmony_ci vk_find_struct_const(pBindInfos->pNext, 2503bf215546Sopenharmony_ci BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR); 2504bf215546Sopenharmony_ci if (swapchain_info && swapchain_info->swapchain) { 2505bf215546Sopenharmony_ci struct v3dv_image *swapchain_image = 2506bf215546Sopenharmony_ci v3dv_wsi_get_image_from_swapchain(swapchain_info->swapchain, 2507bf215546Sopenharmony_ci swapchain_info->imageIndex); 2508bf215546Sopenharmony_ci VkBindImageMemoryInfo swapchain_bind = { 2509bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, 2510bf215546Sopenharmony_ci .image = pBindInfos[i].image, 2511bf215546Sopenharmony_ci .memory = v3dv_device_memory_to_handle(swapchain_image->mem), 2512bf215546Sopenharmony_ci .memoryOffset = swapchain_image->mem_offset, 2513bf215546Sopenharmony_ci }; 2514bf215546Sopenharmony_ci bind_image_memory(&swapchain_bind); 2515bf215546Sopenharmony_ci } else { 2516bf215546Sopenharmony_ci bind_image_memory(&pBindInfos[i]); 2517bf215546Sopenharmony_ci } 2518bf215546Sopenharmony_ci } 2519bf215546Sopenharmony_ci 2520bf215546Sopenharmony_ci return VK_SUCCESS; 2521bf215546Sopenharmony_ci} 2522bf215546Sopenharmony_ci 2523bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2524bf215546Sopenharmony_civ3dv_GetBufferMemoryRequirements2(VkDevice device, 2525bf215546Sopenharmony_ci const VkBufferMemoryRequirementsInfo2 *pInfo, 2526bf215546Sopenharmony_ci VkMemoryRequirements2 *pMemoryRequirements) 2527bf215546Sopenharmony_ci{ 2528bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_buffer, buffer, pInfo->buffer); 2529bf215546Sopenharmony_ci 2530bf215546Sopenharmony_ci pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) { 2531bf215546Sopenharmony_ci .memoryTypeBits = 0x1, 2532bf215546Sopenharmony_ci .alignment = buffer->alignment, 2533bf215546Sopenharmony_ci .size = align64(buffer->size, buffer->alignment), 2534bf215546Sopenharmony_ci }; 2535bf215546Sopenharmony_ci 2536bf215546Sopenharmony_ci vk_foreach_struct(ext, pMemoryRequirements->pNext) { 2537bf215546Sopenharmony_ci switch (ext->sType) { 2538bf215546Sopenharmony_ci case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { 2539bf215546Sopenharmony_ci VkMemoryDedicatedRequirements *req = 2540bf215546Sopenharmony_ci (VkMemoryDedicatedRequirements *) ext; 2541bf215546Sopenharmony_ci req->requiresDedicatedAllocation = false; 2542bf215546Sopenharmony_ci req->prefersDedicatedAllocation = false; 2543bf215546Sopenharmony_ci break; 2544bf215546Sopenharmony_ci } 2545bf215546Sopenharmony_ci default: 2546bf215546Sopenharmony_ci v3dv_debug_ignored_stype(ext->sType); 2547bf215546Sopenharmony_ci break; 2548bf215546Sopenharmony_ci } 2549bf215546Sopenharmony_ci } 2550bf215546Sopenharmony_ci} 2551bf215546Sopenharmony_ci 2552bf215546Sopenharmony_cistatic void 2553bf215546Sopenharmony_cibind_buffer_memory(const VkBindBufferMemoryInfo *info) 2554bf215546Sopenharmony_ci{ 2555bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_buffer, buffer, info->buffer); 2556bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device_memory, mem, info->memory); 2557bf215546Sopenharmony_ci 2558bf215546Sopenharmony_ci /* Valid usage: 2559bf215546Sopenharmony_ci * 2560bf215546Sopenharmony_ci * "memoryOffset must be an integer multiple of the alignment member of 2561bf215546Sopenharmony_ci * the VkMemoryRequirements structure returned from a call to 2562bf215546Sopenharmony_ci * vkGetBufferMemoryRequirements with buffer" 2563bf215546Sopenharmony_ci */ 2564bf215546Sopenharmony_ci assert(info->memoryOffset % buffer->alignment == 0); 2565bf215546Sopenharmony_ci assert(info->memoryOffset < mem->bo->size); 2566bf215546Sopenharmony_ci 2567bf215546Sopenharmony_ci buffer->mem = mem; 2568bf215546Sopenharmony_ci buffer->mem_offset = info->memoryOffset; 2569bf215546Sopenharmony_ci} 2570bf215546Sopenharmony_ci 2571bf215546Sopenharmony_ci 2572bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2573bf215546Sopenharmony_civ3dv_BindBufferMemory2(VkDevice device, 2574bf215546Sopenharmony_ci uint32_t bindInfoCount, 2575bf215546Sopenharmony_ci const VkBindBufferMemoryInfo *pBindInfos) 2576bf215546Sopenharmony_ci{ 2577bf215546Sopenharmony_ci for (uint32_t i = 0; i < bindInfoCount; i++) 2578bf215546Sopenharmony_ci bind_buffer_memory(&pBindInfos[i]); 2579bf215546Sopenharmony_ci 2580bf215546Sopenharmony_ci return VK_SUCCESS; 2581bf215546Sopenharmony_ci} 2582bf215546Sopenharmony_ci 2583bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2584bf215546Sopenharmony_civ3dv_CreateBuffer(VkDevice _device, 2585bf215546Sopenharmony_ci const VkBufferCreateInfo *pCreateInfo, 2586bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 2587bf215546Sopenharmony_ci VkBuffer *pBuffer) 2588bf215546Sopenharmony_ci{ 2589bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2590bf215546Sopenharmony_ci struct v3dv_buffer *buffer; 2591bf215546Sopenharmony_ci 2592bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO); 2593bf215546Sopenharmony_ci assert(pCreateInfo->usage != 0); 2594bf215546Sopenharmony_ci 2595bf215546Sopenharmony_ci /* We don't support any flags for now */ 2596bf215546Sopenharmony_ci assert(pCreateInfo->flags == 0); 2597bf215546Sopenharmony_ci 2598bf215546Sopenharmony_ci buffer = vk_object_zalloc(&device->vk, pAllocator, sizeof(*buffer), 2599bf215546Sopenharmony_ci VK_OBJECT_TYPE_BUFFER); 2600bf215546Sopenharmony_ci if (buffer == NULL) 2601bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2602bf215546Sopenharmony_ci 2603bf215546Sopenharmony_ci buffer->size = pCreateInfo->size; 2604bf215546Sopenharmony_ci buffer->usage = pCreateInfo->usage; 2605bf215546Sopenharmony_ci buffer->alignment = V3D_NON_COHERENT_ATOM_SIZE; 2606bf215546Sopenharmony_ci 2607bf215546Sopenharmony_ci /* Limit allocations to 32-bit */ 2608bf215546Sopenharmony_ci const VkDeviceSize aligned_size = align64(buffer->size, buffer->alignment); 2609bf215546Sopenharmony_ci if (aligned_size > UINT32_MAX || aligned_size < buffer->size) { 2610bf215546Sopenharmony_ci vk_free(&device->vk.alloc, buffer); 2611bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_DEVICE_MEMORY; 2612bf215546Sopenharmony_ci } 2613bf215546Sopenharmony_ci 2614bf215546Sopenharmony_ci *pBuffer = v3dv_buffer_to_handle(buffer); 2615bf215546Sopenharmony_ci 2616bf215546Sopenharmony_ci return VK_SUCCESS; 2617bf215546Sopenharmony_ci} 2618bf215546Sopenharmony_ci 2619bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2620bf215546Sopenharmony_civ3dv_DestroyBuffer(VkDevice _device, 2621bf215546Sopenharmony_ci VkBuffer _buffer, 2622bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 2623bf215546Sopenharmony_ci{ 2624bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2625bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_buffer, buffer, _buffer); 2626bf215546Sopenharmony_ci 2627bf215546Sopenharmony_ci if (!buffer) 2628bf215546Sopenharmony_ci return; 2629bf215546Sopenharmony_ci 2630bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, buffer); 2631bf215546Sopenharmony_ci} 2632bf215546Sopenharmony_ci 2633bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2634bf215546Sopenharmony_civ3dv_CreateFramebuffer(VkDevice _device, 2635bf215546Sopenharmony_ci const VkFramebufferCreateInfo *pCreateInfo, 2636bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 2637bf215546Sopenharmony_ci VkFramebuffer *pFramebuffer) 2638bf215546Sopenharmony_ci{ 2639bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2640bf215546Sopenharmony_ci struct v3dv_framebuffer *framebuffer; 2641bf215546Sopenharmony_ci 2642bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); 2643bf215546Sopenharmony_ci 2644bf215546Sopenharmony_ci size_t size = sizeof(*framebuffer) + 2645bf215546Sopenharmony_ci sizeof(struct v3dv_image_view *) * pCreateInfo->attachmentCount; 2646bf215546Sopenharmony_ci framebuffer = vk_object_zalloc(&device->vk, pAllocator, size, 2647bf215546Sopenharmony_ci VK_OBJECT_TYPE_FRAMEBUFFER); 2648bf215546Sopenharmony_ci if (framebuffer == NULL) 2649bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2650bf215546Sopenharmony_ci 2651bf215546Sopenharmony_ci framebuffer->width = pCreateInfo->width; 2652bf215546Sopenharmony_ci framebuffer->height = pCreateInfo->height; 2653bf215546Sopenharmony_ci framebuffer->layers = pCreateInfo->layers; 2654bf215546Sopenharmony_ci framebuffer->has_edge_padding = true; 2655bf215546Sopenharmony_ci 2656bf215546Sopenharmony_ci const VkFramebufferAttachmentsCreateInfo *imageless = 2657bf215546Sopenharmony_ci vk_find_struct_const(pCreateInfo->pNext, 2658bf215546Sopenharmony_ci FRAMEBUFFER_ATTACHMENTS_CREATE_INFO); 2659bf215546Sopenharmony_ci 2660bf215546Sopenharmony_ci framebuffer->attachment_count = pCreateInfo->attachmentCount; 2661bf215546Sopenharmony_ci framebuffer->color_attachment_count = 0; 2662bf215546Sopenharmony_ci for (uint32_t i = 0; i < framebuffer->attachment_count; i++) { 2663bf215546Sopenharmony_ci if (!imageless) { 2664bf215546Sopenharmony_ci framebuffer->attachments[i] = 2665bf215546Sopenharmony_ci v3dv_image_view_from_handle(pCreateInfo->pAttachments[i]); 2666bf215546Sopenharmony_ci if (framebuffer->attachments[i]->vk.aspects & VK_IMAGE_ASPECT_COLOR_BIT) 2667bf215546Sopenharmony_ci framebuffer->color_attachment_count++; 2668bf215546Sopenharmony_ci } else { 2669bf215546Sopenharmony_ci assert(i < imageless->attachmentImageInfoCount); 2670bf215546Sopenharmony_ci if (imageless->pAttachmentImageInfos[i].usage & 2671bf215546Sopenharmony_ci VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) { 2672bf215546Sopenharmony_ci framebuffer->color_attachment_count++; 2673bf215546Sopenharmony_ci } 2674bf215546Sopenharmony_ci } 2675bf215546Sopenharmony_ci } 2676bf215546Sopenharmony_ci 2677bf215546Sopenharmony_ci *pFramebuffer = v3dv_framebuffer_to_handle(framebuffer); 2678bf215546Sopenharmony_ci 2679bf215546Sopenharmony_ci return VK_SUCCESS; 2680bf215546Sopenharmony_ci} 2681bf215546Sopenharmony_ci 2682bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2683bf215546Sopenharmony_civ3dv_DestroyFramebuffer(VkDevice _device, 2684bf215546Sopenharmony_ci VkFramebuffer _fb, 2685bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 2686bf215546Sopenharmony_ci{ 2687bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2688bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_framebuffer, fb, _fb); 2689bf215546Sopenharmony_ci 2690bf215546Sopenharmony_ci if (!fb) 2691bf215546Sopenharmony_ci return; 2692bf215546Sopenharmony_ci 2693bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, fb); 2694bf215546Sopenharmony_ci} 2695bf215546Sopenharmony_ci 2696bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2697bf215546Sopenharmony_civ3dv_GetMemoryFdPropertiesKHR(VkDevice _device, 2698bf215546Sopenharmony_ci VkExternalMemoryHandleTypeFlagBits handleType, 2699bf215546Sopenharmony_ci int fd, 2700bf215546Sopenharmony_ci VkMemoryFdPropertiesKHR *pMemoryFdProperties) 2701bf215546Sopenharmony_ci{ 2702bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2703bf215546Sopenharmony_ci struct v3dv_physical_device *pdevice = &device->instance->physicalDevice; 2704bf215546Sopenharmony_ci 2705bf215546Sopenharmony_ci switch (handleType) { 2706bf215546Sopenharmony_ci case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT: 2707bf215546Sopenharmony_ci pMemoryFdProperties->memoryTypeBits = 2708bf215546Sopenharmony_ci (1 << pdevice->memory.memoryTypeCount) - 1; 2709bf215546Sopenharmony_ci return VK_SUCCESS; 2710bf215546Sopenharmony_ci default: 2711bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE); 2712bf215546Sopenharmony_ci } 2713bf215546Sopenharmony_ci} 2714bf215546Sopenharmony_ci 2715bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2716bf215546Sopenharmony_civ3dv_GetMemoryFdKHR(VkDevice _device, 2717bf215546Sopenharmony_ci const VkMemoryGetFdInfoKHR *pGetFdInfo, 2718bf215546Sopenharmony_ci int *pFd) 2719bf215546Sopenharmony_ci{ 2720bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2721bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device_memory, mem, pGetFdInfo->memory); 2722bf215546Sopenharmony_ci 2723bf215546Sopenharmony_ci assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR); 2724bf215546Sopenharmony_ci assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT || 2725bf215546Sopenharmony_ci pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); 2726bf215546Sopenharmony_ci 2727bf215546Sopenharmony_ci int fd, ret; 2728bf215546Sopenharmony_ci ret = drmPrimeHandleToFD(device->pdevice->render_fd, 2729bf215546Sopenharmony_ci mem->bo->handle, 2730bf215546Sopenharmony_ci DRM_CLOEXEC, &fd); 2731bf215546Sopenharmony_ci if (ret) 2732bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2733bf215546Sopenharmony_ci 2734bf215546Sopenharmony_ci *pFd = fd; 2735bf215546Sopenharmony_ci 2736bf215546Sopenharmony_ci return VK_SUCCESS; 2737bf215546Sopenharmony_ci} 2738bf215546Sopenharmony_ci 2739bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2740bf215546Sopenharmony_civ3dv_CreateEvent(VkDevice _device, 2741bf215546Sopenharmony_ci const VkEventCreateInfo *pCreateInfo, 2742bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 2743bf215546Sopenharmony_ci VkEvent *pEvent) 2744bf215546Sopenharmony_ci{ 2745bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2746bf215546Sopenharmony_ci struct v3dv_event *event = 2747bf215546Sopenharmony_ci vk_object_zalloc(&device->vk, pAllocator, sizeof(*event), 2748bf215546Sopenharmony_ci VK_OBJECT_TYPE_EVENT); 2749bf215546Sopenharmony_ci if (!event) 2750bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2751bf215546Sopenharmony_ci 2752bf215546Sopenharmony_ci /* Events are created in the unsignaled state */ 2753bf215546Sopenharmony_ci event->state = false; 2754bf215546Sopenharmony_ci *pEvent = v3dv_event_to_handle(event); 2755bf215546Sopenharmony_ci 2756bf215546Sopenharmony_ci return VK_SUCCESS; 2757bf215546Sopenharmony_ci} 2758bf215546Sopenharmony_ci 2759bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2760bf215546Sopenharmony_civ3dv_DestroyEvent(VkDevice _device, 2761bf215546Sopenharmony_ci VkEvent _event, 2762bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 2763bf215546Sopenharmony_ci{ 2764bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2765bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_event, event, _event); 2766bf215546Sopenharmony_ci 2767bf215546Sopenharmony_ci if (!event) 2768bf215546Sopenharmony_ci return; 2769bf215546Sopenharmony_ci 2770bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, event); 2771bf215546Sopenharmony_ci} 2772bf215546Sopenharmony_ci 2773bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2774bf215546Sopenharmony_civ3dv_GetEventStatus(VkDevice _device, VkEvent _event) 2775bf215546Sopenharmony_ci{ 2776bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_event, event, _event); 2777bf215546Sopenharmony_ci return p_atomic_read(&event->state) ? VK_EVENT_SET : VK_EVENT_RESET; 2778bf215546Sopenharmony_ci} 2779bf215546Sopenharmony_ci 2780bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2781bf215546Sopenharmony_civ3dv_SetEvent(VkDevice _device, VkEvent _event) 2782bf215546Sopenharmony_ci{ 2783bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_event, event, _event); 2784bf215546Sopenharmony_ci p_atomic_set(&event->state, 1); 2785bf215546Sopenharmony_ci return VK_SUCCESS; 2786bf215546Sopenharmony_ci} 2787bf215546Sopenharmony_ci 2788bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2789bf215546Sopenharmony_civ3dv_ResetEvent(VkDevice _device, VkEvent _event) 2790bf215546Sopenharmony_ci{ 2791bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_event, event, _event); 2792bf215546Sopenharmony_ci p_atomic_set(&event->state, 0); 2793bf215546Sopenharmony_ci return VK_SUCCESS; 2794bf215546Sopenharmony_ci} 2795bf215546Sopenharmony_ci 2796bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 2797bf215546Sopenharmony_civ3dv_CreateSampler(VkDevice _device, 2798bf215546Sopenharmony_ci const VkSamplerCreateInfo *pCreateInfo, 2799bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 2800bf215546Sopenharmony_ci VkSampler *pSampler) 2801bf215546Sopenharmony_ci{ 2802bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2803bf215546Sopenharmony_ci struct v3dv_sampler *sampler; 2804bf215546Sopenharmony_ci 2805bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); 2806bf215546Sopenharmony_ci 2807bf215546Sopenharmony_ci sampler = vk_object_zalloc(&device->vk, pAllocator, sizeof(*sampler), 2808bf215546Sopenharmony_ci VK_OBJECT_TYPE_SAMPLER); 2809bf215546Sopenharmony_ci if (!sampler) 2810bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 2811bf215546Sopenharmony_ci 2812bf215546Sopenharmony_ci sampler->compare_enable = pCreateInfo->compareEnable; 2813bf215546Sopenharmony_ci sampler->unnormalized_coordinates = pCreateInfo->unnormalizedCoordinates; 2814bf215546Sopenharmony_ci 2815bf215546Sopenharmony_ci const VkSamplerCustomBorderColorCreateInfoEXT *bc_info = 2816bf215546Sopenharmony_ci vk_find_struct_const(pCreateInfo->pNext, 2817bf215546Sopenharmony_ci SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT); 2818bf215546Sopenharmony_ci 2819bf215546Sopenharmony_ci v3dv_X(device, pack_sampler_state)(sampler, pCreateInfo, bc_info); 2820bf215546Sopenharmony_ci 2821bf215546Sopenharmony_ci *pSampler = v3dv_sampler_to_handle(sampler); 2822bf215546Sopenharmony_ci 2823bf215546Sopenharmony_ci return VK_SUCCESS; 2824bf215546Sopenharmony_ci} 2825bf215546Sopenharmony_ci 2826bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2827bf215546Sopenharmony_civ3dv_DestroySampler(VkDevice _device, 2828bf215546Sopenharmony_ci VkSampler _sampler, 2829bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 2830bf215546Sopenharmony_ci{ 2831bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 2832bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_sampler, sampler, _sampler); 2833bf215546Sopenharmony_ci 2834bf215546Sopenharmony_ci if (!sampler) 2835bf215546Sopenharmony_ci return; 2836bf215546Sopenharmony_ci 2837bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, sampler); 2838bf215546Sopenharmony_ci} 2839bf215546Sopenharmony_ci 2840bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2841bf215546Sopenharmony_civ3dv_GetDeviceMemoryCommitment(VkDevice device, 2842bf215546Sopenharmony_ci VkDeviceMemory memory, 2843bf215546Sopenharmony_ci VkDeviceSize *pCommittedMemoryInBytes) 2844bf215546Sopenharmony_ci{ 2845bf215546Sopenharmony_ci *pCommittedMemoryInBytes = 0; 2846bf215546Sopenharmony_ci} 2847bf215546Sopenharmony_ci 2848bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2849bf215546Sopenharmony_civ3dv_GetImageSparseMemoryRequirements( 2850bf215546Sopenharmony_ci VkDevice device, 2851bf215546Sopenharmony_ci VkImage image, 2852bf215546Sopenharmony_ci uint32_t *pSparseMemoryRequirementCount, 2853bf215546Sopenharmony_ci VkSparseImageMemoryRequirements *pSparseMemoryRequirements) 2854bf215546Sopenharmony_ci{ 2855bf215546Sopenharmony_ci *pSparseMemoryRequirementCount = 0; 2856bf215546Sopenharmony_ci} 2857bf215546Sopenharmony_ci 2858bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 2859bf215546Sopenharmony_civ3dv_GetImageSparseMemoryRequirements2( 2860bf215546Sopenharmony_ci VkDevice device, 2861bf215546Sopenharmony_ci const VkImageSparseMemoryRequirementsInfo2 *pInfo, 2862bf215546Sopenharmony_ci uint32_t *pSparseMemoryRequirementCount, 2863bf215546Sopenharmony_ci VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements) 2864bf215546Sopenharmony_ci{ 2865bf215546Sopenharmony_ci *pSparseMemoryRequirementCount = 0; 2866bf215546Sopenharmony_ci} 2867bf215546Sopenharmony_ci 2868bf215546Sopenharmony_ci/* vk_icd.h does not declare this function, so we declare it here to 2869bf215546Sopenharmony_ci * suppress Wmissing-prototypes. 2870bf215546Sopenharmony_ci */ 2871bf215546Sopenharmony_ciPUBLIC VKAPI_ATTR VkResult VKAPI_CALL 2872bf215546Sopenharmony_civk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion); 2873bf215546Sopenharmony_ci 2874bf215546Sopenharmony_ciPUBLIC VKAPI_ATTR VkResult VKAPI_CALL 2875bf215546Sopenharmony_civk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) 2876bf215546Sopenharmony_ci{ 2877bf215546Sopenharmony_ci /* For the full details on loader interface versioning, see 2878bf215546Sopenharmony_ci * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>. 2879bf215546Sopenharmony_ci * What follows is a condensed summary, to help you navigate the large and 2880bf215546Sopenharmony_ci * confusing official doc. 2881bf215546Sopenharmony_ci * 2882bf215546Sopenharmony_ci * - Loader interface v0 is incompatible with later versions. We don't 2883bf215546Sopenharmony_ci * support it. 2884bf215546Sopenharmony_ci * 2885bf215546Sopenharmony_ci * - In loader interface v1: 2886bf215546Sopenharmony_ci * - The first ICD entrypoint called by the loader is 2887bf215546Sopenharmony_ci * vk_icdGetInstanceProcAddr(). The ICD must statically expose this 2888bf215546Sopenharmony_ci * entrypoint. 2889bf215546Sopenharmony_ci * - The ICD must statically expose no other Vulkan symbol unless it is 2890bf215546Sopenharmony_ci * linked with -Bsymbolic. 2891bf215546Sopenharmony_ci * - Each dispatchable Vulkan handle created by the ICD must be 2892bf215546Sopenharmony_ci * a pointer to a struct whose first member is VK_LOADER_DATA. The 2893bf215546Sopenharmony_ci * ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC. 2894bf215546Sopenharmony_ci * - The loader implements vkCreate{PLATFORM}SurfaceKHR() and 2895bf215546Sopenharmony_ci * vkDestroySurfaceKHR(). The ICD must be capable of working with 2896bf215546Sopenharmony_ci * such loader-managed surfaces. 2897bf215546Sopenharmony_ci * 2898bf215546Sopenharmony_ci * - Loader interface v2 differs from v1 in: 2899bf215546Sopenharmony_ci * - The first ICD entrypoint called by the loader is 2900bf215546Sopenharmony_ci * vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must 2901bf215546Sopenharmony_ci * statically expose this entrypoint. 2902bf215546Sopenharmony_ci * 2903bf215546Sopenharmony_ci * - Loader interface v3 differs from v2 in: 2904bf215546Sopenharmony_ci * - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(), 2905bf215546Sopenharmony_ci * vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR, 2906bf215546Sopenharmony_ci * because the loader no longer does so. 2907bf215546Sopenharmony_ci * 2908bf215546Sopenharmony_ci * - Loader interface v4 differs from v3 in: 2909bf215546Sopenharmony_ci * - The ICD must implement vk_icdGetPhysicalDeviceProcAddr(). 2910bf215546Sopenharmony_ci * 2911bf215546Sopenharmony_ci * - Loader interface v5 differs from v4 in: 2912bf215546Sopenharmony_ci * - The ICD must support Vulkan API version 1.1 and must not return 2913bf215546Sopenharmony_ci * VK_ERROR_INCOMPATIBLE_DRIVER from vkCreateInstance() unless a 2914bf215546Sopenharmony_ci * Vulkan Loader with interface v4 or smaller is being used and the 2915bf215546Sopenharmony_ci * application provides an API version that is greater than 1.0. 2916bf215546Sopenharmony_ci */ 2917bf215546Sopenharmony_ci *pSupportedVersion = MIN2(*pSupportedVersion, 5u); 2918bf215546Sopenharmony_ci return VK_SUCCESS; 2919bf215546Sopenharmony_ci} 2920bf215546Sopenharmony_ci 2921bf215546Sopenharmony_ciVkDeviceAddress 2922bf215546Sopenharmony_civ3dv_GetBufferDeviceAddress(VkDevice device, 2923bf215546Sopenharmony_ci const VkBufferDeviceAddressInfoKHR *pInfo) 2924bf215546Sopenharmony_ci{ 2925bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_buffer, buffer, pInfo->buffer); 2926bf215546Sopenharmony_ci return buffer->mem_offset + buffer->mem->bo->offset; 2927bf215546Sopenharmony_ci} 2928bf215546Sopenharmony_ci 2929bf215546Sopenharmony_ciuint64_t 2930bf215546Sopenharmony_civ3dv_GetBufferOpaqueCaptureAddress(VkDevice device, 2931bf215546Sopenharmony_ci const VkBufferDeviceAddressInfoKHR *pInfo) 2932bf215546Sopenharmony_ci{ 2933bf215546Sopenharmony_ci /* Not implemented */ 2934bf215546Sopenharmony_ci return 0; 2935bf215546Sopenharmony_ci} 2936bf215546Sopenharmony_ci 2937bf215546Sopenharmony_ciuint64_t 2938bf215546Sopenharmony_civ3dv_GetDeviceMemoryOpaqueCaptureAddress( 2939bf215546Sopenharmony_ci VkDevice device, 2940bf215546Sopenharmony_ci const VkDeviceMemoryOpaqueCaptureAddressInfoKHR *pInfo) 2941bf215546Sopenharmony_ci{ 2942bf215546Sopenharmony_ci /* Not implemented */ 2943bf215546Sopenharmony_ci return 0; 2944bf215546Sopenharmony_ci} 2945