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