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, &registry_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