2 * Copyright © 2019 Raspberry Pi
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:
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
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
28 #include <sys/sysinfo.h>
31 #include "util/debug.h"
32 #include "libresoc_private.h"
37 libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName
,
38 uint32_t *pPropertyCount
,
39 VkExtensionProperties
*pProperties
)
41 if (getenv("LIBRESOC_TRACE")) {
42 fprintf(stderr
, "EnumerateInstanceExtensionProperties called for: %s \n", pLayerName
);
44 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
46 for (int i
= 0; i
< LIBRESOC_INSTANCE_EXTENSION_COUNT
; i
++) {
47 if (libresoc_instance_extensions_supported
.extensions
[i
]) {
48 vk_outarray_append(&out
, prop
) {
49 *prop
= libresoc_instance_extensions
[i
];
54 return vk_outarray_status(&out
);
58 default_alloc_func(void *pUserData
, size_t size
, size_t align
,
59 VkSystemAllocationScope allocationScope
)
65 default_realloc_func(void *pUserData
, void *pOriginal
, size_t size
,
66 size_t align
, VkSystemAllocationScope allocationScope
)
68 return realloc(pOriginal
, size
);
72 default_free_func(void *pUserData
, void *pMemory
)
77 static const VkAllocationCallbacks default_alloc
= {
79 .pfnAllocation
= default_alloc_func
,
80 .pfnReallocation
= default_realloc_func
,
81 .pfnFree
= default_free_func
,
84 static const struct debug_control libresoc_debug_options
[] = {
85 {"nofastclears", LIBRESOC_DEBUG_NO_FAST_CLEARS
},
86 {"nodcc", LIBRESOC_DEBUG_NO_DCC
},
87 {"shaders", LIBRESOC_DEBUG_DUMP_SHADERS
},
88 {"nocache", LIBRESOC_DEBUG_NO_CACHE
},
89 {"shaderstats", LIBRESOC_DEBUG_DUMP_SHADER_STATS
},
90 {"nohiz", LIBRESOC_DEBUG_NO_HIZ
},
91 {"nocompute", LIBRESOC_DEBUG_NO_COMPUTE_QUEUE
},
92 {"allbos", LIBRESOC_DEBUG_ALL_BOS
},
93 {"noibs", LIBRESOC_DEBUG_NO_IBS
},
94 {"spirv", LIBRESOC_DEBUG_DUMP_SPIRV
},
95 {"vmfaults", LIBRESOC_DEBUG_VM_FAULTS
},
96 {"zerovram", LIBRESOC_DEBUG_ZERO_VRAM
},
97 {"syncshaders", LIBRESOC_DEBUG_SYNC_SHADERS
},
98 {"preoptir", LIBRESOC_DEBUG_PREOPTIR
},
99 {"nodynamicbounds", LIBRESOC_DEBUG_NO_DYNAMIC_BOUNDS
},
100 {"nooutoforder", LIBRESOC_DEBUG_NO_OUT_OF_ORDER
},
101 {"info", LIBRESOC_DEBUG_INFO
},
102 {"errors", LIBRESOC_DEBUG_ERRORS
},
103 {"startup", LIBRESOC_DEBUG_STARTUP
},
104 {"checkir", LIBRESOC_DEBUG_CHECKIR
},
105 {"nothreadllvm", LIBRESOC_DEBUG_NOTHREADLLVM
},
106 {"nobinning", LIBRESOC_DEBUG_NOBINNING
},
107 {"nongg", LIBRESOC_DEBUG_NO_NGG
},
108 {"allentrypoints", LIBRESOC_DEBUG_ALL_ENTRYPOINTS
},
109 {"metashaders", LIBRESOC_DEBUG_DUMP_META_SHADERS
},
110 {"nomemorycache", LIBRESOC_DEBUG_NO_MEMORY_CACHE
},
111 {"llvm", LIBRESOC_DEBUG_LLVM
},
112 {"forcecompress", LIBRESOC_DEBUG_FORCE_COMPRESS
},
117 libresoc_get_debug_option_name(int id
)
119 assert(id
< ARRAY_SIZE(libresoc_debug_options
) - 1);
120 return libresoc_debug_options
[id
].string
;
123 libresoc_CreateInstance(const VkInstanceCreateInfo
*pCreateInfo
,
124 const VkAllocationCallbacks
*pAllocator
,
125 VkInstance
*pInstance
)
127 if (getenv("LIBRESOC_TRACE")) {
128 fprintf(stderr
, "CreateInstance called. \n");
130 struct libresoc_instance
*instance
;
132 instance
= vk_zalloc2(&default_alloc
, pAllocator
, sizeof(*instance
), 8,
133 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
135 return vk_error(NULL
, VK_ERROR_OUT_OF_HOST_MEMORY
);
137 vk_object_base_init(NULL
, &instance
->base
, VK_OBJECT_TYPE_INSTANCE
);
140 instance
->alloc
= *pAllocator
;
142 instance
->alloc
= default_alloc
;
143 if (pCreateInfo
->pApplicationInfo
) {
144 const VkApplicationInfo
*app
= pCreateInfo
->pApplicationInfo
;
146 instance
->engineName
=
147 vk_strdup(&instance
->alloc
, app
->pEngineName
,
148 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
149 instance
->engineVersion
= app
->engineVersion
;
150 instance
->apiVersion
= app
->apiVersion
;
152 instance
->debug_flags
= parse_debug_string(getenv("LIBRESOC_DEBUG"),
153 libresoc_debug_options
);
154 /*TODO : enable extensions*/
155 for (uint32_t i
= 0; i
< pCreateInfo
->enabledExtensionCount
; i
++) {
157 for (idx
= 0; idx
< LIBRESOC_INSTANCE_EXTENSION_COUNT
; idx
++) {
158 if (!strcmp(pCreateInfo
->ppEnabledExtensionNames
[i
],
159 libresoc_instance_extensions
[idx
].extensionName
))
163 if (idx
>= LIBRESOC_INSTANCE_EXTENSION_COUNT
||
164 !libresoc_instance_extensions_supported
.extensions
[idx
]) {
165 vk_object_base_finish(&instance
->base
);
166 vk_free2(&default_alloc
, pAllocator
, instance
);
167 return vk_error(instance
, VK_ERROR_EXTENSION_NOT_PRESENT
);
170 instance
->enabled_extensions
.extensions
[idx
] = true;
172 for (unsigned i
= 0; i
< ARRAY_SIZE(instance
->dispatch
.entrypoints
); i
++) {
173 /* Vulkan requires that entrypoints for extensions which have
174 * not been enabled must not be advertised.
176 if (!libresoc_instance_entrypoint_is_enabled(i
, instance
->apiVersion
,
177 &instance
->enabled_extensions
)) {
178 instance
->dispatch
.entrypoints
[i
] = NULL
;
180 instance
->dispatch
.entrypoints
[i
] =
181 libresoc_instance_dispatch_table
.entrypoints
[i
];
184 for (unsigned i
= 0; i
< ARRAY_SIZE(instance
->physical_device_dispatch
.entrypoints
); i
++) {
185 /* Vulkan requires that entrypoints for extensions which have
186 * not been enabled must not be advertised.
188 if (!libresoc_physical_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
189 &instance
->enabled_extensions
)) {
190 instance
->physical_device_dispatch
.entrypoints
[i
] = NULL
;
192 instance
->physical_device_dispatch
.entrypoints
[i
] =
193 libresoc_physical_device_dispatch_table
.entrypoints
[i
];
197 for (unsigned i
= 0; i
< ARRAY_SIZE(instance
->device_dispatch
.entrypoints
); i
++) {
198 /* Vulkan requires that entrypoints for extensions which have
199 * not been enabled must not be advertised.
201 if (!libresoc_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
202 &instance
->enabled_extensions
, NULL
)) {
203 instance
->device_dispatch
.entrypoints
[i
] = NULL
;
205 instance
->device_dispatch
.entrypoints
[i
] =
206 libresoc_device_dispatch_table
.entrypoints
[i
];
209 instance
->physical_devices_enumerated
= false;
210 list_inithead(&instance
->physical_devices
);
211 *pInstance
= libresoc_instance_to_handle(instance
);
217 libresoc_DestroyInstance(VkInstance _instance
,
218 const VkAllocationCallbacks
*pAllocator
)
220 if (getenv("LIBRESOC_TRACE")) {
221 fprintf(stderr
, "DestroyInstance called. \n");
227 libresoc_physical_device_try_create(struct libresoc_instance
*instance
,
228 struct libresoc_physical_device
**device_out
)
232 struct libresoc_physical_device
*device
=
233 vk_zalloc2(&instance
->alloc
, NULL
, sizeof(*device
), 8,
234 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
236 result
= vk_error(instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
240 device
->_loader_data
.loaderMagic
= ICD_LOADER_MAGIC
;
241 device
->instance
= instance
;
243 snprintf(device
->name
, sizeof(device
->name
),
245 *device_out
= device
;
251 libresoc_enumerate_physical_devices(struct libresoc_instance
*instance
)
254 if (instance
->physical_devices_enumerated
)
257 instance
->physical_devices_enumerated
= true;
258 VkResult result
= VK_SUCCESS
;
259 /* the driver creates a null
260 * device that allows to test the compiler without having a physical device
262 struct libresoc_physical_device
*pdevice
;
264 result
= libresoc_physical_device_try_create(instance
, &pdevice
);
265 if (result
!= VK_SUCCESS
)
268 list_addtail(&pdevice
->link
, &instance
->physical_devices
);
274 libresoc_EnumeratePhysicalDevices(VkInstance _instance
,
275 uint32_t *pPhysicalDeviceCount
,
276 VkPhysicalDevice
*pPhysicalDevices
)
278 if (getenv("LIBRESOC_TRACE")) {
279 fprintf(stderr
, "EnumeratePhysicalDevices called\n");
281 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
282 VK_OUTARRAY_MAKE(out
, pPhysicalDevices
, pPhysicalDeviceCount
);
284 VkResult result
= libresoc_enumerate_physical_devices(instance
);
285 if (result
!= VK_SUCCESS
)
288 list_for_each_entry(struct libresoc_physical_device
, pdevice
,
289 &instance
->physical_devices
, link
) {
290 vk_outarray_append(&out
, i
) {
291 *i
= libresoc_physical_device_to_handle(pdevice
);
295 return vk_outarray_status(&out
);
299 libresoc_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice
,
300 VkPhysicalDeviceFeatures
*pFeatures
)
302 if (getenv("LIBRESOC_TRACE")) {
303 fprintf(stderr
, "GetPhysicalDeviceFeatures called. \n");
305 //LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
306 memset(pFeatures
, 0, sizeof(*pFeatures
));
308 *pFeatures
= (VkPhysicalDeviceFeatures
) {
309 .robustBufferAccess
= true,
310 .fullDrawIndexUint32
= true,
311 .imageCubeArray
= true,
312 .independentBlend
= true,
313 .geometryShader
= true,
314 .tessellationShader
= true,
315 .sampleRateShading
= true,
316 .dualSrcBlend
= true,
318 .multiDrawIndirect
= true,
319 .drawIndirectFirstInstance
= true,
321 .depthBiasClamp
= true,
322 .fillModeNonSolid
= true,
327 .multiViewport
= true,
328 .samplerAnisotropy
= true,
329 .textureCompressionETC2
= false,
330 .textureCompressionASTC_LDR
= false,
331 .textureCompressionBC
= true,
332 .occlusionQueryPrecise
= true,
333 .pipelineStatisticsQuery
= true,
334 .vertexPipelineStoresAndAtomics
= true,
335 .fragmentStoresAndAtomics
= true,
336 .shaderTessellationAndGeometryPointSize
= true,
337 .shaderImageGatherExtended
= true,
338 .shaderStorageImageExtendedFormats
= true,
339 .shaderStorageImageMultisample
= true,
340 .shaderUniformBufferArrayDynamicIndexing
= true,
341 .shaderSampledImageArrayDynamicIndexing
= true,
342 .shaderStorageBufferArrayDynamicIndexing
= true,
343 .shaderStorageImageArrayDynamicIndexing
= true,
344 .shaderStorageImageReadWithoutFormat
= true,
345 .shaderStorageImageWriteWithoutFormat
= true,
346 .shaderClipDistance
= true,
347 .shaderCullDistance
= true,
348 .shaderFloat64
= true,
351 .sparseBinding
= true,
352 .variableMultisampleRate
= true,
353 .shaderResourceMinLod
= true,
354 .inheritedQueries
= true,
359 libresoc_max_descriptor_set_size()
361 /* make sure that the entire descriptor set is addressable with a signed
362 * 32-bit int. So the sum of all limits scaled by descriptor size has to
363 * be at most 2 GiB. the combined image & samples object count as one of
364 * both. This limit is for the pipeline layout, not for the set layout, but
365 * there is no set limit, so we just set a pipeline limit. I don't think
366 * any app is going to hit this soon. */
367 return ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS
368 - MAX_INLINE_UNIFORM_BLOCK_SIZE
* MAX_INLINE_UNIFORM_BLOCK_COUNT
) /
369 (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
370 32 /* storage buffer, 32 due to potential space wasted on alignment */ +
371 32 /* sampler, largest when combined with image */ +
372 64 /* sampled image */ +
373 64 /* storage image */);
377 libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice
,
378 VkPhysicalDeviceProperties
*pProperties
)
380 if (getenv("LIBRESOC_TRACE")) {
381 fprintf(stderr
, "GetPhysicalDeviceProperties called. \n");
383 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
384 VkSampleCountFlags sample_counts
= 0xf;
386 size_t max_descriptor_set_size
= libresoc_max_descriptor_set_size();
388 VkPhysicalDeviceLimits limits
= {
389 .maxImageDimension1D
= (1 << 14),
390 .maxImageDimension2D
= (1 << 14),
391 .maxImageDimension3D
= (1 << 11),
392 .maxImageDimensionCube
= (1 << 14),
393 .maxImageArrayLayers
= (1 << 11),
394 .maxTexelBufferElements
= UINT32_MAX
,
395 .maxUniformBufferRange
= UINT32_MAX
,
396 .maxStorageBufferRange
= UINT32_MAX
,
397 .maxPushConstantsSize
= MAX_PUSH_CONSTANTS_SIZE
,
398 .maxMemoryAllocationCount
= UINT32_MAX
,
399 .maxSamplerAllocationCount
= 64 * 1024,
400 .bufferImageGranularity
= 64, /* A cache line */
401 .sparseAddressSpaceSize
= LIBRESOC_MAX_MEMORY_ALLOCATION_SIZE
, /* buffer max size */
402 .maxBoundDescriptorSets
= MAX_SETS
,
403 .maxPerStageDescriptorSamplers
= max_descriptor_set_size
,
404 .maxPerStageDescriptorUniformBuffers
= max_descriptor_set_size
,
405 .maxPerStageDescriptorStorageBuffers
= max_descriptor_set_size
,
406 .maxPerStageDescriptorSampledImages
= max_descriptor_set_size
,
407 .maxPerStageDescriptorStorageImages
= max_descriptor_set_size
,
408 .maxPerStageDescriptorInputAttachments
= max_descriptor_set_size
,
409 .maxPerStageResources
= max_descriptor_set_size
,
410 .maxDescriptorSetSamplers
= max_descriptor_set_size
,
411 .maxDescriptorSetUniformBuffers
= max_descriptor_set_size
,
412 .maxDescriptorSetUniformBuffersDynamic
= MAX_DYNAMIC_UNIFORM_BUFFERS
,
413 .maxDescriptorSetStorageBuffers
= max_descriptor_set_size
,
414 .maxDescriptorSetStorageBuffersDynamic
= MAX_DYNAMIC_STORAGE_BUFFERS
,
415 .maxDescriptorSetSampledImages
= max_descriptor_set_size
,
416 .maxDescriptorSetStorageImages
= max_descriptor_set_size
,
417 .maxDescriptorSetInputAttachments
= max_descriptor_set_size
,
418 .maxVertexInputAttributes
= MAX_VERTEX_ATTRIBS
,
419 .maxVertexInputBindings
= MAX_VBS
,
420 .maxVertexInputAttributeOffset
= 2047,
421 .maxVertexInputBindingStride
= 2048,
422 .maxVertexOutputComponents
= 128,
423 .maxTessellationGenerationLevel
= 64,
424 .maxTessellationPatchSize
= 32,
425 .maxTessellationControlPerVertexInputComponents
= 128,
426 .maxTessellationControlPerVertexOutputComponents
= 128,
427 .maxTessellationControlPerPatchOutputComponents
= 120,
428 .maxTessellationControlTotalOutputComponents
= 4096,
429 .maxTessellationEvaluationInputComponents
= 128,
430 .maxTessellationEvaluationOutputComponents
= 128,
431 .maxGeometryShaderInvocations
= 127,
432 .maxGeometryInputComponents
= 64,
433 .maxGeometryOutputComponents
= 128,
434 .maxGeometryOutputVertices
= 256,
435 .maxGeometryTotalOutputComponents
= 1024,
436 .maxFragmentInputComponents
= 128,
437 .maxFragmentOutputAttachments
= 8,
438 .maxFragmentDualSrcAttachments
= 1,
439 .maxFragmentCombinedOutputResources
= 8,
440 .maxComputeSharedMemorySize
= 32768,
441 .maxComputeWorkGroupCount
= { 65535, 65535, 65535 },
442 .maxComputeWorkGroupInvocations
= 1024,
443 .maxComputeWorkGroupSize
= {
448 .subPixelPrecisionBits
= 8,
449 .subTexelPrecisionBits
= 8,
450 .mipmapPrecisionBits
= 8,
451 .maxDrawIndexedIndexValue
= UINT32_MAX
,
452 .maxDrawIndirectCount
= UINT32_MAX
,
453 .maxSamplerLodBias
= 16,
454 .maxSamplerAnisotropy
= 16,
455 .maxViewports
= MAX_VIEWPORTS
,
456 .maxViewportDimensions
= { (1 << 14), (1 << 14) },
457 .viewportBoundsRange
= { INT16_MIN
, INT16_MAX
},
458 .viewportSubPixelBits
= 8,
459 .minMemoryMapAlignment
= 4096, /* A page */
460 .minTexelBufferOffsetAlignment
= 4,
461 .minUniformBufferOffsetAlignment
= 4,
462 .minStorageBufferOffsetAlignment
= 4,
463 .minTexelOffset
= -32,
464 .maxTexelOffset
= 31,
465 .minTexelGatherOffset
= -32,
466 .maxTexelGatherOffset
= 31,
467 .minInterpolationOffset
= -2,
468 .maxInterpolationOffset
= 2,
469 .subPixelInterpolationOffsetBits
= 8,
470 .maxFramebufferWidth
= (1 << 14),
471 .maxFramebufferHeight
= (1 << 14),
472 .maxFramebufferLayers
= (1 << 10),
473 .framebufferColorSampleCounts
= sample_counts
,
474 .framebufferDepthSampleCounts
= sample_counts
,
475 .framebufferStencilSampleCounts
= sample_counts
,
476 .framebufferNoAttachmentsSampleCounts
= sample_counts
,
477 .maxColorAttachments
= MAX_RTS
,
478 .sampledImageColorSampleCounts
= sample_counts
,
479 .sampledImageIntegerSampleCounts
= sample_counts
,
480 .sampledImageDepthSampleCounts
= sample_counts
,
481 .sampledImageStencilSampleCounts
= sample_counts
,
482 .storageImageSampleCounts
= sample_counts
,
483 .maxSampleMaskWords
= 1,
484 .timestampComputeAndGraphics
= true,
485 .timestampPeriod
= 1000000.0 /* FIXME /pdevice->rad_info.clock_crystal_freq*/,
486 .maxClipDistances
= 8,
487 .maxCullDistances
= 8,
488 .maxCombinedClipAndCullDistances
= 8,
489 .discreteQueuePriorities
= 2,
490 .pointSizeRange
= { 0.0, 8191.875 },
491 .lineWidthRange
= { 0.0, 8191.875 },
492 .pointSizeGranularity
= (1.0 / 8.0),
493 .lineWidthGranularity
= (1.0 / 8.0),
494 .strictLines
= false, /* FINISHME */
495 .standardSampleLocations
= true,
496 .optimalBufferCopyOffsetAlignment
= 128,
497 .optimalBufferCopyRowPitchAlignment
= 128,
498 .nonCoherentAtomSize
= 64,
501 *pProperties
= (VkPhysicalDeviceProperties
) {
502 .apiVersion
= libresoc_physical_device_api_version(pdevice
),
503 .driverVersion
= vk_get_driver_version(),
504 .vendorID
= 1, //TODO: some dummy value
505 .deviceID
= 1, //TODO: dome dummay value
506 .deviceType
= VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
,
508 .sparseProperties
= {0},
511 strcpy(pProperties
->deviceName
, pdevice
->name
);
512 memcpy(pProperties
->pipelineCacheUUID
, pdevice
->cache_uuid
, VK_UUID_SIZE
);
515 static void libresoc_get_physical_device_queue_family_properties(
516 struct libresoc_physical_device
* pdevice
,
518 VkQueueFamilyProperties
** pQueueFamilyProperties
)
520 int num_queue_families
= 1;
523 if (pQueueFamilyProperties
== NULL
) {
524 *pCount
= num_queue_families
;
533 *pQueueFamilyProperties
[idx
] = (VkQueueFamilyProperties
) {
534 .queueFlags
= VK_QUEUE_GRAPHICS_BIT
|
535 VK_QUEUE_COMPUTE_BIT
|
536 VK_QUEUE_TRANSFER_BIT
|
537 VK_QUEUE_SPARSE_BINDING_BIT
,
539 .timestampValidBits
= 64,
540 .minImageTransferGranularity
= (VkExtent3D
) { 1, 1, 1 },
549 libresoc_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice
,
551 VkQueueFamilyProperties
*pQueueFamilyProperties
)
553 if (getenv("LIBRESOC_TRACE")) {
554 fprintf(stderr
, "GetPhysicalDeviceQueueFamilyProperites called. \n");
556 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
557 if (!pQueueFamilyProperties
) {
558 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, NULL
);
561 VkQueueFamilyProperties
*properties
[] = {
562 pQueueFamilyProperties
+ 0,
563 pQueueFamilyProperties
+ 1,
564 pQueueFamilyProperties
+ 2,
566 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, properties
);
567 assert(*pCount
<= 3);
571 libresoc_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice
,
572 VkPhysicalDeviceMemoryProperties
*pMemoryProperties
)
574 if (getenv("LIBRESOC_TRACE")) {
575 fprintf(stderr
, "GetPhysicalDEviceMemoryProperties called. \n");
581 libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice
, VkFormat format
, VkFormatProperties
*pFormatProperties
) {
583 if (getenv("LIBRESOC_TRACE")) {
584 fprintf(stderr
, "GetPhysicalDeviceFormatProperties called. \n");
590 libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice
, VkFormat format
, VkImageType type
, VkImageTiling tiling
, VkImageUsageFlags usage
, VkImageCreateFlags flags
, VkImageFormatProperties
* pImageFormatProperties
)
592 if (getenv("LIBRESOC_TRACE")) {
593 fprintf(stderr
, "GetPhysicalDEviceImageFormatProperties called. \n");
600 libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice
, VkFormat format
, VkImageType type
, VkSampleCountFlagBits samples
, VkImageUsageFlags usage
, VkImageTiling tiling
, uint32_t* pPropertyCount
, VkSparseImageFormatProperties
* pProperties
)
602 if (getenv("LIBRESOC_TRACE")) {
603 fprintf(stderr
, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
608 libresoc_GetInstanceProcAddr(VkInstance _instance
,
611 if (getenv("LIBRESOC_TRACE")) {
612 fprintf(stderr
, "GetInstanceProcAddr called for: %s \n", pName
);
614 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
616 /* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly
617 * when we have to return valid function pointers, NULL, or it's left
618 * undefined. See the table for exact details.
623 #define LOOKUP_LIBRESOC_ENTRYPOINT(entrypoint) \
624 if (strcmp(pName, "vk" #entrypoint) == 0) \
625 return (PFN_vkVoidFunction)libresoc_##entrypoint
627 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateInstanceExtensionProperties
);
628 LOOKUP_LIBRESOC_ENTRYPOINT(CreateInstance
);
629 LOOKUP_LIBRESOC_ENTRYPOINT(DestroyInstance
);
630 LOOKUP_LIBRESOC_ENTRYPOINT(EnumeratePhysicalDevices
);
631 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFeatures
);
632 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFormatProperties
);
633 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceImageFormatProperties
);
634 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceProperties
);
635 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceQueueFamilyProperties
);
636 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceMemoryProperties
);
637 LOOKUP_LIBRESOC_ENTRYPOINT(GetDeviceProcAddr
);
638 LOOKUP_LIBRESOC_ENTRYPOINT(CreateDevice
);
639 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateDeviceExtensionProperties
);
640 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceSparseImageFormatProperties
);
643 #undef LOOKUP_LIBRESOC_ENTRYPOINT
645 if (instance
== NULL
)
648 int idx
= libresoc_get_instance_entrypoint_index(pName
);
650 return instance
->dispatch
.entrypoints
[idx
];
652 idx
= libresoc_get_physical_device_entrypoint_index(pName
);
654 return instance
->physical_device_dispatch
.entrypoints
[idx
];
656 idx
= libresoc_get_device_entrypoint_index(pName
);
658 return instance
->device_dispatch
.entrypoints
[idx
];
663 /* With version 1+ of the loader interface the ICD should expose
664 * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
667 VKAPI_ATTR PFN_vkVoidFunction
668 VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance
,
672 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
673 vk_icdGetInstanceProcAddr(VkInstance instance
,
676 if (getenv("LIBRESOC_TRACE")) {
677 fprintf(stderr
, "vk_icdGetInstanceProcAddr called for: %s \n", pName
);
679 return libresoc_GetInstanceProcAddr(instance
, pName
);
683 libresoc_GetDeviceProcAddr(VkDevice _device
,
686 if (getenv("LIBRESOC_TRACE")) {
687 fprintf(stderr
, "GetDeviceProcAddr called for: %s \n", pName
);
689 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
691 if (!device
|| !pName
)
694 int idx
= libresoc_get_device_entrypoint_index(pName
);
698 return device
->dispatch
.entrypoints
[idx
];
701 /* With version 4+ of the loader interface the ICD should expose
702 * vk_icdGetPhysicalDeviceProcAddr()
705 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
706 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
710 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
713 if (getenv("LIBRESOC_TRACE")) {
714 fprintf(stderr
, "vk_icdGetPhysicalDeviceProcAddr called for: %s \n", pName
);
716 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
718 if (!pName
|| !instance
)
721 int idx
= libresoc_get_physical_device_entrypoint_index(pName
);
725 return instance
->physical_device_dispatch
.entrypoints
[idx
];
729 libresoc_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice
,
730 const char *pLayerName
,
731 uint32_t *pPropertyCount
,
732 VkExtensionProperties
*pProperties
)
734 if (getenv("LIBRESOC_TRACE")) {
735 fprintf(stderr
, "EnumerateDeviceExtensionProperties called for layer: %s \n", pLayerName
);
737 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, device
, physicalDevice
);
738 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
740 for (int i
= 0; i
< LIBRESOC_DEVICE_EXTENSION_COUNT
; i
++) {
741 if (device
->supported_extensions
.extensions
[i
]) {
742 vk_outarray_append(&out
, prop
) {
743 *prop
= libresoc_device_extensions
[i
];
748 return vk_outarray_status(&out
);
752 libresoc_device_init_dispatch(struct libresoc_device
*device
)
754 const struct libresoc_instance
*instance
= device
->physical_device
->instance
;
755 const struct libresoc_device_dispatch_table
*dispatch_table_layer
= NULL
;
757 for (unsigned i
= 0; i
< ARRAY_SIZE(device
->dispatch
.entrypoints
); i
++) {
758 /* Vulkan requires that entrypoints for extensions which have not been
759 * enabled must not be advertised.
761 if (!libresoc_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
762 &instance
->enabled_extensions
,
763 &device
->enabled_extensions
)) {
764 device
->dispatch
.entrypoints
[i
] = NULL
;
765 } else if (dispatch_table_layer
&&
766 dispatch_table_layer
->entrypoints
[i
]) {
767 device
->dispatch
.entrypoints
[i
] =
768 dispatch_table_layer
->entrypoints
[i
];
770 device
->dispatch
.entrypoints
[i
] =
771 libresoc_device_dispatch_table
.entrypoints
[i
];
778 libresoc_create_pthread_cond(pthread_cond_t *cond)
780 pthread_condattr_t condattr;
781 if (pthread_condattr_init(&condattr)) {
782 return VK_ERROR_INITIALIZATION_FAILED;
785 if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
786 pthread_condattr_destroy(&condattr);
787 return VK_ERROR_INITIALIZATION_FAILED;
789 if (pthread_cond_init(cond, &condattr)) {
790 pthread_condattr_destroy(&condattr);
791 return VK_ERROR_INITIALIZATION_FAILED;
793 pthread_condattr_destroy(&condattr);
798 check_physical_device_features(VkPhysicalDevice physicalDevice
,
799 const VkPhysicalDeviceFeatures
*features
)
801 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
802 VkPhysicalDeviceFeatures supported_features
;
803 libresoc_GetPhysicalDeviceFeatures(physicalDevice
, &supported_features
);
804 VkBool32
*supported_feature
= (VkBool32
*)&supported_features
;
805 VkBool32
*enabled_feature
= (VkBool32
*)features
;
806 unsigned num_features
= sizeof(VkPhysicalDeviceFeatures
) / sizeof(VkBool32
);
807 for (uint32_t i
= 0; i
< num_features
; i
++) {
808 if (enabled_feature
[i
] && !supported_feature
[i
])
809 return vk_error(physical_device
->instance
, VK_ERROR_FEATURE_NOT_PRESENT
);
814 static int libresoc_get_device_extension_index(const char *name
)
816 for (unsigned i
= 0; i
< LIBRESOC_DEVICE_EXTENSION_COUNT
; ++i
) {
817 if (strcmp(name
, libresoc_device_extensions
[i
].extensionName
) == 0)
824 libresoc_queue_init(struct libresoc_device
*device
, struct libresoc_queue
*queue
,
825 uint32_t queue_family_index
, int idx
,
826 VkDeviceQueueCreateFlags flags
,
827 const VkDeviceQueueGlobalPriorityCreateInfoEXT
*global_priority
)
829 queue
->_loader_data
.loaderMagic
= ICD_LOADER_MAGIC
;
830 queue
->device
= device
;
831 queue
->queue_family_index
= queue_family_index
;
832 queue
->queue_idx
= idx
;
833 queue
->flags
= flags
;
838 libresoc_queue_finish(struct libresoc_queue
*queue
)
840 //TODO: understand and enable following code
841 // if (queue->thread_running) {
842 // p_atomic_set(&queue->thread_exit, true);
843 // pthread_cond_broadcast(&queue->thread_cond);
844 // pthread_join(queue->submission_thread, NULL);
846 // pthread_cond_destroy(&queue->thread_cond);
847 // pthread_mutex_destroy(&queue->pending_mutex);
848 // pthread_mutex_destroy(&queue->thread_mutex);
850 // if (queue->hw_ctx)
851 // queue->device->ws->ctx_destroy(queue->hw_ctx);
853 // if (queue->initial_full_flush_preamble_cs)
854 // queue->device->ws->cs_destroy(queue->initial_full_flush_preamble_cs);
855 // if (queue->initial_preamble_cs)
856 // queue->device->ws->cs_destroy(queue->initial_preamble_cs);
857 // if (queue->continue_preamble_cs)
858 // queue->device->ws->cs_destroy(queue->continue_preamble_cs);
859 // if (queue->descriptor_bo)
860 // queue->device->ws->buffer_destroy(queue->descriptor_bo);
861 // if (queue->scratch_bo)
862 // queue->device->ws->buffer_destroy(queue->scratch_bo);
863 // if (queue->esgs_ring_bo)
864 // queue->device->ws->buffer_destroy(queue->esgs_ring_bo);
865 // if (queue->gsvs_ring_bo)
866 // queue->device->ws->buffer_destroy(queue->gsvs_ring_bo);
867 // if (queue->tess_rings_bo)
868 // queue->device->ws->buffer_destroy(queue->tess_rings_bo);
869 // if (queue->gds_bo)
870 // queue->device->ws->buffer_destroy(queue->gds_bo);
871 // if (queue->gds_oa_bo)
872 // queue->device->ws->buffer_destroy(queue->gds_oa_bo);
873 // if (queue->compute_scratch_bo)
874 // queue->device->ws->buffer_destroy(queue->compute_scratch_bo);
877 libresoc_CreateDevice(VkPhysicalDevice physicalDevice
,
878 const VkDeviceCreateInfo
*pCreateInfo
,
879 const VkAllocationCallbacks
*pAllocator
,
882 if (getenv("LIBRESOC_TRACE")) {
883 fprintf(stderr
, "CreateDevice called \n");
885 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
887 struct libresoc_device
*device
;
889 /* Check enabled features */
890 if (pCreateInfo
->pEnabledFeatures
) {
891 result
= check_physical_device_features(physicalDevice
,
892 pCreateInfo
->pEnabledFeatures
);
893 if (result
!= VK_SUCCESS
)
897 device
= vk_zalloc2(&physical_device
->instance
->alloc
, pAllocator
,
899 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
901 return vk_error(physical_device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
903 vk_device_init(&device
->vk
, pCreateInfo
,
904 &physical_device
->instance
->alloc
, pAllocator
);
906 device
->instance
= physical_device
->instance
;
907 device
->physical_device
= physical_device
;
909 for (uint32_t i
= 0; i
< pCreateInfo
->enabledExtensionCount
; i
++) {
910 const char *ext_name
= pCreateInfo
->ppEnabledExtensionNames
[i
];
911 int index
= libresoc_get_device_extension_index(ext_name
);
912 if (index
< 0 || !physical_device
->supported_extensions
.extensions
[index
]) {
913 vk_free(&device
->vk
.alloc
, device
);
914 return vk_error(physical_device
->instance
, VK_ERROR_EXTENSION_NOT_PRESENT
);
917 device
->enabled_extensions
.extensions
[index
] = true;
920 libresoc_device_init_dispatch(device
);
922 for (unsigned i
= 0; i
< pCreateInfo
->queueCreateInfoCount
; i
++) {
923 const VkDeviceQueueCreateInfo
*queue_create
= &pCreateInfo
->pQueueCreateInfos
[i
];
924 uint32_t qfi
= queue_create
->queueFamilyIndex
;
925 const VkDeviceQueueGlobalPriorityCreateInfoEXT
*global_priority
=
926 vk_find_struct_const(queue_create
->pNext
, DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT
);
929 device
->queues
[qfi
] = vk_alloc(&device
->vk
.alloc
,
930 queue_create
->queueCount
* sizeof(struct libresoc_queue
), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
931 if (!device
->queues
[qfi
]) {
932 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
936 memset(device
->queues
[qfi
], 0, queue_create
->queueCount
* sizeof(struct libresoc_queue
));
938 device
->queue_count
[qfi
] = queue_create
->queueCount
;
940 for (unsigned q
= 0; q
< queue_create
->queueCount
; q
++) {
941 result
= libresoc_queue_init(device
, &device
->queues
[qfi
][q
],
942 qfi
, q
, queue_create
->flags
,
944 if (result
!= VK_SUCCESS
)
949 if (result
!= VK_SUCCESS
)
952 VkPipelineCacheCreateInfo ci
;
953 ci
.sType
= VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
;
956 ci
.pInitialData
= NULL
;
957 ci
.initialDataSize
= 0;
959 result
= libresoc_CreatePipelineCache(libresoc_device_to_handle(device
),
961 if (result
!= VK_SUCCESS
)
964 *pDevice
= libresoc_device_to_handle(device
);
968 libresoc_DestroyPipelineCache(libresoc_device_to_handle(device
), pc
, NULL
);
969 for (unsigned i
= 0; i
< LIBRESOC_MAX_QUEUE_FAMILIES
; i
++) {
970 for (unsigned q
= 0; q
< device
->queue_count
[i
]; q
++)
971 libresoc_queue_finish(&device
->queues
[i
][q
]);
972 if (device
->queue_count
[i
])
973 vk_free(&device
->vk
.alloc
, device
->queues
[i
]);
976 vk_free(&device
->vk
.alloc
, device
);
981 libresoc_DestroyDevice(VkDevice _device
,
982 const VkAllocationCallbacks
*pAllocator
)
984 if (getenv("LIBRESOC_TRACE")) {
985 fprintf(stderr
, "DestroyDevice called. \n");
990 void libresoc_GetDeviceQueue(
992 uint32_t queueFamilyIndex
,
996 if (getenv("LIBRESOC_TRACE")) {
997 fprintf(stderr
, "GetDeviceQueue called. \n");
999 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1000 struct libresoc_queue
*queue
;
1002 queue
= &device
->queues
[queueFamilyIndex
][queueIndex
];
1003 *pQueue
= libresoc_queue_to_handle(queue
);
1006 VkResult
libresoc_QueueWaitIdle(
1009 LIBRESOC_FROM_HANDLE(libresoc_queue
, queue
, _queue
);
1011 pthread_mutex_lock(&queue
->pending_mutex
);
1012 while (!list_is_empty(&queue
->pending_submissions
)) {
1013 pthread_cond_wait(&queue
->device
->timeline_cond
, &queue
->pending_mutex
);
1015 pthread_mutex_unlock(&queue
->pending_mutex
);
1020 VkResult
libresoc_DeviceWaitIdle(
1023 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
1025 for (unsigned i
= 0; i
< LIBRESOC_MAX_QUEUE_FAMILIES
; i
++) {
1026 for (unsigned q
= 0; q
< device
->queue_count
[i
]; q
++) {
1028 libresoc_QueueWaitIdle(libresoc_queue_to_handle(&device
->queues
[i
][q
]));
1030 if (result
!= VK_SUCCESS
)