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 "libresoc_private.h"
36 libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName
,
37 uint32_t *pPropertyCount
,
38 VkExtensionProperties
*pProperties
)
40 if (getenv("LIBRESOC_TRACE")) {
41 fprintf(stderr
, "EnumerateInstanceExtensionProperties called for: %s \n", pLayerName
);
43 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
45 for (int i
= 0; i
< LIBRESOC_INSTANCE_EXTENSION_COUNT
; i
++) {
46 if (libresoc_instance_extensions_supported
.extensions
[i
]) {
47 vk_outarray_append(&out
, prop
) {
48 *prop
= libresoc_instance_extensions
[i
];
53 return vk_outarray_status(&out
);
57 default_alloc_func(void *pUserData
, size_t size
, size_t align
,
58 VkSystemAllocationScope allocationScope
)
64 default_realloc_func(void *pUserData
, void *pOriginal
, size_t size
,
65 size_t align
, VkSystemAllocationScope allocationScope
)
67 return realloc(pOriginal
, size
);
71 default_free_func(void *pUserData
, void *pMemory
)
76 static const VkAllocationCallbacks default_alloc
= {
78 .pfnAllocation
= default_alloc_func
,
79 .pfnReallocation
= default_realloc_func
,
80 .pfnFree
= default_free_func
,
84 libresoc_CreateInstance(const VkInstanceCreateInfo
*pCreateInfo
,
85 const VkAllocationCallbacks
*pAllocator
,
86 VkInstance
*pInstance
)
88 if (getenv("LIBRESOC_TRACE")) {
89 fprintf(stderr
, "CreateInstance called. \n");
91 struct libresoc_instance
*instance
;
93 instance
= vk_zalloc2(&default_alloc
, pAllocator
, sizeof(*instance
), 8,
94 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
96 return vk_error(NULL
, VK_ERROR_OUT_OF_HOST_MEMORY
);
98 vk_object_base_init(NULL
, &instance
->base
, VK_OBJECT_TYPE_INSTANCE
);
101 instance
->alloc
= *pAllocator
;
103 instance
->alloc
= default_alloc
;
104 if (pCreateInfo
->pApplicationInfo
) {
105 const VkApplicationInfo
*app
= pCreateInfo
->pApplicationInfo
;
107 instance
->engineName
=
108 vk_strdup(&instance
->alloc
, app
->pEngineName
,
109 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
110 instance
->engineVersion
= app
->engineVersion
;
111 instance
->apiVersion
= app
->apiVersion
;
113 /*TODO : enable extensions*/
114 for (uint32_t i
= 0; i
< pCreateInfo
->enabledExtensionCount
; i
++) {
116 for (idx
= 0; idx
< LIBRESOC_INSTANCE_EXTENSION_COUNT
; idx
++) {
117 if (!strcmp(pCreateInfo
->ppEnabledExtensionNames
[i
],
118 libresoc_instance_extensions
[idx
].extensionName
))
122 if (idx
>= LIBRESOC_INSTANCE_EXTENSION_COUNT
||
123 !libresoc_instance_extensions_supported
.extensions
[idx
]) {
124 vk_object_base_finish(&instance
->base
);
125 vk_free2(&default_alloc
, pAllocator
, instance
);
126 return vk_error(instance
, VK_ERROR_EXTENSION_NOT_PRESENT
);
129 instance
->enabled_extensions
.extensions
[idx
] = true;
131 for (unsigned i
= 0; i
< ARRAY_SIZE(instance
->dispatch
.entrypoints
); i
++) {
132 /* Vulkan requires that entrypoints for extensions which have
133 * not been enabled must not be advertised.
135 if (!libresoc_instance_entrypoint_is_enabled(i
, instance
->apiVersion
,
136 &instance
->enabled_extensions
)) {
137 instance
->dispatch
.entrypoints
[i
] = NULL
;
139 instance
->dispatch
.entrypoints
[i
] =
140 libresoc_instance_dispatch_table
.entrypoints
[i
];
143 for (unsigned i
= 0; i
< ARRAY_SIZE(instance
->physical_device_dispatch
.entrypoints
); i
++) {
144 /* Vulkan requires that entrypoints for extensions which have
145 * not been enabled must not be advertised.
147 if (!libresoc_physical_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
148 &instance
->enabled_extensions
)) {
149 instance
->physical_device_dispatch
.entrypoints
[i
] = NULL
;
151 instance
->physical_device_dispatch
.entrypoints
[i
] =
152 libresoc_physical_device_dispatch_table
.entrypoints
[i
];
156 for (unsigned i
= 0; i
< ARRAY_SIZE(instance
->device_dispatch
.entrypoints
); i
++) {
157 /* Vulkan requires that entrypoints for extensions which have
158 * not been enabled must not be advertised.
160 if (!libresoc_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
161 &instance
->enabled_extensions
, NULL
)) {
162 instance
->device_dispatch
.entrypoints
[i
] = NULL
;
164 instance
->device_dispatch
.entrypoints
[i
] =
165 libresoc_device_dispatch_table
.entrypoints
[i
];
168 instance
->physical_devices_enumerated
= false;
169 list_inithead(&instance
->physical_devices
);
170 *pInstance
= libresoc_instance_to_handle(instance
);
176 libresoc_DestroyInstance(VkInstance _instance
,
177 const VkAllocationCallbacks
*pAllocator
)
179 if (getenv("LIBRESOC_TRACE")) {
180 fprintf(stderr
, "DestroyInstance called. \n");
186 libresoc_physical_device_try_create(struct libresoc_instance
*instance
,
187 struct libresoc_physical_device
**device_out
)
191 struct libresoc_physical_device
*device
=
192 vk_zalloc2(&instance
->alloc
, NULL
, sizeof(*device
), 8,
193 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE
);
195 result
= vk_error(instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
199 device
->_loader_data
.loaderMagic
= ICD_LOADER_MAGIC
;
200 device
->instance
= instance
;
202 snprintf(device
->name
, sizeof(device
->name
),
204 *device_out
= device
;
210 libresoc_enumerate_physical_devices(struct libresoc_instance
*instance
)
213 if (instance
->physical_devices_enumerated
)
216 instance
->physical_devices_enumerated
= true;
217 VkResult result
= VK_SUCCESS
;
218 /* the driver creates a null
219 * device that allows to test the compiler without having a physical device
221 struct libresoc_physical_device
*pdevice
;
223 result
= libresoc_physical_device_try_create(instance
, &pdevice
);
224 if (result
!= VK_SUCCESS
)
227 list_addtail(&pdevice
->link
, &instance
->physical_devices
);
233 libresoc_EnumeratePhysicalDevices(VkInstance _instance
,
234 uint32_t *pPhysicalDeviceCount
,
235 VkPhysicalDevice
*pPhysicalDevices
)
237 if (getenv("LIBRESOC_TRACE")) {
238 fprintf(stderr
, "EnumeratePhysicalDevices called\n");
240 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
241 VK_OUTARRAY_MAKE(out
, pPhysicalDevices
, pPhysicalDeviceCount
);
243 VkResult result
= libresoc_enumerate_physical_devices(instance
);
244 if (result
!= VK_SUCCESS
)
247 list_for_each_entry(struct libresoc_physical_device
, pdevice
,
248 &instance
->physical_devices
, link
) {
249 vk_outarray_append(&out
, i
) {
250 *i
= libresoc_physical_device_to_handle(pdevice
);
254 return vk_outarray_status(&out
);
258 libresoc_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice
,
259 VkPhysicalDeviceFeatures
*pFeatures
)
261 if (getenv("LIBRESOC_TRACE")) {
262 fprintf(stderr
, "GetPhysicalDeviceFeatures called. \n");
264 //LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
265 memset(pFeatures
, 0, sizeof(*pFeatures
));
267 *pFeatures
= (VkPhysicalDeviceFeatures
) {
268 .robustBufferAccess
= true,
269 .fullDrawIndexUint32
= true,
270 .imageCubeArray
= true,
271 .independentBlend
= true,
272 .geometryShader
= true,
273 .tessellationShader
= true,
274 .sampleRateShading
= true,
275 .dualSrcBlend
= true,
277 .multiDrawIndirect
= true,
278 .drawIndirectFirstInstance
= true,
280 .depthBiasClamp
= true,
281 .fillModeNonSolid
= true,
286 .multiViewport
= true,
287 .samplerAnisotropy
= true,
288 .textureCompressionETC2
= false,
289 .textureCompressionASTC_LDR
= false,
290 .textureCompressionBC
= true,
291 .occlusionQueryPrecise
= true,
292 .pipelineStatisticsQuery
= true,
293 .vertexPipelineStoresAndAtomics
= true,
294 .fragmentStoresAndAtomics
= true,
295 .shaderTessellationAndGeometryPointSize
= true,
296 .shaderImageGatherExtended
= true,
297 .shaderStorageImageExtendedFormats
= true,
298 .shaderStorageImageMultisample
= true,
299 .shaderUniformBufferArrayDynamicIndexing
= true,
300 .shaderSampledImageArrayDynamicIndexing
= true,
301 .shaderStorageBufferArrayDynamicIndexing
= true,
302 .shaderStorageImageArrayDynamicIndexing
= true,
303 .shaderStorageImageReadWithoutFormat
= true,
304 .shaderStorageImageWriteWithoutFormat
= true,
305 .shaderClipDistance
= true,
306 .shaderCullDistance
= true,
307 .shaderFloat64
= true,
310 .sparseBinding
= true,
311 .variableMultisampleRate
= true,
312 .shaderResourceMinLod
= true,
313 .inheritedQueries
= true,
318 libresoc_max_descriptor_set_size()
320 /* make sure that the entire descriptor set is addressable with a signed
321 * 32-bit int. So the sum of all limits scaled by descriptor size has to
322 * be at most 2 GiB. the combined image & samples object count as one of
323 * both. This limit is for the pipeline layout, not for the set layout, but
324 * there is no set limit, so we just set a pipeline limit. I don't think
325 * any app is going to hit this soon. */
326 return ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS
327 - MAX_INLINE_UNIFORM_BLOCK_SIZE
* MAX_INLINE_UNIFORM_BLOCK_COUNT
) /
328 (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
329 32 /* storage buffer, 32 due to potential space wasted on alignment */ +
330 32 /* sampler, largest when combined with image */ +
331 64 /* sampled image */ +
332 64 /* storage image */);
336 libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice
,
337 VkPhysicalDeviceProperties
*pProperties
)
339 if (getenv("LIBRESOC_TRACE")) {
340 fprintf(stderr
, "GetPhysicalDeviceProperties called. \n");
342 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
343 VkSampleCountFlags sample_counts
= 0xf;
345 size_t max_descriptor_set_size
= libresoc_max_descriptor_set_size();
347 VkPhysicalDeviceLimits limits
= {
348 .maxImageDimension1D
= (1 << 14),
349 .maxImageDimension2D
= (1 << 14),
350 .maxImageDimension3D
= (1 << 11),
351 .maxImageDimensionCube
= (1 << 14),
352 .maxImageArrayLayers
= (1 << 11),
353 .maxTexelBufferElements
= UINT32_MAX
,
354 .maxUniformBufferRange
= UINT32_MAX
,
355 .maxStorageBufferRange
= UINT32_MAX
,
356 .maxPushConstantsSize
= MAX_PUSH_CONSTANTS_SIZE
,
357 .maxMemoryAllocationCount
= UINT32_MAX
,
358 .maxSamplerAllocationCount
= 64 * 1024,
359 .bufferImageGranularity
= 64, /* A cache line */
360 .sparseAddressSpaceSize
= LIBRESOC_MAX_MEMORY_ALLOCATION_SIZE
, /* buffer max size */
361 .maxBoundDescriptorSets
= MAX_SETS
,
362 .maxPerStageDescriptorSamplers
= max_descriptor_set_size
,
363 .maxPerStageDescriptorUniformBuffers
= max_descriptor_set_size
,
364 .maxPerStageDescriptorStorageBuffers
= max_descriptor_set_size
,
365 .maxPerStageDescriptorSampledImages
= max_descriptor_set_size
,
366 .maxPerStageDescriptorStorageImages
= max_descriptor_set_size
,
367 .maxPerStageDescriptorInputAttachments
= max_descriptor_set_size
,
368 .maxPerStageResources
= max_descriptor_set_size
,
369 .maxDescriptorSetSamplers
= max_descriptor_set_size
,
370 .maxDescriptorSetUniformBuffers
= max_descriptor_set_size
,
371 .maxDescriptorSetUniformBuffersDynamic
= MAX_DYNAMIC_UNIFORM_BUFFERS
,
372 .maxDescriptorSetStorageBuffers
= max_descriptor_set_size
,
373 .maxDescriptorSetStorageBuffersDynamic
= MAX_DYNAMIC_STORAGE_BUFFERS
,
374 .maxDescriptorSetSampledImages
= max_descriptor_set_size
,
375 .maxDescriptorSetStorageImages
= max_descriptor_set_size
,
376 .maxDescriptorSetInputAttachments
= max_descriptor_set_size
,
377 .maxVertexInputAttributes
= MAX_VERTEX_ATTRIBS
,
378 .maxVertexInputBindings
= MAX_VBS
,
379 .maxVertexInputAttributeOffset
= 2047,
380 .maxVertexInputBindingStride
= 2048,
381 .maxVertexOutputComponents
= 128,
382 .maxTessellationGenerationLevel
= 64,
383 .maxTessellationPatchSize
= 32,
384 .maxTessellationControlPerVertexInputComponents
= 128,
385 .maxTessellationControlPerVertexOutputComponents
= 128,
386 .maxTessellationControlPerPatchOutputComponents
= 120,
387 .maxTessellationControlTotalOutputComponents
= 4096,
388 .maxTessellationEvaluationInputComponents
= 128,
389 .maxTessellationEvaluationOutputComponents
= 128,
390 .maxGeometryShaderInvocations
= 127,
391 .maxGeometryInputComponents
= 64,
392 .maxGeometryOutputComponents
= 128,
393 .maxGeometryOutputVertices
= 256,
394 .maxGeometryTotalOutputComponents
= 1024,
395 .maxFragmentInputComponents
= 128,
396 .maxFragmentOutputAttachments
= 8,
397 .maxFragmentDualSrcAttachments
= 1,
398 .maxFragmentCombinedOutputResources
= 8,
399 .maxComputeSharedMemorySize
= 32768,
400 .maxComputeWorkGroupCount
= { 65535, 65535, 65535 },
401 .maxComputeWorkGroupInvocations
= 1024,
402 .maxComputeWorkGroupSize
= {
407 .subPixelPrecisionBits
= 8,
408 .subTexelPrecisionBits
= 8,
409 .mipmapPrecisionBits
= 8,
410 .maxDrawIndexedIndexValue
= UINT32_MAX
,
411 .maxDrawIndirectCount
= UINT32_MAX
,
412 .maxSamplerLodBias
= 16,
413 .maxSamplerAnisotropy
= 16,
414 .maxViewports
= MAX_VIEWPORTS
,
415 .maxViewportDimensions
= { (1 << 14), (1 << 14) },
416 .viewportBoundsRange
= { INT16_MIN
, INT16_MAX
},
417 .viewportSubPixelBits
= 8,
418 .minMemoryMapAlignment
= 4096, /* A page */
419 .minTexelBufferOffsetAlignment
= 4,
420 .minUniformBufferOffsetAlignment
= 4,
421 .minStorageBufferOffsetAlignment
= 4,
422 .minTexelOffset
= -32,
423 .maxTexelOffset
= 31,
424 .minTexelGatherOffset
= -32,
425 .maxTexelGatherOffset
= 31,
426 .minInterpolationOffset
= -2,
427 .maxInterpolationOffset
= 2,
428 .subPixelInterpolationOffsetBits
= 8,
429 .maxFramebufferWidth
= (1 << 14),
430 .maxFramebufferHeight
= (1 << 14),
431 .maxFramebufferLayers
= (1 << 10),
432 .framebufferColorSampleCounts
= sample_counts
,
433 .framebufferDepthSampleCounts
= sample_counts
,
434 .framebufferStencilSampleCounts
= sample_counts
,
435 .framebufferNoAttachmentsSampleCounts
= sample_counts
,
436 .maxColorAttachments
= MAX_RTS
,
437 .sampledImageColorSampleCounts
= sample_counts
,
438 .sampledImageIntegerSampleCounts
= sample_counts
,
439 .sampledImageDepthSampleCounts
= sample_counts
,
440 .sampledImageStencilSampleCounts
= sample_counts
,
441 .storageImageSampleCounts
= sample_counts
,
442 .maxSampleMaskWords
= 1,
443 .timestampComputeAndGraphics
= true,
444 .timestampPeriod
= 1000000.0 /* FIXME /pdevice->rad_info.clock_crystal_freq*/,
445 .maxClipDistances
= 8,
446 .maxCullDistances
= 8,
447 .maxCombinedClipAndCullDistances
= 8,
448 .discreteQueuePriorities
= 2,
449 .pointSizeRange
= { 0.0, 8191.875 },
450 .lineWidthRange
= { 0.0, 8191.875 },
451 .pointSizeGranularity
= (1.0 / 8.0),
452 .lineWidthGranularity
= (1.0 / 8.0),
453 .strictLines
= false, /* FINISHME */
454 .standardSampleLocations
= true,
455 .optimalBufferCopyOffsetAlignment
= 128,
456 .optimalBufferCopyRowPitchAlignment
= 128,
457 .nonCoherentAtomSize
= 64,
460 *pProperties
= (VkPhysicalDeviceProperties
) {
461 .apiVersion
= libresoc_physical_device_api_version(pdevice
),
462 .driverVersion
= vk_get_driver_version(),
465 .deviceType
= VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
,
467 .sparseProperties
= {0},
470 strcpy(pProperties
->deviceName
, pdevice
->name
);
471 // memcpy(pProperties->pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
474 static void libresoc_get_physical_device_queue_family_properties(
475 struct libresoc_physical_device
* pdevice
,
477 VkQueueFamilyProperties
** pQueueFamilyProperties
)
479 int num_queue_families
= 1;
482 if (pQueueFamilyProperties
== NULL
) {
483 *pCount
= num_queue_families
;
492 *pQueueFamilyProperties
[idx
] = (VkQueueFamilyProperties
) {
493 .queueFlags
= VK_QUEUE_GRAPHICS_BIT
|
494 VK_QUEUE_COMPUTE_BIT
|
495 VK_QUEUE_TRANSFER_BIT
|
496 VK_QUEUE_SPARSE_BINDING_BIT
,
498 .timestampValidBits
= 64,
499 .minImageTransferGranularity
= (VkExtent3D
) { 1, 1, 1 },
508 libresoc_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice
,
510 VkQueueFamilyProperties
*pQueueFamilyProperties
)
512 if (getenv("LIBRESOC_TRACE")) {
513 fprintf(stderr
, "GetPhysicalDeviceQueueFamilyProperites called. \n");
515 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, pdevice
, physicalDevice
);
516 if (!pQueueFamilyProperties
) {
517 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, NULL
);
520 VkQueueFamilyProperties
*properties
[] = {
521 pQueueFamilyProperties
+ 0,
522 pQueueFamilyProperties
+ 1,
523 pQueueFamilyProperties
+ 2,
525 libresoc_get_physical_device_queue_family_properties(pdevice
, pCount
, properties
);
526 assert(*pCount
<= 3);
530 libresoc_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice
,
531 VkPhysicalDeviceMemoryProperties
*pMemoryProperties
)
533 if (getenv("LIBRESOC_TRACE")) {
534 fprintf(stderr
, "GetPhysicalDEviceMemoryProperties called. \n");
540 libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice
, VkFormat format
, VkFormatProperties
*pFormatProperties
) {
542 if (getenv("LIBRESOC_TRACE")) {
543 fprintf(stderr
, "GetPhysicalDeviceFormatProperties called. \n");
549 libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice
, VkFormat format
, VkImageType type
, VkImageTiling tiling
, VkImageUsageFlags usage
, VkImageCreateFlags flags
, VkImageFormatProperties
* pImageFormatProperties
)
551 if (getenv("LIBRESOC_TRACE")) {
552 fprintf(stderr
, "GetPhysicalDEviceImageFormatProperties called. \n");
559 libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice
, VkFormat format
, VkImageType type
, VkSampleCountFlagBits samples
, VkImageUsageFlags usage
, VkImageTiling tiling
, uint32_t* pPropertyCount
, VkSparseImageFormatProperties
* pProperties
)
561 if (getenv("LIBRESOC_TRACE")) {
562 fprintf(stderr
, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
567 libresoc_GetInstanceProcAddr(VkInstance _instance
,
570 if (getenv("LIBRESOC_TRACE")) {
571 fprintf(stderr
, "GetInstanceProcAddr called for: %s \n", pName
);
573 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
575 /* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly
576 * when we have to return valid function pointers, NULL, or it's left
577 * undefined. See the table for exact details.
582 #define LOOKUP_LIBRESOC_ENTRYPOINT(entrypoint) \
583 if (strcmp(pName, "vk" #entrypoint) == 0) \
584 return (PFN_vkVoidFunction)libresoc_##entrypoint
586 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateInstanceExtensionProperties
);
587 LOOKUP_LIBRESOC_ENTRYPOINT(CreateInstance
);
588 LOOKUP_LIBRESOC_ENTRYPOINT(DestroyInstance
);
589 LOOKUP_LIBRESOC_ENTRYPOINT(EnumeratePhysicalDevices
);
590 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFeatures
);
591 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFormatProperties
);
592 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceImageFormatProperties
);
593 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceProperties
);
594 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceQueueFamilyProperties
);
595 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceMemoryProperties
);
596 LOOKUP_LIBRESOC_ENTRYPOINT(GetDeviceProcAddr
);
597 LOOKUP_LIBRESOC_ENTRYPOINT(CreateDevice
);
598 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateDeviceExtensionProperties
);
599 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceSparseImageFormatProperties
);
602 #undef LOOKUP_LIBRESOC_ENTRYPOINT
604 if (instance
== NULL
)
607 int idx
= libresoc_get_instance_entrypoint_index(pName
);
609 return instance
->dispatch
.entrypoints
[idx
];
611 idx
= libresoc_get_physical_device_entrypoint_index(pName
);
613 return instance
->physical_device_dispatch
.entrypoints
[idx
];
615 idx
= libresoc_get_device_entrypoint_index(pName
);
617 return instance
->device_dispatch
.entrypoints
[idx
];
622 /* With version 1+ of the loader interface the ICD should expose
623 * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
626 VKAPI_ATTR PFN_vkVoidFunction
627 VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance
,
631 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
632 vk_icdGetInstanceProcAddr(VkInstance instance
,
635 if (getenv("LIBRESOC_TRACE")) {
636 fprintf(stderr
, "vk_icdGetInstanceProcAddr called for: %s \n", pName
);
638 return libresoc_GetInstanceProcAddr(instance
, pName
);
642 libresoc_GetDeviceProcAddr(VkDevice _device
,
645 if (getenv("LIBRESOC_TRACE")) {
646 fprintf(stderr
, "GetDeviceProcAddr called for: %s \n", pName
);
648 LIBRESOC_FROM_HANDLE(libresoc_device
, device
, _device
);
650 if (!device
|| !pName
)
653 int idx
= libresoc_get_device_entrypoint_index(pName
);
657 return device
->dispatch
.entrypoints
[idx
];
660 /* With version 4+ of the loader interface the ICD should expose
661 * vk_icdGetPhysicalDeviceProcAddr()
664 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
665 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
669 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance
,
672 if (getenv("LIBRESOC_TRACE")) {
673 fprintf(stderr
, "vk_icdGetPhysicalDeviceProcAddr called for: %s \n", pName
);
675 LIBRESOC_FROM_HANDLE(libresoc_instance
, instance
, _instance
);
677 if (!pName
|| !instance
)
680 int idx
= libresoc_get_physical_device_entrypoint_index(pName
);
684 return instance
->physical_device_dispatch
.entrypoints
[idx
];
688 libresoc_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice
,
689 const char *pLayerName
,
690 uint32_t *pPropertyCount
,
691 VkExtensionProperties
*pProperties
)
693 if (getenv("LIBRESOC_TRACE")) {
694 fprintf(stderr
, "EnumerateDeviceExtensionProperties called for layer: %s \n", pLayerName
);
696 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, device
, physicalDevice
);
697 VK_OUTARRAY_MAKE(out
, pProperties
, pPropertyCount
);
699 for (int i
= 0; i
< LIBRESOC_DEVICE_EXTENSION_COUNT
; i
++) {
700 if (device
->supported_extensions
.extensions
[i
]) {
701 vk_outarray_append(&out
, prop
) {
702 *prop
= libresoc_device_extensions
[i
];
707 return vk_outarray_status(&out
);
711 libresoc_device_init_dispatch(struct libresoc_device
*device
)
713 const struct libresoc_instance
*instance
= device
->physical_device
->instance
;
714 const struct libresoc_device_dispatch_table
*dispatch_table_layer
= NULL
;
716 for (unsigned i
= 0; i
< ARRAY_SIZE(device
->dispatch
.entrypoints
); i
++) {
717 /* Vulkan requires that entrypoints for extensions which have not been
718 * enabled must not be advertised.
720 if (!libresoc_device_entrypoint_is_enabled(i
, instance
->apiVersion
,
721 &instance
->enabled_extensions
,
722 &device
->enabled_extensions
)) {
723 device
->dispatch
.entrypoints
[i
] = NULL
;
724 } else if (dispatch_table_layer
&&
725 dispatch_table_layer
->entrypoints
[i
]) {
726 device
->dispatch
.entrypoints
[i
] =
727 dispatch_table_layer
->entrypoints
[i
];
729 device
->dispatch
.entrypoints
[i
] =
730 libresoc_device_dispatch_table
.entrypoints
[i
];
737 libresoc_create_pthread_cond(pthread_cond_t *cond)
739 pthread_condattr_t condattr;
740 if (pthread_condattr_init(&condattr)) {
741 return VK_ERROR_INITIALIZATION_FAILED;
744 if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
745 pthread_condattr_destroy(&condattr);
746 return VK_ERROR_INITIALIZATION_FAILED;
748 if (pthread_cond_init(cond, &condattr)) {
749 pthread_condattr_destroy(&condattr);
750 return VK_ERROR_INITIALIZATION_FAILED;
752 pthread_condattr_destroy(&condattr);
757 check_physical_device_features(VkPhysicalDevice physicalDevice
,
758 const VkPhysicalDeviceFeatures
*features
)
760 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
761 VkPhysicalDeviceFeatures supported_features
;
762 libresoc_GetPhysicalDeviceFeatures(physicalDevice
, &supported_features
);
763 VkBool32
*supported_feature
= (VkBool32
*)&supported_features
;
764 VkBool32
*enabled_feature
= (VkBool32
*)features
;
765 unsigned num_features
= sizeof(VkPhysicalDeviceFeatures
) / sizeof(VkBool32
);
766 for (uint32_t i
= 0; i
< num_features
; i
++) {
767 if (enabled_feature
[i
] && !supported_feature
[i
])
768 return vk_error(physical_device
->instance
, VK_ERROR_FEATURE_NOT_PRESENT
);
773 static int libresoc_get_device_extension_index(const char *name
)
775 for (unsigned i
= 0; i
< LIBRESOC_DEVICE_EXTENSION_COUNT
; ++i
) {
776 if (strcmp(name
, libresoc_device_extensions
[i
].extensionName
) == 0)
783 libresoc_queue_init(struct libresoc_device
*device
, struct libresoc_queue
*queue
,
784 uint32_t queue_family_index
, int idx
,
785 VkDeviceQueueCreateFlags flags
,
786 const VkDeviceQueueGlobalPriorityCreateInfoEXT
*global_priority
)
788 queue
->_loader_data
.loaderMagic
= ICD_LOADER_MAGIC
;
789 queue
->device
= device
;
790 queue
->queue_family_index
= queue_family_index
;
791 queue
->queue_idx
= idx
;
792 queue
->flags
= flags
;
797 libresoc_queue_finish(struct libresoc_queue
*queue
)
799 //TODO: understand and enable following code
800 // if (queue->thread_running) {
801 // p_atomic_set(&queue->thread_exit, true);
802 // pthread_cond_broadcast(&queue->thread_cond);
803 // pthread_join(queue->submission_thread, NULL);
805 // pthread_cond_destroy(&queue->thread_cond);
806 // pthread_mutex_destroy(&queue->pending_mutex);
807 // pthread_mutex_destroy(&queue->thread_mutex);
809 // if (queue->hw_ctx)
810 // queue->device->ws->ctx_destroy(queue->hw_ctx);
812 // if (queue->initial_full_flush_preamble_cs)
813 // queue->device->ws->cs_destroy(queue->initial_full_flush_preamble_cs);
814 // if (queue->initial_preamble_cs)
815 // queue->device->ws->cs_destroy(queue->initial_preamble_cs);
816 // if (queue->continue_preamble_cs)
817 // queue->device->ws->cs_destroy(queue->continue_preamble_cs);
818 // if (queue->descriptor_bo)
819 // queue->device->ws->buffer_destroy(queue->descriptor_bo);
820 // if (queue->scratch_bo)
821 // queue->device->ws->buffer_destroy(queue->scratch_bo);
822 // if (queue->esgs_ring_bo)
823 // queue->device->ws->buffer_destroy(queue->esgs_ring_bo);
824 // if (queue->gsvs_ring_bo)
825 // queue->device->ws->buffer_destroy(queue->gsvs_ring_bo);
826 // if (queue->tess_rings_bo)
827 // queue->device->ws->buffer_destroy(queue->tess_rings_bo);
828 // if (queue->gds_bo)
829 // queue->device->ws->buffer_destroy(queue->gds_bo);
830 // if (queue->gds_oa_bo)
831 // queue->device->ws->buffer_destroy(queue->gds_oa_bo);
832 // if (queue->compute_scratch_bo)
833 // queue->device->ws->buffer_destroy(queue->compute_scratch_bo);
836 libresoc_CreateDevice(VkPhysicalDevice physicalDevice
,
837 const VkDeviceCreateInfo
*pCreateInfo
,
838 const VkAllocationCallbacks
*pAllocator
,
841 if (getenv("LIBRESOC_TRACE")) {
842 fprintf(stderr
, "CreateDevice called \n");
844 LIBRESOC_FROM_HANDLE(libresoc_physical_device
, physical_device
, physicalDevice
);
846 struct libresoc_device
*device
;
848 /* Check enabled features */
849 if (pCreateInfo
->pEnabledFeatures
) {
850 result
= check_physical_device_features(physicalDevice
,
851 pCreateInfo
->pEnabledFeatures
);
852 if (result
!= VK_SUCCESS
)
856 device
= vk_zalloc2(&physical_device
->instance
->alloc
, pAllocator
,
858 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
860 return vk_error(physical_device
->instance
, VK_ERROR_OUT_OF_HOST_MEMORY
);
862 vk_device_init(&device
->vk
, pCreateInfo
,
863 &physical_device
->instance
->alloc
, pAllocator
);
865 device
->instance
= physical_device
->instance
;
866 device
->physical_device
= physical_device
;
868 for (uint32_t i
= 0; i
< pCreateInfo
->enabledExtensionCount
; i
++) {
869 const char *ext_name
= pCreateInfo
->ppEnabledExtensionNames
[i
];
870 int index
= libresoc_get_device_extension_index(ext_name
);
871 if (index
< 0 || !physical_device
->supported_extensions
.extensions
[index
]) {
872 vk_free(&device
->vk
.alloc
, device
);
873 return vk_error(physical_device
->instance
, VK_ERROR_EXTENSION_NOT_PRESENT
);
876 device
->enabled_extensions
.extensions
[index
] = true;
879 libresoc_device_init_dispatch(device
);
881 for (unsigned i
= 0; i
< pCreateInfo
->queueCreateInfoCount
; i
++) {
882 const VkDeviceQueueCreateInfo
*queue_create
= &pCreateInfo
->pQueueCreateInfos
[i
];
883 uint32_t qfi
= queue_create
->queueFamilyIndex
;
884 const VkDeviceQueueGlobalPriorityCreateInfoEXT
*global_priority
=
885 vk_find_struct_const(queue_create
->pNext
, DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT
);
888 device
->queues
[qfi
] = vk_alloc(&device
->vk
.alloc
,
889 queue_create
->queueCount
* sizeof(struct libresoc_queue
), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE
);
890 if (!device
->queues
[qfi
]) {
891 result
= VK_ERROR_OUT_OF_HOST_MEMORY
;
895 memset(device
->queues
[qfi
], 0, queue_create
->queueCount
* sizeof(struct libresoc_queue
));
897 device
->queue_count
[qfi
] = queue_create
->queueCount
;
899 for (unsigned q
= 0; q
< queue_create
->queueCount
; q
++) {
900 result
= libresoc_queue_init(device
, &device
->queues
[qfi
][q
],
901 qfi
, q
, queue_create
->flags
,
903 if (result
!= VK_SUCCESS
)
908 if (result
!= VK_SUCCESS
)
911 VkPipelineCacheCreateInfo ci
;
912 ci
.sType
= VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO
;
915 ci
.pInitialData
= NULL
;
916 ci
.initialDataSize
= 0;
918 result
= libresoc_CreatePipelineCache(libresoc_device_to_handle(device
),
920 if (result
!= VK_SUCCESS
)
923 *pDevice
= libresoc_device_to_handle(device
);
927 libresoc_DestroyPipelineCache(libresoc_device_to_handle(device
), pc
, NULL
);
928 for (unsigned i
= 0; i
< LIBRESOC_MAX_QUEUE_FAMILIES
; i
++) {
929 for (unsigned q
= 0; q
< device
->queue_count
[i
]; q
++)
930 libresoc_queue_finish(&device
->queues
[i
][q
]);
931 if (device
->queue_count
[i
])
932 vk_free(&device
->vk
.alloc
, device
->queues
[i
]);
935 vk_free(&device
->vk
.alloc
, device
);
940 libresoc_DestroyDevice(VkDevice _device
,
941 const VkAllocationCallbacks
*pAllocator
)
943 if (getenv("LIBRESOC_TRACE")) {
944 fprintf(stderr
, "DestroyDevice called. \n");
950 libresoc_GetDeviceQueue(VkDevice _device
,
951 uint32_t queueNodeIndex
,
955 if (getenv("LIBRESOC_TRACE")) {
956 fprintf(stderr
, "GetDeviceQueue called. \n");