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