Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/freedreno/vulkan/tu_device.c
4565 views
1
/*
2
* Copyright © 2016 Red Hat.
3
* Copyright © 2016 Bas Nieuwenhuizen
4
*
5
* based in part on anv driver which is:
6
* Copyright © 2015 Intel Corporation
7
*
8
* Permission is hereby granted, free of charge, to any person obtaining a
9
* copy of this software and associated documentation files (the "Software"),
10
* to deal in the Software without restriction, including without limitation
11
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
12
* and/or sell copies of the Software, and to permit persons to whom the
13
* Software is furnished to do so, subject to the following conditions:
14
*
15
* The above copyright notice and this permission notice (including the next
16
* paragraph) shall be included in all copies or substantial portions of the
17
* Software.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
* DEALINGS IN THE SOFTWARE.
26
*/
27
28
#include "tu_private.h"
29
#include "tu_cs.h"
30
31
#include <fcntl.h>
32
#include <poll.h>
33
#include <stdbool.h>
34
#include <string.h>
35
#include <sys/sysinfo.h>
36
#include <unistd.h>
37
38
#include "util/debug.h"
39
#include "util/disk_cache.h"
40
#include "util/u_atomic.h"
41
#include "vk_format.h"
42
#include "vk_util.h"
43
44
/* for fd_get_driver/device_uuid() */
45
#include "freedreno/common/freedreno_uuid.h"
46
47
#if defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
48
defined(VK_USE_PLATFORM_XCB_KHR) || \
49
defined(VK_USE_PLATFORM_XLIB_KHR) || \
50
defined(VK_USE_PLATFORM_DISPLAY_KHR)
51
#define TU_HAS_SURFACE 1
52
#else
53
#define TU_HAS_SURFACE 0
54
#endif
55
56
57
static int
58
tu_device_get_cache_uuid(uint16_t family, void *uuid)
59
{
60
uint32_t mesa_timestamp;
61
uint16_t f = family;
62
memset(uuid, 0, VK_UUID_SIZE);
63
if (!disk_cache_get_function_timestamp(tu_device_get_cache_uuid,
64
&mesa_timestamp))
65
return -1;
66
67
memcpy(uuid, &mesa_timestamp, 4);
68
memcpy((char *) uuid + 4, &f, 2);
69
snprintf((char *) uuid + 6, VK_UUID_SIZE - 10, "tu");
70
return 0;
71
}
72
73
#define TU_API_VERSION VK_MAKE_VERSION(1, 1, VK_HEADER_VERSION)
74
75
VKAPI_ATTR VkResult VKAPI_CALL
76
tu_EnumerateInstanceVersion(uint32_t *pApiVersion)
77
{
78
*pApiVersion = TU_API_VERSION;
79
return VK_SUCCESS;
80
}
81
82
static const struct vk_instance_extension_table tu_instance_extensions_supported = {
83
.KHR_device_group_creation = true,
84
.KHR_external_fence_capabilities = true,
85
.KHR_external_memory_capabilities = true,
86
.KHR_external_semaphore_capabilities = true,
87
.KHR_get_physical_device_properties2 = true,
88
.KHR_surface = TU_HAS_SURFACE,
89
.KHR_get_surface_capabilities2 = TU_HAS_SURFACE,
90
.EXT_debug_report = true,
91
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
92
.KHR_wayland_surface = true,
93
#endif
94
#ifdef VK_USE_PLATFORM_XCB_KHR
95
.KHR_xcb_surface = true,
96
#endif
97
#ifdef VK_USE_PLATFORM_XLIB_KHR
98
.KHR_xlib_surface = true,
99
#endif
100
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
101
.EXT_acquire_xlib_display = true,
102
#endif
103
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
104
.KHR_display = true,
105
.KHR_get_display_properties2 = true,
106
.EXT_direct_mode_display = true,
107
.EXT_display_surface_counter = true,
108
#endif
109
};
110
111
static void
112
get_device_extensions(const struct tu_physical_device *device,
113
struct vk_device_extension_table *ext)
114
{
115
*ext = (struct vk_device_extension_table) {
116
.KHR_16bit_storage = device->info->a6xx.storage_16bit,
117
.KHR_bind_memory2 = true,
118
.KHR_create_renderpass2 = true,
119
.KHR_dedicated_allocation = true,
120
.KHR_depth_stencil_resolve = true,
121
.KHR_descriptor_update_template = true,
122
.KHR_device_group = true,
123
.KHR_draw_indirect_count = true,
124
.KHR_external_fence = true,
125
.KHR_external_fence_fd = true,
126
.KHR_external_memory = true,
127
.KHR_external_memory_fd = true,
128
.KHR_external_semaphore = true,
129
.KHR_external_semaphore_fd = true,
130
.KHR_get_memory_requirements2 = true,
131
.KHR_incremental_present = TU_HAS_SURFACE,
132
.KHR_image_format_list = true,
133
.KHR_maintenance1 = true,
134
.KHR_maintenance2 = true,
135
.KHR_maintenance3 = true,
136
.KHR_multiview = true,
137
.KHR_performance_query = device->instance->debug_flags & TU_DEBUG_PERFC,
138
.KHR_pipeline_executable_properties = true,
139
.KHR_push_descriptor = true,
140
.KHR_relaxed_block_layout = true,
141
.KHR_sampler_mirror_clamp_to_edge = true,
142
.KHR_sampler_ycbcr_conversion = true,
143
.KHR_shader_draw_parameters = true,
144
.KHR_shader_float_controls = true,
145
.KHR_shader_float16_int8 = true,
146
.KHR_shader_terminate_invocation = true,
147
.KHR_spirv_1_4 = true,
148
.KHR_storage_buffer_storage_class = true,
149
.KHR_swapchain = TU_HAS_SURFACE,
150
.KHR_variable_pointers = true,
151
.KHR_vulkan_memory_model = true,
152
#ifndef TU_USE_KGSL
153
.KHR_timeline_semaphore = true,
154
#endif
155
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
156
.EXT_display_control = true,
157
#endif
158
.EXT_external_memory_dma_buf = true,
159
.EXT_image_drm_format_modifier = true,
160
.EXT_sample_locations = device->info->a6xx.has_sample_locations,
161
.EXT_sampler_filter_minmax = true,
162
.EXT_transform_feedback = true,
163
.EXT_4444_formats = true,
164
.EXT_conditional_rendering = true,
165
.EXT_custom_border_color = true,
166
.EXT_depth_clip_enable = true,
167
.EXT_descriptor_indexing = true,
168
.EXT_extended_dynamic_state = true,
169
.EXT_filter_cubic = device->info->a6xx.has_tex_filter_cubic,
170
.EXT_host_query_reset = true,
171
.EXT_index_type_uint8 = true,
172
.EXT_memory_budget = true,
173
.EXT_private_data = true,
174
.EXT_robustness2 = true,
175
.EXT_scalar_block_layout = true,
176
.EXT_separate_stencil_usage = true,
177
.EXT_shader_demote_to_helper_invocation = true,
178
.EXT_shader_stencil_export = true,
179
.EXT_shader_viewport_index_layer = true,
180
.EXT_vertex_attribute_divisor = true,
181
.EXT_provoking_vertex = true,
182
#ifdef ANDROID
183
.ANDROID_native_buffer = true,
184
#endif
185
.IMG_filter_cubic = device->info->a6xx.has_tex_filter_cubic,
186
};
187
}
188
189
VkResult
190
tu_physical_device_init(struct tu_physical_device *device,
191
struct tu_instance *instance)
192
{
193
VkResult result = VK_SUCCESS;
194
195
device->name = fd_dev_name(device->gpu_id);
196
197
const struct fd_dev_info *info = fd_dev_info(device->gpu_id);
198
if (!info) {
199
result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
200
"device %s is unsupported", device->name);
201
return result;
202
}
203
switch (device->gpu_id / 100) {
204
case 6:
205
device->info = info;
206
device->ccu_offset_bypass = device->info->num_ccu * A6XX_CCU_DEPTH_SIZE;
207
device->ccu_offset_gmem = (device->gmem_size -
208
device->info->num_ccu * A6XX_CCU_GMEM_COLOR_SIZE);
209
break;
210
default:
211
result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
212
"device %s is unsupported", device->name);
213
return result;
214
}
215
if (tu_device_get_cache_uuid(device->gpu_id, device->cache_uuid)) {
216
result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
217
"cannot generate UUID");
218
return result;
219
}
220
221
/* The gpu id is already embedded in the uuid so we just pass "tu"
222
* when creating the cache.
223
*/
224
char buf[VK_UUID_SIZE * 2 + 1];
225
disk_cache_format_hex_id(buf, device->cache_uuid, VK_UUID_SIZE * 2);
226
device->disk_cache = disk_cache_create(device->name, buf, 0);
227
228
vk_warn_non_conformant_implementation("tu");
229
230
fd_get_driver_uuid(device->driver_uuid);
231
fd_get_device_uuid(device->device_uuid, device->gpu_id);
232
233
struct vk_device_extension_table supported_extensions;
234
get_device_extensions(device, &supported_extensions);
235
236
struct vk_physical_device_dispatch_table dispatch_table;
237
vk_physical_device_dispatch_table_from_entrypoints(
238
&dispatch_table, &tu_physical_device_entrypoints, true);
239
240
result = vk_physical_device_init(&device->vk, &instance->vk,
241
&supported_extensions,
242
&dispatch_table);
243
if (result != VK_SUCCESS)
244
return result;
245
246
#if TU_HAS_SURFACE
247
result = tu_wsi_init(device);
248
if (result != VK_SUCCESS) {
249
vk_startup_errorf(instance, result, "WSI init failure");
250
vk_physical_device_finish(&device->vk);
251
return result;
252
}
253
#endif
254
255
return VK_SUCCESS;
256
}
257
258
static void
259
tu_physical_device_finish(struct tu_physical_device *device)
260
{
261
#if TU_HAS_SURFACE
262
tu_wsi_finish(device);
263
#endif
264
265
disk_cache_destroy(device->disk_cache);
266
close(device->local_fd);
267
if (device->master_fd != -1)
268
close(device->master_fd);
269
270
vk_physical_device_finish(&device->vk);
271
}
272
273
static const struct debug_control tu_debug_options[] = {
274
{ "startup", TU_DEBUG_STARTUP },
275
{ "nir", TU_DEBUG_NIR },
276
{ "nobin", TU_DEBUG_NOBIN },
277
{ "sysmem", TU_DEBUG_SYSMEM },
278
{ "forcebin", TU_DEBUG_FORCEBIN },
279
{ "noubwc", TU_DEBUG_NOUBWC },
280
{ "nomultipos", TU_DEBUG_NOMULTIPOS },
281
{ "nolrz", TU_DEBUG_NOLRZ },
282
{ "perfc", TU_DEBUG_PERFC },
283
{ NULL, 0 }
284
};
285
286
const char *
287
tu_get_debug_option_name(int id)
288
{
289
assert(id < ARRAY_SIZE(tu_debug_options) - 1);
290
return tu_debug_options[id].string;
291
}
292
293
VKAPI_ATTR VkResult VKAPI_CALL
294
tu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
295
const VkAllocationCallbacks *pAllocator,
296
VkInstance *pInstance)
297
{
298
struct tu_instance *instance;
299
VkResult result;
300
301
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
302
303
if (pAllocator == NULL)
304
pAllocator = vk_default_allocator();
305
306
instance = vk_zalloc(pAllocator, sizeof(*instance), 8,
307
VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
308
309
if (!instance)
310
return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
311
312
struct vk_instance_dispatch_table dispatch_table;
313
vk_instance_dispatch_table_from_entrypoints(
314
&dispatch_table, &tu_instance_entrypoints, true);
315
316
result = vk_instance_init(&instance->vk,
317
&tu_instance_extensions_supported,
318
&dispatch_table,
319
pCreateInfo, pAllocator);
320
if (result != VK_SUCCESS) {
321
vk_free(pAllocator, instance);
322
return vk_error(NULL, result);
323
}
324
325
instance->physical_device_count = -1;
326
327
instance->debug_flags =
328
parse_debug_string(getenv("TU_DEBUG"), tu_debug_options);
329
330
#ifdef DEBUG
331
/* Enable startup debugging by default on debug drivers. You almost always
332
* want to see your startup failures in that case, and it's hard to set
333
* this env var on android.
334
*/
335
instance->debug_flags |= TU_DEBUG_STARTUP;
336
#endif
337
338
if (instance->debug_flags & TU_DEBUG_STARTUP)
339
mesa_logi("Created an instance");
340
341
VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
342
343
*pInstance = tu_instance_to_handle(instance);
344
345
return VK_SUCCESS;
346
}
347
348
VKAPI_ATTR void VKAPI_CALL
349
tu_DestroyInstance(VkInstance _instance,
350
const VkAllocationCallbacks *pAllocator)
351
{
352
TU_FROM_HANDLE(tu_instance, instance, _instance);
353
354
if (!instance)
355
return;
356
357
for (int i = 0; i < instance->physical_device_count; ++i) {
358
tu_physical_device_finish(instance->physical_devices + i);
359
}
360
361
VG(VALGRIND_DESTROY_MEMPOOL(instance));
362
363
vk_instance_finish(&instance->vk);
364
vk_free(&instance->vk.alloc, instance);
365
}
366
367
VKAPI_ATTR VkResult VKAPI_CALL
368
tu_EnumeratePhysicalDevices(VkInstance _instance,
369
uint32_t *pPhysicalDeviceCount,
370
VkPhysicalDevice *pPhysicalDevices)
371
{
372
TU_FROM_HANDLE(tu_instance, instance, _instance);
373
VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
374
375
VkResult result;
376
377
if (instance->physical_device_count < 0) {
378
result = tu_enumerate_devices(instance);
379
if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
380
return result;
381
}
382
383
for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
384
vk_outarray_append(&out, p)
385
{
386
*p = tu_physical_device_to_handle(instance->physical_devices + i);
387
}
388
}
389
390
return vk_outarray_status(&out);
391
}
392
393
VKAPI_ATTR VkResult VKAPI_CALL
394
tu_EnumeratePhysicalDeviceGroups(
395
VkInstance _instance,
396
uint32_t *pPhysicalDeviceGroupCount,
397
VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)
398
{
399
TU_FROM_HANDLE(tu_instance, instance, _instance);
400
VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
401
pPhysicalDeviceGroupCount);
402
VkResult result;
403
404
if (instance->physical_device_count < 0) {
405
result = tu_enumerate_devices(instance);
406
if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
407
return result;
408
}
409
410
for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
411
vk_outarray_append(&out, p)
412
{
413
p->physicalDeviceCount = 1;
414
p->physicalDevices[0] =
415
tu_physical_device_to_handle(instance->physical_devices + i);
416
p->subsetAllocation = false;
417
}
418
}
419
420
return vk_outarray_status(&out);
421
}
422
423
VKAPI_ATTR void VKAPI_CALL
424
tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
425
VkPhysicalDeviceFeatures2 *pFeatures)
426
{
427
TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
428
429
pFeatures->features = (VkPhysicalDeviceFeatures) {
430
.robustBufferAccess = true,
431
.fullDrawIndexUint32 = true,
432
.imageCubeArray = true,
433
.independentBlend = true,
434
.geometryShader = true,
435
.tessellationShader = true,
436
.sampleRateShading = true,
437
.dualSrcBlend = true,
438
.logicOp = true,
439
.multiDrawIndirect = true,
440
.drawIndirectFirstInstance = true,
441
.depthClamp = true,
442
.depthBiasClamp = true,
443
.fillModeNonSolid = true,
444
.depthBounds = true,
445
.wideLines = false,
446
.largePoints = true,
447
.alphaToOne = true,
448
.multiViewport = true,
449
.samplerAnisotropy = true,
450
.textureCompressionETC2 = true,
451
.textureCompressionASTC_LDR = true,
452
.textureCompressionBC = true,
453
.occlusionQueryPrecise = true,
454
.pipelineStatisticsQuery = true,
455
.vertexPipelineStoresAndAtomics = true,
456
.fragmentStoresAndAtomics = true,
457
.shaderTessellationAndGeometryPointSize = false,
458
.shaderImageGatherExtended = true,
459
.shaderStorageImageExtendedFormats = true,
460
.shaderStorageImageMultisample = false,
461
.shaderUniformBufferArrayDynamicIndexing = true,
462
.shaderSampledImageArrayDynamicIndexing = true,
463
.shaderStorageBufferArrayDynamicIndexing = true,
464
.shaderStorageImageArrayDynamicIndexing = true,
465
.shaderStorageImageReadWithoutFormat = true,
466
.shaderStorageImageWriteWithoutFormat = true,
467
.shaderClipDistance = true,
468
.shaderCullDistance = true,
469
.shaderFloat64 = false,
470
.shaderInt64 = false,
471
.shaderInt16 = true,
472
.sparseBinding = false,
473
.variableMultisampleRate = true,
474
.inheritedQueries = true,
475
};
476
477
vk_foreach_struct(ext, pFeatures->pNext)
478
{
479
switch (ext->sType) {
480
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: {
481
VkPhysicalDeviceVulkan11Features *features = (void *) ext;
482
features->storageBuffer16BitAccess = pdevice->info->a6xx.storage_16bit;
483
features->uniformAndStorageBuffer16BitAccess = false;
484
features->storagePushConstant16 = false;
485
features->storageInputOutput16 = false;
486
features->multiview = true;
487
features->multiviewGeometryShader = false;
488
features->multiviewTessellationShader = false;
489
features->variablePointersStorageBuffer = true;
490
features->variablePointers = true;
491
features->protectedMemory = false;
492
features->samplerYcbcrConversion = true;
493
features->shaderDrawParameters = true;
494
break;
495
}
496
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: {
497
VkPhysicalDeviceVulkan12Features *features = (void *) ext;
498
features->samplerMirrorClampToEdge = true;
499
features->drawIndirectCount = true;
500
features->storageBuffer8BitAccess = false;
501
features->uniformAndStorageBuffer8BitAccess = false;
502
features->storagePushConstant8 = false;
503
features->shaderBufferInt64Atomics = false;
504
features->shaderSharedInt64Atomics = false;
505
features->shaderFloat16 = true;
506
features->shaderInt8 = false;
507
508
features->descriptorIndexing = true;
509
features->shaderInputAttachmentArrayDynamicIndexing = false;
510
features->shaderUniformTexelBufferArrayDynamicIndexing = true;
511
features->shaderStorageTexelBufferArrayDynamicIndexing = true;
512
features->shaderUniformBufferArrayNonUniformIndexing = true;
513
features->shaderSampledImageArrayNonUniformIndexing = true;
514
features->shaderStorageBufferArrayNonUniformIndexing = true;
515
features->shaderStorageImageArrayNonUniformIndexing = true;
516
features->shaderInputAttachmentArrayNonUniformIndexing = false;
517
features->shaderUniformTexelBufferArrayNonUniformIndexing = true;
518
features->shaderStorageTexelBufferArrayNonUniformIndexing = true;
519
features->descriptorBindingUniformBufferUpdateAfterBind = false;
520
features->descriptorBindingSampledImageUpdateAfterBind = true;
521
features->descriptorBindingStorageImageUpdateAfterBind = true;
522
features->descriptorBindingStorageBufferUpdateAfterBind = true;
523
features->descriptorBindingUniformTexelBufferUpdateAfterBind = true;
524
features->descriptorBindingStorageTexelBufferUpdateAfterBind = true;
525
features->descriptorBindingUpdateUnusedWhilePending = true;
526
features->descriptorBindingPartiallyBound = true;
527
features->descriptorBindingVariableDescriptorCount = true;
528
features->runtimeDescriptorArray = true;
529
530
features->samplerFilterMinmax = true;
531
features->scalarBlockLayout = true;
532
features->imagelessFramebuffer = false;
533
features->uniformBufferStandardLayout = false;
534
features->shaderSubgroupExtendedTypes = false;
535
features->separateDepthStencilLayouts = false;
536
features->hostQueryReset = true;
537
features->timelineSemaphore = true;
538
features->bufferDeviceAddress = false;
539
features->bufferDeviceAddressCaptureReplay = false;
540
features->bufferDeviceAddressMultiDevice = false;
541
features->vulkanMemoryModel = true;
542
features->vulkanMemoryModelDeviceScope = true;
543
features->vulkanMemoryModelAvailabilityVisibilityChains = true;
544
features->shaderOutputViewportIndex = true;
545
features->shaderOutputLayer = true;
546
features->subgroupBroadcastDynamicId = false;
547
break;
548
}
549
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {
550
VkPhysicalDeviceVariablePointersFeatures *features = (void *) ext;
551
features->variablePointersStorageBuffer = true;
552
features->variablePointers = true;
553
break;
554
}
555
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
556
VkPhysicalDeviceMultiviewFeatures *features =
557
(VkPhysicalDeviceMultiviewFeatures *) ext;
558
features->multiview = true;
559
features->multiviewGeometryShader = false;
560
features->multiviewTessellationShader = false;
561
break;
562
}
563
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {
564
VkPhysicalDeviceShaderDrawParametersFeatures *features =
565
(VkPhysicalDeviceShaderDrawParametersFeatures *) ext;
566
features->shaderDrawParameters = true;
567
break;
568
}
569
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
570
VkPhysicalDeviceProtectedMemoryFeatures *features =
571
(VkPhysicalDeviceProtectedMemoryFeatures *) ext;
572
features->protectedMemory = false;
573
break;
574
}
575
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
576
VkPhysicalDevice16BitStorageFeatures *features =
577
(VkPhysicalDevice16BitStorageFeatures *) ext;
578
features->storageBuffer16BitAccess = pdevice->info->a6xx.storage_16bit;
579
features->uniformAndStorageBuffer16BitAccess = false;
580
features->storagePushConstant16 = false;
581
features->storageInputOutput16 = false;
582
break;
583
}
584
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
585
VkPhysicalDeviceSamplerYcbcrConversionFeatures *features =
586
(VkPhysicalDeviceSamplerYcbcrConversionFeatures *) ext;
587
features->samplerYcbcrConversion = true;
588
break;
589
}
590
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: {
591
VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features =
592
(VkPhysicalDeviceDescriptorIndexingFeaturesEXT *) ext;
593
features->shaderInputAttachmentArrayDynamicIndexing = false;
594
features->shaderUniformTexelBufferArrayDynamicIndexing = true;
595
features->shaderStorageTexelBufferArrayDynamicIndexing = true;
596
features->shaderUniformBufferArrayNonUniformIndexing = true;
597
features->shaderSampledImageArrayNonUniformIndexing = true;
598
features->shaderStorageBufferArrayNonUniformIndexing = true;
599
features->shaderStorageImageArrayNonUniformIndexing = true;
600
features->shaderInputAttachmentArrayNonUniformIndexing = false;
601
features->shaderUniformTexelBufferArrayNonUniformIndexing = true;
602
features->shaderStorageTexelBufferArrayNonUniformIndexing = true;
603
features->descriptorBindingUniformBufferUpdateAfterBind = false;
604
features->descriptorBindingSampledImageUpdateAfterBind = true;
605
features->descriptorBindingStorageImageUpdateAfterBind = true;
606
features->descriptorBindingStorageBufferUpdateAfterBind = true;
607
features->descriptorBindingUniformTexelBufferUpdateAfterBind = true;
608
features->descriptorBindingStorageTexelBufferUpdateAfterBind = true;
609
features->descriptorBindingUpdateUnusedWhilePending = true;
610
features->descriptorBindingPartiallyBound = true;
611
features->descriptorBindingVariableDescriptorCount = true;
612
features->runtimeDescriptorArray = true;
613
break;
614
}
615
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
616
VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
617
(VkPhysicalDeviceConditionalRenderingFeaturesEXT *) ext;
618
features->conditionalRendering = true;
619
features->inheritedConditionalRendering = true;
620
break;
621
}
622
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
623
VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =
624
(VkPhysicalDeviceTransformFeedbackFeaturesEXT *) ext;
625
features->transformFeedback = true;
626
features->geometryStreams = true;
627
break;
628
}
629
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
630
VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =
631
(VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;
632
features->indexTypeUint8 = true;
633
break;
634
}
635
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
636
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
637
(VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;
638
features->vertexAttributeInstanceRateDivisor = true;
639
features->vertexAttributeInstanceRateZeroDivisor = true;
640
break;
641
}
642
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
643
VkPhysicalDevicePrivateDataFeaturesEXT *features =
644
(VkPhysicalDevicePrivateDataFeaturesEXT *)ext;
645
features->privateData = true;
646
break;
647
}
648
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
649
VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =
650
(VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;
651
features->depthClipEnable = true;
652
break;
653
}
654
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
655
VkPhysicalDevice4444FormatsFeaturesEXT *features = (void *)ext;
656
features->formatA4R4G4B4 = true;
657
features->formatA4B4G4R4 = true;
658
break;
659
}
660
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
661
VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = (void *) ext;
662
features->customBorderColors = true;
663
features->customBorderColorWithoutFormat = true;
664
break;
665
}
666
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: {
667
VkPhysicalDeviceHostQueryResetFeaturesEXT *features =
668
(VkPhysicalDeviceHostQueryResetFeaturesEXT *)ext;
669
features->hostQueryReset = true;
670
break;
671
}
672
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: {
673
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *features = (void *)ext;
674
features->extendedDynamicState = true;
675
break;
676
}
677
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
678
VkPhysicalDevicePerformanceQueryFeaturesKHR *feature =
679
(VkPhysicalDevicePerformanceQueryFeaturesKHR *)ext;
680
feature->performanceCounterQueryPools = true;
681
feature->performanceCounterMultipleQueryPools = false;
682
break;
683
}
684
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: {
685
VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *features =
686
(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *)ext;
687
features->pipelineExecutableInfo = true;
688
break;
689
}
690
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES: {
691
VkPhysicalDeviceShaderFloat16Int8Features *features =
692
(VkPhysicalDeviceShaderFloat16Int8Features *) ext;
693
features->shaderFloat16 = true;
694
features->shaderInt8 = false;
695
break;
696
}
697
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {
698
VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *features = (void *)ext;
699
features->scalarBlockLayout = true;
700
break;
701
}
702
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: {
703
VkPhysicalDeviceRobustness2FeaturesEXT *features = (void *)ext;
704
features->robustBufferAccess2 = true;
705
features->robustImageAccess2 = true;
706
features->nullDescriptor = true;
707
break;
708
}
709
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT: {
710
VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *features =
711
(VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *)ext;
712
features->shaderDemoteToHelperInvocation = true;
713
break;
714
}
715
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR: {
716
VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR *features =
717
(VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR *)ext;
718
features->shaderTerminateInvocation = true;
719
break;
720
}
721
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_MEMORY_MODEL_FEATURES_KHR: {
722
VkPhysicalDeviceVulkanMemoryModelFeaturesKHR *feature =
723
(VkPhysicalDeviceVulkanMemoryModelFeaturesKHR *)ext;
724
feature->vulkanMemoryModel = true;
725
feature->vulkanMemoryModelDeviceScope = true;
726
feature->vulkanMemoryModelAvailabilityVisibilityChains = true;
727
break;
728
}
729
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES: {
730
VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *features =
731
(VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *) ext;
732
features->timelineSemaphore = true;
733
break;
734
}
735
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: {
736
VkPhysicalDeviceProvokingVertexFeaturesEXT *features =
737
(VkPhysicalDeviceProvokingVertexFeaturesEXT *)ext;
738
features->provokingVertexLast = true;
739
features->transformFeedbackPreservesProvokingVertex = true;
740
break;
741
}
742
743
default:
744
break;
745
}
746
}
747
}
748
749
VKAPI_ATTR void VKAPI_CALL
750
tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
751
VkPhysicalDeviceProperties2 *pProperties)
752
{
753
TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
754
VkSampleCountFlags sample_counts =
755
VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
756
757
/* I have no idea what the maximum size is, but the hardware supports very
758
* large numbers of descriptors (at least 2^16). This limit is based on
759
* CP_LOAD_STATE6, which has a 28-bit field for the DWORD offset, so that
760
* we don't have to think about what to do if that overflows, but really
761
* nothing is likely to get close to this.
762
*/
763
const size_t max_descriptor_set_size = (1 << 28) / A6XX_TEX_CONST_DWORDS;
764
765
VkPhysicalDeviceLimits limits = {
766
.maxImageDimension1D = (1 << 14),
767
.maxImageDimension2D = (1 << 14),
768
.maxImageDimension3D = (1 << 11),
769
.maxImageDimensionCube = (1 << 14),
770
.maxImageArrayLayers = (1 << 11),
771
.maxTexelBufferElements = 128 * 1024 * 1024,
772
.maxUniformBufferRange = MAX_UNIFORM_BUFFER_RANGE,
773
.maxStorageBufferRange = MAX_STORAGE_BUFFER_RANGE,
774
.maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
775
.maxMemoryAllocationCount = UINT32_MAX,
776
.maxSamplerAllocationCount = 64 * 1024,
777
.bufferImageGranularity = 64, /* A cache line */
778
.sparseAddressSpaceSize = 0,
779
.maxBoundDescriptorSets = MAX_SETS,
780
.maxPerStageDescriptorSamplers = max_descriptor_set_size,
781
.maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
782
.maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
783
.maxPerStageDescriptorSampledImages = max_descriptor_set_size,
784
.maxPerStageDescriptorStorageImages = max_descriptor_set_size,
785
.maxPerStageDescriptorInputAttachments = MAX_RTS,
786
.maxPerStageResources = max_descriptor_set_size,
787
.maxDescriptorSetSamplers = max_descriptor_set_size,
788
.maxDescriptorSetUniformBuffers = max_descriptor_set_size,
789
.maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
790
.maxDescriptorSetStorageBuffers = max_descriptor_set_size,
791
.maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
792
.maxDescriptorSetSampledImages = max_descriptor_set_size,
793
.maxDescriptorSetStorageImages = max_descriptor_set_size,
794
.maxDescriptorSetInputAttachments = MAX_RTS,
795
.maxVertexInputAttributes = 32,
796
.maxVertexInputBindings = 32,
797
.maxVertexInputAttributeOffset = 4095,
798
.maxVertexInputBindingStride = 2048,
799
.maxVertexOutputComponents = 128,
800
.maxTessellationGenerationLevel = 64,
801
.maxTessellationPatchSize = 32,
802
.maxTessellationControlPerVertexInputComponents = 128,
803
.maxTessellationControlPerVertexOutputComponents = 128,
804
.maxTessellationControlPerPatchOutputComponents = 120,
805
.maxTessellationControlTotalOutputComponents = 4096,
806
.maxTessellationEvaluationInputComponents = 128,
807
.maxTessellationEvaluationOutputComponents = 128,
808
.maxGeometryShaderInvocations = 32,
809
.maxGeometryInputComponents = 64,
810
.maxGeometryOutputComponents = 128,
811
.maxGeometryOutputVertices = 256,
812
.maxGeometryTotalOutputComponents = 1024,
813
.maxFragmentInputComponents = 124,
814
.maxFragmentOutputAttachments = 8,
815
.maxFragmentDualSrcAttachments = 1,
816
.maxFragmentCombinedOutputResources = 8,
817
.maxComputeSharedMemorySize = 32768,
818
.maxComputeWorkGroupCount = { 65535, 65535, 65535 },
819
.maxComputeWorkGroupInvocations = 2048,
820
.maxComputeWorkGroupSize = { 2048, 2048, 2048 },
821
.subPixelPrecisionBits = 8,
822
.subTexelPrecisionBits = 8,
823
.mipmapPrecisionBits = 8,
824
.maxDrawIndexedIndexValue = UINT32_MAX,
825
.maxDrawIndirectCount = UINT32_MAX,
826
.maxSamplerLodBias = 4095.0 / 256.0, /* [-16, 15.99609375] */
827
.maxSamplerAnisotropy = 16,
828
.maxViewports = MAX_VIEWPORTS,
829
.maxViewportDimensions = { (1 << 14), (1 << 14) },
830
.viewportBoundsRange = { INT16_MIN, INT16_MAX },
831
.viewportSubPixelBits = 8,
832
.minMemoryMapAlignment = 4096, /* A page */
833
.minTexelBufferOffsetAlignment = 64,
834
.minUniformBufferOffsetAlignment = 64,
835
.minStorageBufferOffsetAlignment = 64,
836
.minTexelOffset = -16,
837
.maxTexelOffset = 15,
838
.minTexelGatherOffset = -32,
839
.maxTexelGatherOffset = 31,
840
.minInterpolationOffset = -0.5,
841
.maxInterpolationOffset = 0.4375,
842
.subPixelInterpolationOffsetBits = 4,
843
.maxFramebufferWidth = (1 << 14),
844
.maxFramebufferHeight = (1 << 14),
845
.maxFramebufferLayers = (1 << 10),
846
.framebufferColorSampleCounts = sample_counts,
847
.framebufferDepthSampleCounts = sample_counts,
848
.framebufferStencilSampleCounts = sample_counts,
849
.framebufferNoAttachmentsSampleCounts = sample_counts,
850
.maxColorAttachments = MAX_RTS,
851
.sampledImageColorSampleCounts = sample_counts,
852
.sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
853
.sampledImageDepthSampleCounts = sample_counts,
854
.sampledImageStencilSampleCounts = sample_counts,
855
.storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
856
.maxSampleMaskWords = 1,
857
.timestampComputeAndGraphics = true,
858
.timestampPeriod = 1000000000.0 / 19200000.0, /* CP_ALWAYS_ON_COUNTER is fixed 19.2MHz */
859
.maxClipDistances = 8,
860
.maxCullDistances = 8,
861
.maxCombinedClipAndCullDistances = 8,
862
.discreteQueuePriorities = 2,
863
.pointSizeRange = { 1, 4092 },
864
.lineWidthRange = { 1.0, 1.0 },
865
.pointSizeGranularity = 0.0625,
866
.lineWidthGranularity = 0.0,
867
.strictLines = false, /* FINISHME */
868
.standardSampleLocations = true,
869
.optimalBufferCopyOffsetAlignment = 128,
870
.optimalBufferCopyRowPitchAlignment = 128,
871
.nonCoherentAtomSize = 64,
872
};
873
874
pProperties->properties = (VkPhysicalDeviceProperties) {
875
.apiVersion = TU_API_VERSION,
876
.driverVersion = vk_get_driver_version(),
877
.vendorID = 0, /* TODO */
878
.deviceID = 0,
879
.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
880
.limits = limits,
881
.sparseProperties = { 0 },
882
};
883
884
strcpy(pProperties->properties.deviceName, pdevice->name);
885
memcpy(pProperties->properties.pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
886
887
vk_foreach_struct(ext, pProperties->pNext)
888
{
889
switch (ext->sType) {
890
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
891
VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
892
(VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
893
properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
894
break;
895
}
896
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
897
VkPhysicalDeviceIDProperties *properties =
898
(VkPhysicalDeviceIDProperties *) ext;
899
memcpy(properties->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
900
memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
901
properties->deviceLUIDValid = false;
902
break;
903
}
904
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {
905
VkPhysicalDeviceMultiviewProperties *properties =
906
(VkPhysicalDeviceMultiviewProperties *) ext;
907
properties->maxMultiviewViewCount = MAX_VIEWS;
908
properties->maxMultiviewInstanceIndex = INT_MAX;
909
break;
910
}
911
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
912
VkPhysicalDevicePointClippingProperties *properties =
913
(VkPhysicalDevicePointClippingProperties *) ext;
914
properties->pointClippingBehavior =
915
VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
916
break;
917
}
918
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
919
VkPhysicalDeviceMaintenance3Properties *properties =
920
(VkPhysicalDeviceMaintenance3Properties *) ext;
921
/* Make sure everything is addressable by a signed 32-bit int, and
922
* our largest descriptors are 96 bytes. */
923
properties->maxPerSetDescriptors = (1ull << 31) / 96;
924
/* Our buffer size fields allow only this much */
925
properties->maxMemoryAllocationSize = 0xFFFFFFFFull;
926
break;
927
}
928
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: {
929
VkPhysicalDeviceTransformFeedbackPropertiesEXT *properties =
930
(VkPhysicalDeviceTransformFeedbackPropertiesEXT *)ext;
931
932
properties->maxTransformFeedbackStreams = IR3_MAX_SO_STREAMS;
933
properties->maxTransformFeedbackBuffers = IR3_MAX_SO_BUFFERS;
934
properties->maxTransformFeedbackBufferSize = UINT32_MAX;
935
properties->maxTransformFeedbackStreamDataSize = 512;
936
properties->maxTransformFeedbackBufferDataSize = 512;
937
properties->maxTransformFeedbackBufferDataStride = 512;
938
properties->transformFeedbackQueries = true;
939
properties->transformFeedbackStreamsLinesTriangles = true;
940
properties->transformFeedbackRasterizationStreamSelect = true;
941
properties->transformFeedbackDraw = true;
942
break;
943
}
944
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: {
945
VkPhysicalDeviceSampleLocationsPropertiesEXT *properties =
946
(VkPhysicalDeviceSampleLocationsPropertiesEXT *)ext;
947
properties->sampleLocationSampleCounts = 0;
948
if (pdevice->vk.supported_extensions.EXT_sample_locations) {
949
properties->sampleLocationSampleCounts =
950
VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
951
}
952
properties->maxSampleLocationGridSize = (VkExtent2D) { 1 , 1 };
953
properties->sampleLocationCoordinateRange[0] = 0.0f;
954
properties->sampleLocationCoordinateRange[1] = 0.9375f;
955
properties->sampleLocationSubPixelBits = 4;
956
properties->variableSampleLocations = true;
957
break;
958
}
959
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES: {
960
VkPhysicalDeviceSamplerFilterMinmaxProperties *properties =
961
(VkPhysicalDeviceSamplerFilterMinmaxProperties *)ext;
962
properties->filterMinmaxImageComponentMapping = true;
963
properties->filterMinmaxSingleComponentFormats = true;
964
break;
965
}
966
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: {
967
VkPhysicalDeviceSubgroupProperties *properties =
968
(VkPhysicalDeviceSubgroupProperties *)ext;
969
properties->subgroupSize = 128;
970
properties->supportedStages = VK_SHADER_STAGE_COMPUTE_BIT;
971
properties->supportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT |
972
VK_SUBGROUP_FEATURE_VOTE_BIT |
973
VK_SUBGROUP_FEATURE_BALLOT_BIT;
974
properties->quadOperationsInAllStages = false;
975
break;
976
}
977
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
978
VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props =
979
(VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
980
props->maxVertexAttribDivisor = UINT32_MAX;
981
break;
982
}
983
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: {
984
VkPhysicalDeviceCustomBorderColorPropertiesEXT *props = (void *)ext;
985
props->maxCustomBorderColorSamplers = TU_BORDER_COLOR_COUNT;
986
break;
987
}
988
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES: {
989
VkPhysicalDeviceDepthStencilResolveProperties *props =
990
(VkPhysicalDeviceDepthStencilResolveProperties *)ext;
991
props->independentResolve = false;
992
props->independentResolveNone = false;
993
props->supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
994
props->supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
995
break;
996
}
997
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR: {
998
VkPhysicalDevicePerformanceQueryPropertiesKHR *properties =
999
(VkPhysicalDevicePerformanceQueryPropertiesKHR *)ext;
1000
properties->allowCommandBufferQueryCopies = false;
1001
break;
1002
}
1003
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT: {
1004
VkPhysicalDeviceDescriptorIndexingPropertiesEXT *props =
1005
(VkPhysicalDeviceDescriptorIndexingPropertiesEXT *)ext;
1006
props->shaderUniformBufferArrayNonUniformIndexingNative = true;
1007
props->shaderSampledImageArrayNonUniformIndexingNative = true;
1008
props->shaderStorageBufferArrayNonUniformIndexingNative = true;
1009
props->shaderStorageImageArrayNonUniformIndexingNative = true;
1010
props->shaderInputAttachmentArrayNonUniformIndexingNative = false;
1011
props->robustBufferAccessUpdateAfterBind = false;
1012
props->quadDivergentImplicitLod = false;
1013
1014
props->maxUpdateAfterBindDescriptorsInAllPools = max_descriptor_set_size;
1015
props->maxPerStageDescriptorUpdateAfterBindSamplers = max_descriptor_set_size;
1016
props->maxPerStageDescriptorUpdateAfterBindUniformBuffers = max_descriptor_set_size;
1017
props->maxPerStageDescriptorUpdateAfterBindStorageBuffers = max_descriptor_set_size;
1018
props->maxPerStageDescriptorUpdateAfterBindSampledImages = max_descriptor_set_size;
1019
props->maxPerStageDescriptorUpdateAfterBindStorageImages = max_descriptor_set_size;
1020
props->maxPerStageDescriptorUpdateAfterBindInputAttachments = max_descriptor_set_size;
1021
props->maxPerStageUpdateAfterBindResources = max_descriptor_set_size;
1022
props->maxDescriptorSetUpdateAfterBindSamplers = max_descriptor_set_size;
1023
props->maxDescriptorSetUpdateAfterBindUniformBuffers = max_descriptor_set_size;
1024
props->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = MAX_DYNAMIC_BUFFERS / 2;
1025
props->maxDescriptorSetUpdateAfterBindStorageBuffers = max_descriptor_set_size;
1026
props->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = MAX_DYNAMIC_BUFFERS / 2;
1027
props->maxDescriptorSetUpdateAfterBindSampledImages = max_descriptor_set_size;
1028
props->maxDescriptorSetUpdateAfterBindStorageImages = max_descriptor_set_size;
1029
props->maxDescriptorSetUpdateAfterBindInputAttachments = max_descriptor_set_size;
1030
break;
1031
}
1032
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES: {
1033
VkPhysicalDeviceFloatControlsProperties *properties =
1034
(VkPhysicalDeviceFloatControlsProperties *) ext;
1035
properties->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
1036
properties->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
1037
properties->shaderSignedZeroInfNanPreserveFloat16 = true;
1038
properties->shaderSignedZeroInfNanPreserveFloat32 = true;
1039
properties->shaderSignedZeroInfNanPreserveFloat64 = false;
1040
properties->shaderDenormPreserveFloat16 = false;
1041
properties->shaderDenormPreserveFloat32 = false;
1042
properties->shaderDenormPreserveFloat64 = false;
1043
properties->shaderDenormFlushToZeroFloat16 = true;
1044
properties->shaderDenormFlushToZeroFloat32 = true;
1045
properties->shaderDenormFlushToZeroFloat64 = false;
1046
properties->shaderRoundingModeRTEFloat16 = true;
1047
properties->shaderRoundingModeRTEFloat32 = true;
1048
properties->shaderRoundingModeRTEFloat64 = false;
1049
properties->shaderRoundingModeRTZFloat16 = false;
1050
properties->shaderRoundingModeRTZFloat32 = false;
1051
properties->shaderRoundingModeRTZFloat64 = false;
1052
break;
1053
}
1054
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT: {
1055
VkPhysicalDeviceRobustness2PropertiesEXT *props = (void *)ext;
1056
/* see write_buffer_descriptor() */
1057
props->robustStorageBufferAccessSizeAlignment = 4;
1058
/* see write_ubo_descriptor() */
1059
props->robustUniformBufferAccessSizeAlignment = 16;
1060
break;
1061
}
1062
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES: {
1063
VkPhysicalDeviceTimelineSemaphorePropertiesKHR *props =
1064
(VkPhysicalDeviceTimelineSemaphorePropertiesKHR *) ext;
1065
props->maxTimelineSemaphoreValueDifference = UINT64_MAX;
1066
break;
1067
}
1068
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: {
1069
VkPhysicalDeviceProvokingVertexPropertiesEXT *properties =
1070
(VkPhysicalDeviceProvokingVertexPropertiesEXT *)ext;
1071
properties->provokingVertexModePerPipeline = true;
1072
properties->transformFeedbackPreservesTriangleFanProvokingVertex = false;
1073
break;
1074
}
1075
default:
1076
break;
1077
}
1078
}
1079
}
1080
1081
static const VkQueueFamilyProperties tu_queue_family_properties = {
1082
.queueFlags =
1083
VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
1084
.queueCount = 1,
1085
.timestampValidBits = 48,
1086
.minImageTransferGranularity = { 1, 1, 1 },
1087
};
1088
1089
VKAPI_ATTR void VKAPI_CALL
1090
tu_GetPhysicalDeviceQueueFamilyProperties2(
1091
VkPhysicalDevice physicalDevice,
1092
uint32_t *pQueueFamilyPropertyCount,
1093
VkQueueFamilyProperties2 *pQueueFamilyProperties)
1094
{
1095
VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
1096
1097
vk_outarray_append(&out, p)
1098
{
1099
p->queueFamilyProperties = tu_queue_family_properties;
1100
}
1101
}
1102
1103
uint64_t
1104
tu_get_system_heap_size()
1105
{
1106
struct sysinfo info;
1107
sysinfo(&info);
1108
1109
uint64_t total_ram = (uint64_t) info.totalram * (uint64_t) info.mem_unit;
1110
1111
/* We don't want to burn too much ram with the GPU. If the user has 4GiB
1112
* or less, we use at most half. If they have more than 4GiB, we use 3/4.
1113
*/
1114
uint64_t available_ram;
1115
if (total_ram <= 4ull * 1024ull * 1024ull * 1024ull)
1116
available_ram = total_ram / 2;
1117
else
1118
available_ram = total_ram * 3 / 4;
1119
1120
return available_ram;
1121
}
1122
1123
static VkDeviceSize
1124
tu_get_budget_memory(struct tu_physical_device *physical_device)
1125
{
1126
uint64_t heap_size = physical_device->heap.size;
1127
uint64_t heap_used = physical_device->heap.used;
1128
uint64_t sys_available;
1129
ASSERTED bool has_available_memory =
1130
os_get_available_system_memory(&sys_available);
1131
assert(has_available_memory);
1132
1133
/*
1134
* Let's not incite the app to starve the system: report at most 90% of
1135
* available system memory.
1136
*/
1137
uint64_t heap_available = sys_available * 9 / 10;
1138
return MIN2(heap_size, heap_used + heap_available);
1139
}
1140
1141
VKAPI_ATTR void VKAPI_CALL
1142
tu_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice pdev,
1143
VkPhysicalDeviceMemoryProperties2 *props2)
1144
{
1145
TU_FROM_HANDLE(tu_physical_device, physical_device, pdev);
1146
1147
VkPhysicalDeviceMemoryProperties *props = &props2->memoryProperties;
1148
props->memoryHeapCount = 1;
1149
props->memoryHeaps[0].size = physical_device->heap.size;
1150
props->memoryHeaps[0].flags = physical_device->heap.flags;
1151
1152
props->memoryTypeCount = 1;
1153
props->memoryTypes[0].propertyFlags =
1154
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
1155
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1156
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
1157
props->memoryTypes[0].heapIndex = 0;
1158
1159
vk_foreach_struct(ext, props2->pNext)
1160
{
1161
switch (ext->sType) {
1162
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
1163
VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget_props =
1164
(VkPhysicalDeviceMemoryBudgetPropertiesEXT *) ext;
1165
memory_budget_props->heapUsage[0] = physical_device->heap.used;
1166
memory_budget_props->heapBudget[0] = tu_get_budget_memory(physical_device);
1167
1168
/* The heapBudget and heapUsage values must be zero for array elements
1169
* greater than or equal to VkPhysicalDeviceMemoryProperties::memoryHeapCount
1170
*/
1171
for (unsigned i = 1; i < VK_MAX_MEMORY_HEAPS; i++) {
1172
memory_budget_props->heapBudget[i] = 0u;
1173
memory_budget_props->heapUsage[i] = 0u;
1174
}
1175
break;
1176
}
1177
default:
1178
break;
1179
}
1180
}
1181
}
1182
1183
static VkResult
1184
tu_queue_init(struct tu_device *device,
1185
struct tu_queue *queue,
1186
uint32_t queue_family_index,
1187
int idx,
1188
VkDeviceQueueCreateFlags flags)
1189
{
1190
vk_object_base_init(&device->vk, &queue->base, VK_OBJECT_TYPE_QUEUE);
1191
1192
queue->device = device;
1193
queue->queue_family_index = queue_family_index;
1194
queue->queue_idx = idx;
1195
queue->flags = flags;
1196
1197
list_inithead(&queue->queued_submits);
1198
1199
int ret = tu_drm_submitqueue_new(device, 0, &queue->msm_queue_id);
1200
if (ret)
1201
return vk_startup_errorf(device->instance, VK_ERROR_INITIALIZATION_FAILED,
1202
"submitqueue create failed");
1203
1204
queue->fence = -1;
1205
1206
return VK_SUCCESS;
1207
}
1208
1209
static void
1210
tu_queue_finish(struct tu_queue *queue)
1211
{
1212
vk_object_base_finish(&queue->base);
1213
if (queue->fence >= 0)
1214
close(queue->fence);
1215
tu_drm_submitqueue_close(queue->device, queue->msm_queue_id);
1216
}
1217
1218
VKAPI_ATTR VkResult VKAPI_CALL
1219
tu_CreateDevice(VkPhysicalDevice physicalDevice,
1220
const VkDeviceCreateInfo *pCreateInfo,
1221
const VkAllocationCallbacks *pAllocator,
1222
VkDevice *pDevice)
1223
{
1224
TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
1225
VkResult result;
1226
struct tu_device *device;
1227
bool custom_border_colors = false;
1228
bool perf_query_pools = false;
1229
bool robust_buffer_access2 = false;
1230
1231
/* Check enabled features */
1232
if (pCreateInfo->pEnabledFeatures) {
1233
VkPhysicalDeviceFeatures2 supported_features = {
1234
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,
1235
};
1236
tu_GetPhysicalDeviceFeatures2(physicalDevice, &supported_features);
1237
VkBool32 *supported_feature = (VkBool32 *) &supported_features.features;
1238
VkBool32 *enabled_feature = (VkBool32 *) pCreateInfo->pEnabledFeatures;
1239
unsigned num_features =
1240
sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
1241
for (uint32_t i = 0; i < num_features; i++) {
1242
if (enabled_feature[i] && !supported_feature[i])
1243
return vk_startup_errorf(physical_device->instance,
1244
VK_ERROR_FEATURE_NOT_PRESENT,
1245
"Missing feature bit %d\n", i);
1246
}
1247
}
1248
1249
vk_foreach_struct_const(ext, pCreateInfo->pNext) {
1250
switch (ext->sType) {
1251
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
1252
const VkPhysicalDeviceCustomBorderColorFeaturesEXT *border_color_features = (const void *)ext;
1253
custom_border_colors = border_color_features->customBorderColors;
1254
break;
1255
}
1256
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
1257
const VkPhysicalDevicePerformanceQueryFeaturesKHR *feature =
1258
(VkPhysicalDevicePerformanceQueryFeaturesKHR *)ext;
1259
perf_query_pools = feature->performanceCounterQueryPools;
1260
break;
1261
}
1262
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: {
1263
VkPhysicalDeviceRobustness2FeaturesEXT *features = (void *)ext;
1264
robust_buffer_access2 = features->robustBufferAccess2;
1265
break;
1266
}
1267
default:
1268
break;
1269
}
1270
}
1271
1272
device = vk_zalloc2(&physical_device->instance->vk.alloc, pAllocator,
1273
sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1274
if (!device)
1275
return vk_startup_errorf(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");
1276
1277
struct vk_device_dispatch_table dispatch_table;
1278
vk_device_dispatch_table_from_entrypoints(
1279
&dispatch_table, &tu_device_entrypoints, true);
1280
1281
result = vk_device_init(&device->vk, &physical_device->vk,
1282
&dispatch_table, pCreateInfo, pAllocator);
1283
if (result != VK_SUCCESS) {
1284
vk_free(&device->vk.alloc, device);
1285
return vk_startup_errorf(physical_device->instance, result,
1286
"vk_device_init failed");
1287
}
1288
1289
device->instance = physical_device->instance;
1290
device->physical_device = physical_device;
1291
device->fd = physical_device->local_fd;
1292
device->_lost = false;
1293
1294
mtx_init(&device->bo_mutex, mtx_plain);
1295
pthread_mutex_init(&device->submit_mutex, NULL);
1296
1297
for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
1298
const VkDeviceQueueCreateInfo *queue_create =
1299
&pCreateInfo->pQueueCreateInfos[i];
1300
uint32_t qfi = queue_create->queueFamilyIndex;
1301
device->queues[qfi] = vk_alloc(
1302
&device->vk.alloc, queue_create->queueCount * sizeof(struct tu_queue),
1303
8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1304
if (!device->queues[qfi]) {
1305
result = vk_startup_errorf(physical_device->instance,
1306
VK_ERROR_OUT_OF_HOST_MEMORY,
1307
"OOM");
1308
goto fail_queues;
1309
}
1310
1311
memset(device->queues[qfi], 0,
1312
queue_create->queueCount * sizeof(struct tu_queue));
1313
1314
device->queue_count[qfi] = queue_create->queueCount;
1315
1316
for (unsigned q = 0; q < queue_create->queueCount; q++) {
1317
result = tu_queue_init(device, &device->queues[qfi][q], qfi, q,
1318
queue_create->flags);
1319
if (result != VK_SUCCESS)
1320
goto fail_queues;
1321
}
1322
}
1323
1324
device->compiler = ir3_compiler_create(NULL, physical_device->gpu_id,
1325
robust_buffer_access2);
1326
if (!device->compiler) {
1327
result = vk_startup_errorf(physical_device->instance,
1328
VK_ERROR_INITIALIZATION_FAILED,
1329
"failed to initialize ir3 compiler");
1330
goto fail_queues;
1331
}
1332
1333
/* initial sizes, these will increase if there is overflow */
1334
device->vsc_draw_strm_pitch = 0x1000 + VSC_PAD;
1335
device->vsc_prim_strm_pitch = 0x4000 + VSC_PAD;
1336
1337
uint32_t global_size = sizeof(struct tu6_global);
1338
if (custom_border_colors)
1339
global_size += TU_BORDER_COLOR_COUNT * sizeof(struct bcolor_entry);
1340
1341
result = tu_bo_init_new(device, &device->global_bo, global_size,
1342
TU_BO_ALLOC_NO_FLAGS);
1343
if (result != VK_SUCCESS) {
1344
vk_startup_errorf(device->instance, result, "BO init");
1345
goto fail_global_bo;
1346
}
1347
1348
result = tu_bo_map(device, &device->global_bo);
1349
if (result != VK_SUCCESS) {
1350
vk_startup_errorf(device->instance, result, "BO map");
1351
goto fail_global_bo_map;
1352
}
1353
1354
struct tu6_global *global = device->global_bo.map;
1355
tu_init_clear_blit_shaders(device->global_bo.map);
1356
global->predicate = 0;
1357
tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK],
1358
&(VkClearColorValue) {}, false);
1359
tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_TRANSPARENT_BLACK],
1360
&(VkClearColorValue) {}, true);
1361
tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK],
1362
&(VkClearColorValue) { .float32[3] = 1.0f }, false);
1363
tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_OPAQUE_BLACK],
1364
&(VkClearColorValue) { .int32[3] = 1 }, true);
1365
tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE],
1366
&(VkClearColorValue) { .float32[0 ... 3] = 1.0f }, false);
1367
tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_OPAQUE_WHITE],
1368
&(VkClearColorValue) { .int32[0 ... 3] = 1 }, true);
1369
1370
/* initialize to ones so ffs can be used to find unused slots */
1371
BITSET_ONES(device->custom_border_color);
1372
1373
VkPipelineCacheCreateInfo ci;
1374
ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1375
ci.pNext = NULL;
1376
ci.flags = 0;
1377
ci.pInitialData = NULL;
1378
ci.initialDataSize = 0;
1379
VkPipelineCache pc;
1380
result =
1381
tu_CreatePipelineCache(tu_device_to_handle(device), &ci, NULL, &pc);
1382
if (result != VK_SUCCESS) {
1383
vk_startup_errorf(device->instance, result, "create pipeline cache failed");
1384
goto fail_pipeline_cache;
1385
}
1386
1387
if (perf_query_pools) {
1388
/* Prepare command streams setting pass index to the PERF_CNTRS_REG
1389
* from 0 to 31. One of these will be picked up at cmd submit time
1390
* when the perf query is executed.
1391
*/
1392
struct tu_cs *cs;
1393
1394
if (!(device->perfcntrs_pass_cs = calloc(1, sizeof(struct tu_cs)))) {
1395
result = vk_startup_errorf(device->instance,
1396
VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");
1397
goto fail_perfcntrs_pass_alloc;
1398
}
1399
1400
device->perfcntrs_pass_cs_entries = calloc(32, sizeof(struct tu_cs_entry));
1401
if (!device->perfcntrs_pass_cs_entries) {
1402
result = vk_startup_errorf(device->instance,
1403
VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");
1404
goto fail_perfcntrs_pass_entries_alloc;
1405
}
1406
1407
cs = device->perfcntrs_pass_cs;
1408
tu_cs_init(cs, device, TU_CS_MODE_SUB_STREAM, 96);
1409
1410
for (unsigned i = 0; i < 32; i++) {
1411
struct tu_cs sub_cs;
1412
1413
result = tu_cs_begin_sub_stream(cs, 3, &sub_cs);
1414
if (result != VK_SUCCESS) {
1415
vk_startup_errorf(device->instance, result,
1416
"failed to allocate commands streams");
1417
goto fail_prepare_perfcntrs_pass_cs;
1418
}
1419
1420
tu_cs_emit_regs(&sub_cs, A6XX_CP_SCRATCH_REG(PERF_CNTRS_REG, 1 << i));
1421
tu_cs_emit_pkt7(&sub_cs, CP_WAIT_FOR_ME, 0);
1422
1423
device->perfcntrs_pass_cs_entries[i] = tu_cs_end_sub_stream(cs, &sub_cs);
1424
}
1425
}
1426
1427
/* Initialize a condition variable for timeline semaphore */
1428
pthread_condattr_t condattr;
1429
if (pthread_condattr_init(&condattr) != 0) {
1430
result = vk_startup_errorf(physical_device->instance,
1431
VK_ERROR_INITIALIZATION_FAILED,
1432
"pthread condattr init");
1433
goto fail_timeline_cond;
1434
}
1435
if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC) != 0) {
1436
pthread_condattr_destroy(&condattr);
1437
result = vk_startup_errorf(physical_device->instance,
1438
VK_ERROR_INITIALIZATION_FAILED,
1439
"pthread condattr clock setup");
1440
goto fail_timeline_cond;
1441
}
1442
if (pthread_cond_init(&device->timeline_cond, &condattr) != 0) {
1443
pthread_condattr_destroy(&condattr);
1444
result = vk_startup_errorf(physical_device->instance,
1445
VK_ERROR_INITIALIZATION_FAILED,
1446
"pthread cond init");
1447
goto fail_timeline_cond;
1448
}
1449
pthread_condattr_destroy(&condattr);
1450
1451
device->mem_cache = tu_pipeline_cache_from_handle(pc);
1452
1453
for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++)
1454
mtx_init(&device->scratch_bos[i].construct_mtx, mtx_plain);
1455
1456
mtx_init(&device->mutex, mtx_plain);
1457
1458
*pDevice = tu_device_to_handle(device);
1459
return VK_SUCCESS;
1460
1461
fail_timeline_cond:
1462
fail_prepare_perfcntrs_pass_cs:
1463
free(device->perfcntrs_pass_cs_entries);
1464
tu_cs_finish(device->perfcntrs_pass_cs);
1465
fail_perfcntrs_pass_entries_alloc:
1466
free(device->perfcntrs_pass_cs);
1467
fail_perfcntrs_pass_alloc:
1468
tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);
1469
fail_pipeline_cache:
1470
fail_global_bo_map:
1471
tu_bo_finish(device, &device->global_bo);
1472
1473
fail_global_bo:
1474
ir3_compiler_destroy(device->compiler);
1475
1476
fail_queues:
1477
for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1478
for (unsigned q = 0; q < device->queue_count[i]; q++)
1479
tu_queue_finish(&device->queues[i][q]);
1480
if (device->queue_count[i])
1481
vk_free(&device->vk.alloc, device->queues[i]);
1482
}
1483
1484
vk_device_finish(&device->vk);
1485
vk_free(&device->vk.alloc, device);
1486
return result;
1487
}
1488
1489
VKAPI_ATTR void VKAPI_CALL
1490
tu_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
1491
{
1492
TU_FROM_HANDLE(tu_device, device, _device);
1493
1494
if (!device)
1495
return;
1496
1497
for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1498
for (unsigned q = 0; q < device->queue_count[i]; q++)
1499
tu_queue_finish(&device->queues[i][q]);
1500
if (device->queue_count[i])
1501
vk_free(&device->vk.alloc, device->queues[i]);
1502
}
1503
1504
for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++) {
1505
if (device->scratch_bos[i].initialized)
1506
tu_bo_finish(device, &device->scratch_bos[i].bo);
1507
}
1508
1509
ir3_compiler_destroy(device->compiler);
1510
1511
VkPipelineCache pc = tu_pipeline_cache_to_handle(device->mem_cache);
1512
tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);
1513
1514
if (device->perfcntrs_pass_cs) {
1515
free(device->perfcntrs_pass_cs_entries);
1516
tu_cs_finish(device->perfcntrs_pass_cs);
1517
free(device->perfcntrs_pass_cs);
1518
}
1519
1520
pthread_cond_destroy(&device->timeline_cond);
1521
vk_free(&device->vk.alloc, device->bo_list);
1522
vk_free(&device->vk.alloc, device->bo_idx);
1523
vk_device_finish(&device->vk);
1524
vk_free(&device->vk.alloc, device);
1525
}
1526
1527
VkResult
1528
_tu_device_set_lost(struct tu_device *device,
1529
const char *msg, ...)
1530
{
1531
/* Set the flag indicating that waits should return in finite time even
1532
* after device loss.
1533
*/
1534
p_atomic_inc(&device->_lost);
1535
1536
/* TODO: Report the log message through VkDebugReportCallbackEXT instead */
1537
va_list ap;
1538
va_start(ap, msg);
1539
mesa_loge_v(msg, ap);
1540
va_end(ap);
1541
1542
if (env_var_as_boolean("TU_ABORT_ON_DEVICE_LOSS", false))
1543
abort();
1544
1545
return VK_ERROR_DEVICE_LOST;
1546
}
1547
1548
VkResult
1549
tu_get_scratch_bo(struct tu_device *dev, uint64_t size, struct tu_bo **bo)
1550
{
1551
unsigned size_log2 = MAX2(util_logbase2_ceil64(size), MIN_SCRATCH_BO_SIZE_LOG2);
1552
unsigned index = size_log2 - MIN_SCRATCH_BO_SIZE_LOG2;
1553
assert(index < ARRAY_SIZE(dev->scratch_bos));
1554
1555
for (unsigned i = index; i < ARRAY_SIZE(dev->scratch_bos); i++) {
1556
if (p_atomic_read(&dev->scratch_bos[i].initialized)) {
1557
/* Fast path: just return the already-allocated BO. */
1558
*bo = &dev->scratch_bos[i].bo;
1559
return VK_SUCCESS;
1560
}
1561
}
1562
1563
/* Slow path: actually allocate the BO. We take a lock because the process
1564
* of allocating it is slow, and we don't want to block the CPU while it
1565
* finishes.
1566
*/
1567
mtx_lock(&dev->scratch_bos[index].construct_mtx);
1568
1569
/* Another thread may have allocated it already while we were waiting on
1570
* the lock. We need to check this in order to avoid double-allocating.
1571
*/
1572
if (dev->scratch_bos[index].initialized) {
1573
mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1574
*bo = &dev->scratch_bos[index].bo;
1575
return VK_SUCCESS;
1576
}
1577
1578
unsigned bo_size = 1ull << size_log2;
1579
VkResult result = tu_bo_init_new(dev, &dev->scratch_bos[index].bo, bo_size,
1580
TU_BO_ALLOC_NO_FLAGS);
1581
if (result != VK_SUCCESS) {
1582
mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1583
return result;
1584
}
1585
1586
p_atomic_set(&dev->scratch_bos[index].initialized, true);
1587
1588
mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1589
1590
*bo = &dev->scratch_bos[index].bo;
1591
return VK_SUCCESS;
1592
}
1593
1594
VKAPI_ATTR VkResult VKAPI_CALL
1595
tu_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
1596
VkLayerProperties *pProperties)
1597
{
1598
*pPropertyCount = 0;
1599
return VK_SUCCESS;
1600
}
1601
1602
VKAPI_ATTR void VKAPI_CALL
1603
tu_GetDeviceQueue2(VkDevice _device,
1604
const VkDeviceQueueInfo2 *pQueueInfo,
1605
VkQueue *pQueue)
1606
{
1607
TU_FROM_HANDLE(tu_device, device, _device);
1608
struct tu_queue *queue;
1609
1610
queue =
1611
&device->queues[pQueueInfo->queueFamilyIndex][pQueueInfo->queueIndex];
1612
if (pQueueInfo->flags != queue->flags) {
1613
/* From the Vulkan 1.1.70 spec:
1614
*
1615
* "The queue returned by vkGetDeviceQueue2 must have the same
1616
* flags value from this structure as that used at device
1617
* creation time in a VkDeviceQueueCreateInfo instance. If no
1618
* matching flags were specified at device creation time then
1619
* pQueue will return VK_NULL_HANDLE."
1620
*/
1621
*pQueue = VK_NULL_HANDLE;
1622
return;
1623
}
1624
1625
*pQueue = tu_queue_to_handle(queue);
1626
}
1627
1628
VKAPI_ATTR VkResult VKAPI_CALL
1629
tu_QueueWaitIdle(VkQueue _queue)
1630
{
1631
TU_FROM_HANDLE(tu_queue, queue, _queue);
1632
1633
if (tu_device_is_lost(queue->device))
1634
return VK_ERROR_DEVICE_LOST;
1635
1636
if (queue->fence < 0)
1637
return VK_SUCCESS;
1638
1639
pthread_mutex_lock(&queue->device->submit_mutex);
1640
1641
do {
1642
tu_device_submit_deferred_locked(queue->device);
1643
1644
if (list_is_empty(&queue->queued_submits))
1645
break;
1646
1647
pthread_cond_wait(&queue->device->timeline_cond,
1648
&queue->device->submit_mutex);
1649
} while (!list_is_empty(&queue->queued_submits));
1650
1651
pthread_mutex_unlock(&queue->device->submit_mutex);
1652
1653
struct pollfd fds = { .fd = queue->fence, .events = POLLIN };
1654
int ret;
1655
do {
1656
ret = poll(&fds, 1, -1);
1657
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
1658
1659
/* TODO: otherwise set device lost ? */
1660
assert(ret == 1 && !(fds.revents & (POLLERR | POLLNVAL)));
1661
1662
close(queue->fence);
1663
queue->fence = -1;
1664
return VK_SUCCESS;
1665
}
1666
1667
VKAPI_ATTR VkResult VKAPI_CALL
1668
tu_DeviceWaitIdle(VkDevice _device)
1669
{
1670
TU_FROM_HANDLE(tu_device, device, _device);
1671
1672
if (tu_device_is_lost(device))
1673
return VK_ERROR_DEVICE_LOST;
1674
1675
for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1676
for (unsigned q = 0; q < device->queue_count[i]; q++) {
1677
tu_QueueWaitIdle(tu_queue_to_handle(&device->queues[i][q]));
1678
}
1679
}
1680
return VK_SUCCESS;
1681
}
1682
1683
VKAPI_ATTR VkResult VKAPI_CALL
1684
tu_EnumerateInstanceExtensionProperties(const char *pLayerName,
1685
uint32_t *pPropertyCount,
1686
VkExtensionProperties *pProperties)
1687
{
1688
if (pLayerName)
1689
return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1690
1691
return vk_enumerate_instance_extension_properties(
1692
&tu_instance_extensions_supported, pPropertyCount, pProperties);
1693
}
1694
1695
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1696
tu_GetInstanceProcAddr(VkInstance _instance, const char *pName)
1697
{
1698
TU_FROM_HANDLE(tu_instance, instance, _instance);
1699
return vk_instance_get_proc_addr(&instance->vk,
1700
&tu_instance_entrypoints,
1701
pName);
1702
}
1703
1704
/* The loader wants us to expose a second GetInstanceProcAddr function
1705
* to work around certain LD_PRELOAD issues seen in apps.
1706
*/
1707
PUBLIC
1708
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1709
vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName);
1710
1711
PUBLIC
1712
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1713
vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
1714
{
1715
return tu_GetInstanceProcAddr(instance, pName);
1716
}
1717
1718
VKAPI_ATTR VkResult VKAPI_CALL
1719
tu_AllocateMemory(VkDevice _device,
1720
const VkMemoryAllocateInfo *pAllocateInfo,
1721
const VkAllocationCallbacks *pAllocator,
1722
VkDeviceMemory *pMem)
1723
{
1724
TU_FROM_HANDLE(tu_device, device, _device);
1725
struct tu_device_memory *mem;
1726
VkResult result;
1727
1728
assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
1729
1730
if (pAllocateInfo->allocationSize == 0) {
1731
/* Apparently, this is allowed */
1732
*pMem = VK_NULL_HANDLE;
1733
return VK_SUCCESS;
1734
}
1735
1736
struct tu_memory_heap *mem_heap = &device->physical_device->heap;
1737
uint64_t mem_heap_used = p_atomic_read(&mem_heap->used);
1738
if (mem_heap_used > mem_heap->size)
1739
return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1740
1741
mem = vk_object_alloc(&device->vk, pAllocator, sizeof(*mem),
1742
VK_OBJECT_TYPE_DEVICE_MEMORY);
1743
if (mem == NULL)
1744
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1745
1746
const VkImportMemoryFdInfoKHR *fd_info =
1747
vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
1748
if (fd_info && !fd_info->handleType)
1749
fd_info = NULL;
1750
1751
if (fd_info) {
1752
assert(fd_info->handleType ==
1753
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1754
fd_info->handleType ==
1755
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1756
1757
/*
1758
* TODO Importing the same fd twice gives us the same handle without
1759
* reference counting. We need to maintain a per-instance handle-to-bo
1760
* table and add reference count to tu_bo.
1761
*/
1762
result = tu_bo_init_dmabuf(device, &mem->bo,
1763
pAllocateInfo->allocationSize, fd_info->fd);
1764
if (result == VK_SUCCESS) {
1765
/* take ownership and close the fd */
1766
close(fd_info->fd);
1767
}
1768
} else {
1769
result =
1770
tu_bo_init_new(device, &mem->bo, pAllocateInfo->allocationSize,
1771
TU_BO_ALLOC_NO_FLAGS);
1772
}
1773
1774
1775
if (result == VK_SUCCESS) {
1776
mem_heap_used = p_atomic_add_return(&mem_heap->used, mem->bo.size);
1777
if (mem_heap_used > mem_heap->size) {
1778
p_atomic_add(&mem_heap->used, -mem->bo.size);
1779
tu_bo_finish(device, &mem->bo);
1780
result = vk_errorf(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY,
1781
"Out of heap memory");
1782
}
1783
}
1784
1785
if (result != VK_SUCCESS) {
1786
vk_object_free(&device->vk, pAllocator, mem);
1787
return result;
1788
}
1789
1790
*pMem = tu_device_memory_to_handle(mem);
1791
1792
return VK_SUCCESS;
1793
}
1794
1795
VKAPI_ATTR void VKAPI_CALL
1796
tu_FreeMemory(VkDevice _device,
1797
VkDeviceMemory _mem,
1798
const VkAllocationCallbacks *pAllocator)
1799
{
1800
TU_FROM_HANDLE(tu_device, device, _device);
1801
TU_FROM_HANDLE(tu_device_memory, mem, _mem);
1802
1803
if (mem == NULL)
1804
return;
1805
1806
p_atomic_add(&device->physical_device->heap.used, -mem->bo.size);
1807
tu_bo_finish(device, &mem->bo);
1808
vk_object_free(&device->vk, pAllocator, mem);
1809
}
1810
1811
VKAPI_ATTR VkResult VKAPI_CALL
1812
tu_MapMemory(VkDevice _device,
1813
VkDeviceMemory _memory,
1814
VkDeviceSize offset,
1815
VkDeviceSize size,
1816
VkMemoryMapFlags flags,
1817
void **ppData)
1818
{
1819
TU_FROM_HANDLE(tu_device, device, _device);
1820
TU_FROM_HANDLE(tu_device_memory, mem, _memory);
1821
VkResult result;
1822
1823
if (mem == NULL) {
1824
*ppData = NULL;
1825
return VK_SUCCESS;
1826
}
1827
1828
if (!mem->bo.map) {
1829
result = tu_bo_map(device, &mem->bo);
1830
if (result != VK_SUCCESS)
1831
return result;
1832
}
1833
1834
*ppData = mem->bo.map + offset;
1835
return VK_SUCCESS;
1836
}
1837
1838
VKAPI_ATTR void VKAPI_CALL
1839
tu_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)
1840
{
1841
/* TODO: unmap here instead of waiting for FreeMemory */
1842
}
1843
1844
VKAPI_ATTR VkResult VKAPI_CALL
1845
tu_FlushMappedMemoryRanges(VkDevice _device,
1846
uint32_t memoryRangeCount,
1847
const VkMappedMemoryRange *pMemoryRanges)
1848
{
1849
return VK_SUCCESS;
1850
}
1851
1852
VKAPI_ATTR VkResult VKAPI_CALL
1853
tu_InvalidateMappedMemoryRanges(VkDevice _device,
1854
uint32_t memoryRangeCount,
1855
const VkMappedMemoryRange *pMemoryRanges)
1856
{
1857
return VK_SUCCESS;
1858
}
1859
1860
VKAPI_ATTR void VKAPI_CALL
1861
tu_GetBufferMemoryRequirements2(
1862
VkDevice device,
1863
const VkBufferMemoryRequirementsInfo2 *pInfo,
1864
VkMemoryRequirements2 *pMemoryRequirements)
1865
{
1866
TU_FROM_HANDLE(tu_buffer, buffer, pInfo->buffer);
1867
1868
pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
1869
.memoryTypeBits = 1,
1870
.alignment = 64,
1871
.size = MAX2(align64(buffer->size, 64), buffer->size),
1872
};
1873
1874
vk_foreach_struct(ext, pMemoryRequirements->pNext) {
1875
switch (ext->sType) {
1876
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
1877
VkMemoryDedicatedRequirements *req =
1878
(VkMemoryDedicatedRequirements *) ext;
1879
req->requiresDedicatedAllocation = false;
1880
req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
1881
break;
1882
}
1883
default:
1884
break;
1885
}
1886
}
1887
}
1888
1889
VKAPI_ATTR void VKAPI_CALL
1890
tu_GetImageMemoryRequirements2(VkDevice device,
1891
const VkImageMemoryRequirementsInfo2 *pInfo,
1892
VkMemoryRequirements2 *pMemoryRequirements)
1893
{
1894
TU_FROM_HANDLE(tu_image, image, pInfo->image);
1895
1896
pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
1897
.memoryTypeBits = 1,
1898
.alignment = image->layout[0].base_align,
1899
.size = image->total_size
1900
};
1901
1902
vk_foreach_struct(ext, pMemoryRequirements->pNext) {
1903
switch (ext->sType) {
1904
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
1905
VkMemoryDedicatedRequirements *req =
1906
(VkMemoryDedicatedRequirements *) ext;
1907
req->requiresDedicatedAllocation = image->shareable;
1908
req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
1909
break;
1910
}
1911
default:
1912
break;
1913
}
1914
}
1915
}
1916
1917
VKAPI_ATTR void VKAPI_CALL
1918
tu_GetImageSparseMemoryRequirements2(
1919
VkDevice device,
1920
const VkImageSparseMemoryRequirementsInfo2 *pInfo,
1921
uint32_t *pSparseMemoryRequirementCount,
1922
VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1923
{
1924
tu_stub();
1925
}
1926
1927
VKAPI_ATTR void VKAPI_CALL
1928
tu_GetDeviceMemoryCommitment(VkDevice device,
1929
VkDeviceMemory memory,
1930
VkDeviceSize *pCommittedMemoryInBytes)
1931
{
1932
*pCommittedMemoryInBytes = 0;
1933
}
1934
1935
VKAPI_ATTR VkResult VKAPI_CALL
1936
tu_BindBufferMemory2(VkDevice device,
1937
uint32_t bindInfoCount,
1938
const VkBindBufferMemoryInfo *pBindInfos)
1939
{
1940
for (uint32_t i = 0; i < bindInfoCount; ++i) {
1941
TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
1942
TU_FROM_HANDLE(tu_buffer, buffer, pBindInfos[i].buffer);
1943
1944
if (mem) {
1945
buffer->bo = &mem->bo;
1946
buffer->bo_offset = pBindInfos[i].memoryOffset;
1947
} else {
1948
buffer->bo = NULL;
1949
}
1950
}
1951
return VK_SUCCESS;
1952
}
1953
1954
VKAPI_ATTR VkResult VKAPI_CALL
1955
tu_BindImageMemory2(VkDevice device,
1956
uint32_t bindInfoCount,
1957
const VkBindImageMemoryInfo *pBindInfos)
1958
{
1959
for (uint32_t i = 0; i < bindInfoCount; ++i) {
1960
TU_FROM_HANDLE(tu_image, image, pBindInfos[i].image);
1961
TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
1962
1963
if (mem) {
1964
image->bo = &mem->bo;
1965
image->bo_offset = pBindInfos[i].memoryOffset;
1966
} else {
1967
image->bo = NULL;
1968
image->bo_offset = 0;
1969
}
1970
}
1971
1972
return VK_SUCCESS;
1973
}
1974
1975
VKAPI_ATTR VkResult VKAPI_CALL
1976
tu_QueueBindSparse(VkQueue _queue,
1977
uint32_t bindInfoCount,
1978
const VkBindSparseInfo *pBindInfo,
1979
VkFence _fence)
1980
{
1981
return VK_SUCCESS;
1982
}
1983
1984
VKAPI_ATTR VkResult VKAPI_CALL
1985
tu_CreateEvent(VkDevice _device,
1986
const VkEventCreateInfo *pCreateInfo,
1987
const VkAllocationCallbacks *pAllocator,
1988
VkEvent *pEvent)
1989
{
1990
TU_FROM_HANDLE(tu_device, device, _device);
1991
1992
struct tu_event *event =
1993
vk_object_alloc(&device->vk, pAllocator, sizeof(*event),
1994
VK_OBJECT_TYPE_EVENT);
1995
if (!event)
1996
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1997
1998
VkResult result = tu_bo_init_new(device, &event->bo, 0x1000,
1999
TU_BO_ALLOC_NO_FLAGS);
2000
if (result != VK_SUCCESS)
2001
goto fail_alloc;
2002
2003
result = tu_bo_map(device, &event->bo);
2004
if (result != VK_SUCCESS)
2005
goto fail_map;
2006
2007
*pEvent = tu_event_to_handle(event);
2008
2009
return VK_SUCCESS;
2010
2011
fail_map:
2012
tu_bo_finish(device, &event->bo);
2013
fail_alloc:
2014
vk_object_free(&device->vk, pAllocator, event);
2015
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2016
}
2017
2018
VKAPI_ATTR void VKAPI_CALL
2019
tu_DestroyEvent(VkDevice _device,
2020
VkEvent _event,
2021
const VkAllocationCallbacks *pAllocator)
2022
{
2023
TU_FROM_HANDLE(tu_device, device, _device);
2024
TU_FROM_HANDLE(tu_event, event, _event);
2025
2026
if (!event)
2027
return;
2028
2029
tu_bo_finish(device, &event->bo);
2030
vk_object_free(&device->vk, pAllocator, event);
2031
}
2032
2033
VKAPI_ATTR VkResult VKAPI_CALL
2034
tu_GetEventStatus(VkDevice _device, VkEvent _event)
2035
{
2036
TU_FROM_HANDLE(tu_event, event, _event);
2037
2038
if (*(uint64_t*) event->bo.map == 1)
2039
return VK_EVENT_SET;
2040
return VK_EVENT_RESET;
2041
}
2042
2043
VKAPI_ATTR VkResult VKAPI_CALL
2044
tu_SetEvent(VkDevice _device, VkEvent _event)
2045
{
2046
TU_FROM_HANDLE(tu_event, event, _event);
2047
*(uint64_t*) event->bo.map = 1;
2048
2049
return VK_SUCCESS;
2050
}
2051
2052
VKAPI_ATTR VkResult VKAPI_CALL
2053
tu_ResetEvent(VkDevice _device, VkEvent _event)
2054
{
2055
TU_FROM_HANDLE(tu_event, event, _event);
2056
*(uint64_t*) event->bo.map = 0;
2057
2058
return VK_SUCCESS;
2059
}
2060
2061
VKAPI_ATTR VkResult VKAPI_CALL
2062
tu_CreateBuffer(VkDevice _device,
2063
const VkBufferCreateInfo *pCreateInfo,
2064
const VkAllocationCallbacks *pAllocator,
2065
VkBuffer *pBuffer)
2066
{
2067
TU_FROM_HANDLE(tu_device, device, _device);
2068
struct tu_buffer *buffer;
2069
2070
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
2071
2072
buffer = vk_object_alloc(&device->vk, pAllocator, sizeof(*buffer),
2073
VK_OBJECT_TYPE_BUFFER);
2074
if (buffer == NULL)
2075
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2076
2077
buffer->size = pCreateInfo->size;
2078
buffer->usage = pCreateInfo->usage;
2079
buffer->flags = pCreateInfo->flags;
2080
2081
*pBuffer = tu_buffer_to_handle(buffer);
2082
2083
return VK_SUCCESS;
2084
}
2085
2086
VKAPI_ATTR void VKAPI_CALL
2087
tu_DestroyBuffer(VkDevice _device,
2088
VkBuffer _buffer,
2089
const VkAllocationCallbacks *pAllocator)
2090
{
2091
TU_FROM_HANDLE(tu_device, device, _device);
2092
TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
2093
2094
if (!buffer)
2095
return;
2096
2097
vk_object_free(&device->vk, pAllocator, buffer);
2098
}
2099
2100
VKAPI_ATTR VkResult VKAPI_CALL
2101
tu_CreateFramebuffer(VkDevice _device,
2102
const VkFramebufferCreateInfo *pCreateInfo,
2103
const VkAllocationCallbacks *pAllocator,
2104
VkFramebuffer *pFramebuffer)
2105
{
2106
TU_FROM_HANDLE(tu_device, device, _device);
2107
TU_FROM_HANDLE(tu_render_pass, pass, pCreateInfo->renderPass);
2108
struct tu_framebuffer *framebuffer;
2109
2110
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
2111
2112
size_t size = sizeof(*framebuffer) + sizeof(struct tu_attachment_info) *
2113
pCreateInfo->attachmentCount;
2114
framebuffer = vk_object_alloc(&device->vk, pAllocator, size,
2115
VK_OBJECT_TYPE_FRAMEBUFFER);
2116
if (framebuffer == NULL)
2117
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2118
2119
framebuffer->attachment_count = pCreateInfo->attachmentCount;
2120
framebuffer->width = pCreateInfo->width;
2121
framebuffer->height = pCreateInfo->height;
2122
framebuffer->layers = pCreateInfo->layers;
2123
for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
2124
VkImageView _iview = pCreateInfo->pAttachments[i];
2125
struct tu_image_view *iview = tu_image_view_from_handle(_iview);
2126
framebuffer->attachments[i].attachment = iview;
2127
}
2128
2129
tu_framebuffer_tiling_config(framebuffer, device, pass);
2130
2131
*pFramebuffer = tu_framebuffer_to_handle(framebuffer);
2132
return VK_SUCCESS;
2133
}
2134
2135
VKAPI_ATTR void VKAPI_CALL
2136
tu_DestroyFramebuffer(VkDevice _device,
2137
VkFramebuffer _fb,
2138
const VkAllocationCallbacks *pAllocator)
2139
{
2140
TU_FROM_HANDLE(tu_device, device, _device);
2141
TU_FROM_HANDLE(tu_framebuffer, fb, _fb);
2142
2143
if (!fb)
2144
return;
2145
2146
vk_object_free(&device->vk, pAllocator, fb);
2147
}
2148
2149
static void
2150
tu_init_sampler(struct tu_device *device,
2151
struct tu_sampler *sampler,
2152
const VkSamplerCreateInfo *pCreateInfo)
2153
{
2154
const struct VkSamplerReductionModeCreateInfo *reduction =
2155
vk_find_struct_const(pCreateInfo->pNext, SAMPLER_REDUCTION_MODE_CREATE_INFO);
2156
const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion =
2157
vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);
2158
const VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color =
2159
vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);
2160
/* for non-custom border colors, the VK enum is translated directly to an offset in
2161
* the border color buffer. custom border colors are located immediately after the
2162
* builtin colors, and thus an offset of TU_BORDER_COLOR_BUILTIN is added.
2163
*/
2164
uint32_t border_color = (unsigned) pCreateInfo->borderColor;
2165
if (pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT ||
2166
pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT) {
2167
mtx_lock(&device->mutex);
2168
border_color = BITSET_FFS(device->custom_border_color);
2169
BITSET_CLEAR(device->custom_border_color, border_color);
2170
mtx_unlock(&device->mutex);
2171
tu6_pack_border_color(device->global_bo.map + gb_offset(bcolor[border_color]),
2172
&custom_border_color->customBorderColor,
2173
pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT);
2174
border_color += TU_BORDER_COLOR_BUILTIN;
2175
}
2176
2177
unsigned aniso = pCreateInfo->anisotropyEnable ?
2178
util_last_bit(MIN2((uint32_t)pCreateInfo->maxAnisotropy >> 1, 8)) : 0;
2179
bool miplinear = (pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR);
2180
float min_lod = CLAMP(pCreateInfo->minLod, 0.0f, 4095.0f / 256.0f);
2181
float max_lod = CLAMP(pCreateInfo->maxLod, 0.0f, 4095.0f / 256.0f);
2182
2183
sampler->descriptor[0] =
2184
COND(miplinear, A6XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR) |
2185
A6XX_TEX_SAMP_0_XY_MAG(tu6_tex_filter(pCreateInfo->magFilter, aniso)) |
2186
A6XX_TEX_SAMP_0_XY_MIN(tu6_tex_filter(pCreateInfo->minFilter, aniso)) |
2187
A6XX_TEX_SAMP_0_ANISO(aniso) |
2188
A6XX_TEX_SAMP_0_WRAP_S(tu6_tex_wrap(pCreateInfo->addressModeU)) |
2189
A6XX_TEX_SAMP_0_WRAP_T(tu6_tex_wrap(pCreateInfo->addressModeV)) |
2190
A6XX_TEX_SAMP_0_WRAP_R(tu6_tex_wrap(pCreateInfo->addressModeW)) |
2191
A6XX_TEX_SAMP_0_LOD_BIAS(pCreateInfo->mipLodBias);
2192
sampler->descriptor[1] =
2193
/* COND(!cso->seamless_cube_map, A6XX_TEX_SAMP_1_CUBEMAPSEAMLESSFILTOFF) | */
2194
COND(pCreateInfo->unnormalizedCoordinates, A6XX_TEX_SAMP_1_UNNORM_COORDS) |
2195
A6XX_TEX_SAMP_1_MIN_LOD(min_lod) |
2196
A6XX_TEX_SAMP_1_MAX_LOD(max_lod) |
2197
COND(pCreateInfo->compareEnable,
2198
A6XX_TEX_SAMP_1_COMPARE_FUNC(tu6_compare_func(pCreateInfo->compareOp)));
2199
sampler->descriptor[2] = A6XX_TEX_SAMP_2_BCOLOR(border_color);
2200
sampler->descriptor[3] = 0;
2201
2202
if (reduction) {
2203
sampler->descriptor[2] |= A6XX_TEX_SAMP_2_REDUCTION_MODE(
2204
tu6_reduction_mode(reduction->reductionMode));
2205
}
2206
2207
sampler->ycbcr_sampler = ycbcr_conversion ?
2208
tu_sampler_ycbcr_conversion_from_handle(ycbcr_conversion->conversion) : NULL;
2209
2210
if (sampler->ycbcr_sampler &&
2211
sampler->ycbcr_sampler->chroma_filter == VK_FILTER_LINEAR) {
2212
sampler->descriptor[2] |= A6XX_TEX_SAMP_2_CHROMA_LINEAR;
2213
}
2214
2215
/* TODO:
2216
* A6XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR disables mipmapping, but vk has no NONE mipfilter?
2217
*/
2218
}
2219
2220
VKAPI_ATTR VkResult VKAPI_CALL
2221
tu_CreateSampler(VkDevice _device,
2222
const VkSamplerCreateInfo *pCreateInfo,
2223
const VkAllocationCallbacks *pAllocator,
2224
VkSampler *pSampler)
2225
{
2226
TU_FROM_HANDLE(tu_device, device, _device);
2227
struct tu_sampler *sampler;
2228
2229
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
2230
2231
sampler = vk_object_alloc(&device->vk, pAllocator, sizeof(*sampler),
2232
VK_OBJECT_TYPE_SAMPLER);
2233
if (!sampler)
2234
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2235
2236
tu_init_sampler(device, sampler, pCreateInfo);
2237
*pSampler = tu_sampler_to_handle(sampler);
2238
2239
return VK_SUCCESS;
2240
}
2241
2242
VKAPI_ATTR void VKAPI_CALL
2243
tu_DestroySampler(VkDevice _device,
2244
VkSampler _sampler,
2245
const VkAllocationCallbacks *pAllocator)
2246
{
2247
TU_FROM_HANDLE(tu_device, device, _device);
2248
TU_FROM_HANDLE(tu_sampler, sampler, _sampler);
2249
uint32_t border_color;
2250
2251
if (!sampler)
2252
return;
2253
2254
border_color = (sampler->descriptor[2] & A6XX_TEX_SAMP_2_BCOLOR__MASK) >> A6XX_TEX_SAMP_2_BCOLOR__SHIFT;
2255
if (border_color >= TU_BORDER_COLOR_BUILTIN) {
2256
border_color -= TU_BORDER_COLOR_BUILTIN;
2257
/* if the sampler had a custom border color, free it. TODO: no lock */
2258
mtx_lock(&device->mutex);
2259
assert(!BITSET_TEST(device->custom_border_color, border_color));
2260
BITSET_SET(device->custom_border_color, border_color);
2261
mtx_unlock(&device->mutex);
2262
}
2263
2264
vk_object_free(&device->vk, pAllocator, sampler);
2265
}
2266
2267
/* vk_icd.h does not declare this function, so we declare it here to
2268
* suppress Wmissing-prototypes.
2269
*/
2270
PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2271
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion);
2272
2273
PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2274
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
2275
{
2276
/* For the full details on loader interface versioning, see
2277
* <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
2278
* What follows is a condensed summary, to help you navigate the large and
2279
* confusing official doc.
2280
*
2281
* - Loader interface v0 is incompatible with later versions. We don't
2282
* support it.
2283
*
2284
* - In loader interface v1:
2285
* - The first ICD entrypoint called by the loader is
2286
* vk_icdGetInstanceProcAddr(). The ICD must statically expose this
2287
* entrypoint.
2288
* - The ICD must statically expose no other Vulkan symbol unless it
2289
* is linked with -Bsymbolic.
2290
* - Each dispatchable Vulkan handle created by the ICD must be
2291
* a pointer to a struct whose first member is VK_LOADER_DATA. The
2292
* ICD must initialize VK_LOADER_DATA.loadMagic to
2293
* ICD_LOADER_MAGIC.
2294
* - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
2295
* vkDestroySurfaceKHR(). The ICD must be capable of working with
2296
* such loader-managed surfaces.
2297
*
2298
* - Loader interface v2 differs from v1 in:
2299
* - The first ICD entrypoint called by the loader is
2300
* vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
2301
* statically expose this entrypoint.
2302
*
2303
* - Loader interface v3 differs from v2 in:
2304
* - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
2305
* vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
2306
* because the loader no longer does so.
2307
*/
2308
*pSupportedVersion = MIN2(*pSupportedVersion, 3u);
2309
return VK_SUCCESS;
2310
}
2311
2312
VKAPI_ATTR VkResult VKAPI_CALL
2313
tu_GetMemoryFdKHR(VkDevice _device,
2314
const VkMemoryGetFdInfoKHR *pGetFdInfo,
2315
int *pFd)
2316
{
2317
TU_FROM_HANDLE(tu_device, device, _device);
2318
TU_FROM_HANDLE(tu_device_memory, memory, pGetFdInfo->memory);
2319
2320
assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
2321
2322
/* At the moment, we support only the below handle types. */
2323
assert(pGetFdInfo->handleType ==
2324
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
2325
pGetFdInfo->handleType ==
2326
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2327
2328
int prime_fd = tu_bo_export_dmabuf(device, &memory->bo);
2329
if (prime_fd < 0)
2330
return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2331
2332
*pFd = prime_fd;
2333
return VK_SUCCESS;
2334
}
2335
2336
VKAPI_ATTR VkResult VKAPI_CALL
2337
tu_GetMemoryFdPropertiesKHR(VkDevice _device,
2338
VkExternalMemoryHandleTypeFlagBits handleType,
2339
int fd,
2340
VkMemoryFdPropertiesKHR *pMemoryFdProperties)
2341
{
2342
assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2343
pMemoryFdProperties->memoryTypeBits = 1;
2344
return VK_SUCCESS;
2345
}
2346
2347
VKAPI_ATTR void VKAPI_CALL
2348
tu_GetPhysicalDeviceExternalFenceProperties(
2349
VkPhysicalDevice physicalDevice,
2350
const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
2351
VkExternalFenceProperties *pExternalFenceProperties)
2352
{
2353
pExternalFenceProperties->exportFromImportedHandleTypes = 0;
2354
pExternalFenceProperties->compatibleHandleTypes = 0;
2355
pExternalFenceProperties->externalFenceFeatures = 0;
2356
}
2357
2358
VKAPI_ATTR void VKAPI_CALL
2359
tu_GetDeviceGroupPeerMemoryFeatures(
2360
VkDevice device,
2361
uint32_t heapIndex,
2362
uint32_t localDeviceIndex,
2363
uint32_t remoteDeviceIndex,
2364
VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
2365
{
2366
assert(localDeviceIndex == remoteDeviceIndex);
2367
2368
*pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |
2369
VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |
2370
VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |
2371
VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;
2372
}
2373
2374
VKAPI_ATTR void VKAPI_CALL
2375
tu_GetPhysicalDeviceMultisamplePropertiesEXT(
2376
VkPhysicalDevice physicalDevice,
2377
VkSampleCountFlagBits samples,
2378
VkMultisamplePropertiesEXT* pMultisampleProperties)
2379
{
2380
TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
2381
2382
if (samples <= VK_SAMPLE_COUNT_4_BIT && pdevice->vk.supported_extensions.EXT_sample_locations)
2383
pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 1, 1 };
2384
else
2385
pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 0, 0 };
2386
}
2387
2388