Add code to few more essential methods in libresoc_device.c
[mesa.git] / src / libre-soc / vulkan / libresoc_device.c
1 /*
2 * Copyright © 2019 Raspberry Pi
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <assert.h>
25 #include <stdbool.h>
26 #include <string.h>
27 #include <sys/mman.h>
28 #include <sys/sysinfo.h>
29 #include <unistd.h>
30
31 #include "libresoc_private.h"
32 #include "vk_util.h"
33 #include "vk_alloc.h"
34
35 VkResult
36 libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName,
37 uint32_t *pPropertyCount,
38 VkExtensionProperties *pProperties)
39 {
40 if (getenv("LIBRESOC_TRACE")) {
41 fprintf(stderr, "EnumerateInstanceExtensionProperties called for: %s \n", pLayerName);
42 }
43 VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
44
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];
49 }
50 }
51 }
52
53 return vk_outarray_status(&out);
54 }
55
56 static void *
57 default_alloc_func(void *pUserData, size_t size, size_t align,
58 VkSystemAllocationScope allocationScope)
59 {
60 return malloc(size);
61 }
62
63 static void *
64 default_realloc_func(void *pUserData, void *pOriginal, size_t size,
65 size_t align, VkSystemAllocationScope allocationScope)
66 {
67 return realloc(pOriginal, size);
68 }
69
70 static void
71 default_free_func(void *pUserData, void *pMemory)
72 {
73 free(pMemory);
74 }
75
76 static const VkAllocationCallbacks default_alloc = {
77 .pUserData = NULL,
78 .pfnAllocation = default_alloc_func,
79 .pfnReallocation = default_realloc_func,
80 .pfnFree = default_free_func,
81 };
82
83 VkResult
84 libresoc_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
85 const VkAllocationCallbacks *pAllocator,
86 VkInstance *pInstance)
87 {
88 if (getenv("LIBRESOC_TRACE")) {
89 fprintf(stderr, "CreateInstance called. \n");
90 }
91 struct libresoc_instance *instance;
92
93 instance = vk_zalloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
94 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
95 if (!instance)
96 return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
97
98 vk_object_base_init(NULL, &instance->base, VK_OBJECT_TYPE_INSTANCE);
99
100 if (pAllocator)
101 instance->alloc = *pAllocator;
102 else
103 instance->alloc = default_alloc;
104 if (pCreateInfo->pApplicationInfo) {
105 const VkApplicationInfo *app = pCreateInfo->pApplicationInfo;
106
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;
112 }
113 /*TODO : enable extensions*/
114 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
115 int idx;
116 for (idx = 0; idx < LIBRESOC_INSTANCE_EXTENSION_COUNT; idx++) {
117 if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i],
118 libresoc_instance_extensions[idx].extensionName))
119 break;
120 }
121
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);
127 }
128
129 instance->enabled_extensions.extensions[idx] = true;
130 }
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.
134 */
135 if (!libresoc_instance_entrypoint_is_enabled(i, instance->apiVersion,
136 &instance->enabled_extensions)) {
137 instance->dispatch.entrypoints[i] = NULL;
138 } else {
139 instance->dispatch.entrypoints[i] =
140 libresoc_instance_dispatch_table.entrypoints[i];
141 }
142 }
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.
146 */
147 if (!libresoc_physical_device_entrypoint_is_enabled(i, instance->apiVersion,
148 &instance->enabled_extensions)) {
149 instance->physical_device_dispatch.entrypoints[i] = NULL;
150 } else {
151 instance->physical_device_dispatch.entrypoints[i] =
152 libresoc_physical_device_dispatch_table.entrypoints[i];
153 }
154 }
155
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.
159 */
160 if (!libresoc_device_entrypoint_is_enabled(i, instance->apiVersion,
161 &instance->enabled_extensions, NULL)) {
162 instance->device_dispatch.entrypoints[i] = NULL;
163 } else {
164 instance->device_dispatch.entrypoints[i] =
165 libresoc_device_dispatch_table.entrypoints[i];
166 }
167 }
168 instance->physical_devices_enumerated = false;
169 list_inithead(&instance->physical_devices);
170 *pInstance = libresoc_instance_to_handle(instance);
171
172 return VK_SUCCESS;
173 }
174
175 void
176 libresoc_DestroyInstance(VkInstance _instance,
177 const VkAllocationCallbacks *pAllocator)
178 {
179 if (getenv("LIBRESOC_TRACE")) {
180 fprintf(stderr, "DestroyInstance called. \n");
181 }
182 /* FIXME: stub */
183 }
184
185 static VkResult
186 libresoc_physical_device_try_create(struct libresoc_instance *instance,
187 struct libresoc_physical_device **device_out)
188 {
189 VkResult result;
190
191 struct libresoc_physical_device *device =
192 vk_zalloc2(&instance->alloc, NULL, sizeof(*device), 8,
193 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
194 if (!device) {
195 result = vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
196 return result;
197 }
198
199 device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
200 device->instance = instance;
201
202 snprintf(device->name, sizeof(device->name),
203 "LIBRE-SOC DEVICE");
204 *device_out = device;
205
206 return VK_SUCCESS;
207
208 }
209 static VkResult
210 libresoc_enumerate_physical_devices(struct libresoc_instance *instance)
211 {
212
213 if (instance->physical_devices_enumerated)
214 return VK_SUCCESS;
215
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
220 */
221 struct libresoc_physical_device *pdevice;
222
223 result = libresoc_physical_device_try_create(instance, &pdevice);
224 if (result != VK_SUCCESS)
225 return result;
226
227 list_addtail(&pdevice->link, &instance->physical_devices);
228 return VK_SUCCESS;
229
230 }
231
232 VkResult
233 libresoc_EnumeratePhysicalDevices(VkInstance _instance,
234 uint32_t *pPhysicalDeviceCount,
235 VkPhysicalDevice *pPhysicalDevices)
236 {
237 if (getenv("LIBRESOC_TRACE")) {
238 fprintf(stderr, "EnumeratePhysicalDevices called\n");
239 }
240 LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
241 VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
242
243 VkResult result = libresoc_enumerate_physical_devices(instance);
244 if (result != VK_SUCCESS)
245 return result;
246
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);
251 }
252 }
253
254 return vk_outarray_status(&out);
255 }
256
257 void
258 libresoc_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
259 VkPhysicalDeviceFeatures *pFeatures)
260 {
261 if (getenv("LIBRESOC_TRACE")) {
262 fprintf(stderr, "GetPhysicalDeviceFeatures called. \n");
263 }
264 //LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
265 memset(pFeatures, 0, sizeof(*pFeatures));
266
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,
276 .logicOp = true,
277 .multiDrawIndirect = true,
278 .drawIndirectFirstInstance = true,
279 .depthClamp = true,
280 .depthBiasClamp = true,
281 .fillModeNonSolid = true,
282 .depthBounds = true,
283 .wideLines = true,
284 .largePoints = true,
285 .alphaToOne = 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,
308 .shaderInt64 = true,
309 .shaderInt16 = true,
310 .sparseBinding = true,
311 .variableMultisampleRate = true,
312 .shaderResourceMinLod = true,
313 .inheritedQueries = true,
314 };
315 }
316
317 static size_t
318 libresoc_max_descriptor_set_size()
319 {
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 */);
333 }
334
335 void
336 libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
337 VkPhysicalDeviceProperties *pProperties)
338 {
339 if (getenv("LIBRESOC_TRACE")) {
340 fprintf(stderr, "GetPhysicalDeviceProperties called. \n");
341 }
342 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
343 VkSampleCountFlags sample_counts = 0xf;
344
345 size_t max_descriptor_set_size = libresoc_max_descriptor_set_size();
346
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 = {
403 1024,
404 1024,
405 1024
406 },
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,
458 };
459
460 *pProperties = (VkPhysicalDeviceProperties) {
461 .apiVersion = libresoc_physical_device_api_version(pdevice),
462 .driverVersion = vk_get_driver_version(),
463 .vendorID = 1,
464 .deviceID = 1,
465 .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
466 .limits = limits,
467 .sparseProperties = {0},
468 };
469
470 strcpy(pProperties->deviceName, pdevice->name);
471 // memcpy(pProperties->pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
472 }
473
474 static void libresoc_get_physical_device_queue_family_properties(
475 struct libresoc_physical_device* pdevice,
476 uint32_t* pCount,
477 VkQueueFamilyProperties** pQueueFamilyProperties)
478 {
479 int num_queue_families = 1;
480 int idx;
481
482 if (pQueueFamilyProperties == NULL) {
483 *pCount = num_queue_families;
484 return;
485 }
486
487 if (!*pCount)
488 return;
489
490 idx = 0;
491 if (*pCount >= 1) {
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,
497 .queueCount = 1,
498 .timestampValidBits = 64,
499 .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 },
500 };
501 idx++;
502 }
503
504 *pCount = idx;
505 }
506
507 void
508 libresoc_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
509 uint32_t *pCount,
510 VkQueueFamilyProperties *pQueueFamilyProperties)
511 {
512 if (getenv("LIBRESOC_TRACE")) {
513 fprintf(stderr, "GetPhysicalDeviceQueueFamilyProperites called. \n");
514 }
515 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
516 if (!pQueueFamilyProperties) {
517 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, NULL);
518 return;
519 }
520 VkQueueFamilyProperties *properties[] = {
521 pQueueFamilyProperties + 0,
522 pQueueFamilyProperties + 1,
523 pQueueFamilyProperties + 2,
524 };
525 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, properties);
526 assert(*pCount <= 3);
527 }
528
529 void
530 libresoc_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
531 VkPhysicalDeviceMemoryProperties *pMemoryProperties)
532 {
533 if (getenv("LIBRESOC_TRACE")) {
534 fprintf(stderr, "GetPhysicalDEviceMemoryProperties called. \n");
535 }
536 /* FIXME: stub */
537 }
538
539 void
540 libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
541
542 if (getenv("LIBRESOC_TRACE")) {
543 fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
544 }
545 /* FIXME: stub */
546 }
547
548 VkResult
549 libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
550 {
551 if (getenv("LIBRESOC_TRACE")) {
552 fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
553 }
554
555 /* FIXME: stub */
556 return VK_SUCCESS;
557 }
558 void
559 libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
560 {
561 if (getenv("LIBRESOC_TRACE")) {
562 fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
563 }
564 /* FIXME: stub */
565 }
566 PFN_vkVoidFunction
567 libresoc_GetInstanceProcAddr(VkInstance _instance,
568 const char *pName)
569 {
570 if (getenv("LIBRESOC_TRACE")) {
571 fprintf(stderr, "GetInstanceProcAddr called for: %s \n", pName);
572 }
573 LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
574
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.
578 */
579 if (pName == NULL)
580 return NULL;
581
582 #define LOOKUP_LIBRESOC_ENTRYPOINT(entrypoint) \
583 if (strcmp(pName, "vk" #entrypoint) == 0) \
584 return (PFN_vkVoidFunction)libresoc_##entrypoint
585
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);
600
601
602 #undef LOOKUP_LIBRESOC_ENTRYPOINT
603
604 if (instance == NULL)
605 return NULL;
606
607 int idx = libresoc_get_instance_entrypoint_index(pName);
608 if (idx >= 0)
609 return instance->dispatch.entrypoints[idx];
610
611 idx = libresoc_get_physical_device_entrypoint_index(pName);
612 if (idx >= 0)
613 return instance->physical_device_dispatch.entrypoints[idx];
614
615 idx = libresoc_get_device_entrypoint_index(pName);
616 if (idx >= 0)
617 return instance->device_dispatch.entrypoints[idx];
618
619 return NULL;
620 }
621
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.
624 */
625 PUBLIC
626 VKAPI_ATTR PFN_vkVoidFunction
627 VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance,
628 const char *pName);
629
630 PUBLIC
631 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
632 vk_icdGetInstanceProcAddr(VkInstance instance,
633 const char* pName)
634 {
635 if (getenv("LIBRESOC_TRACE")) {
636 fprintf(stderr, "vk_icdGetInstanceProcAddr called for: %s \n", pName);
637 }
638 return libresoc_GetInstanceProcAddr(instance, pName);
639 }
640
641 PFN_vkVoidFunction
642 libresoc_GetDeviceProcAddr(VkDevice _device,
643 const char *pName)
644 {
645 if (getenv("LIBRESOC_TRACE")) {
646 fprintf(stderr, "GetDeviceProcAddr called for: %s \n", pName);
647 }
648 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
649
650 if (!device || !pName)
651 return NULL;
652
653 int idx = libresoc_get_device_entrypoint_index(pName);
654 if (idx < 0)
655 return NULL;
656
657 return device->dispatch.entrypoints[idx];
658 }
659
660 /* With version 4+ of the loader interface the ICD should expose
661 * vk_icdGetPhysicalDeviceProcAddr()
662 */
663 PUBLIC
664 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
665 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
666 const char* pName);
667
668 PFN_vkVoidFunction
669 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
670 const char* pName)
671 {
672 if (getenv("LIBRESOC_TRACE")) {
673 fprintf(stderr, "vk_icdGetPhysicalDeviceProcAddr called for: %s \n", pName);
674 }
675 LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
676
677 if (!pName || !instance)
678 return NULL;
679
680 int idx = libresoc_get_physical_device_entrypoint_index(pName);
681 if (idx < 0)
682 return NULL;
683
684 return instance->physical_device_dispatch.entrypoints[idx];
685 }
686
687 VkResult
688 libresoc_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
689 const char *pLayerName,
690 uint32_t *pPropertyCount,
691 VkExtensionProperties *pProperties)
692 {
693 if (getenv("LIBRESOC_TRACE")) {
694 fprintf(stderr, "EnumerateDeviceExtensionProperties called for layer: %s \n", pLayerName);
695 }
696 LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
697 VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
698
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];
703 }
704 }
705 }
706
707 return vk_outarray_status(&out);
708 }
709
710 static void
711 libresoc_device_init_dispatch(struct libresoc_device *device)
712 {
713 const struct libresoc_instance *instance = device->physical_device->instance;
714 const struct libresoc_device_dispatch_table *dispatch_table_layer = NULL;
715
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.
719 */
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];
728 } else {
729 device->dispatch.entrypoints[i] =
730 libresoc_device_dispatch_table.entrypoints[i];
731 }
732 }
733 }
734
735 /*
736 static VkResult
737 libresoc_create_pthread_cond(pthread_cond_t *cond)
738 {
739 pthread_condattr_t condattr;
740 if (pthread_condattr_init(&condattr)) {
741 return VK_ERROR_INITIALIZATION_FAILED;
742 }
743
744 if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
745 pthread_condattr_destroy(&condattr);
746 return VK_ERROR_INITIALIZATION_FAILED;
747 }
748 if (pthread_cond_init(cond, &condattr)) {
749 pthread_condattr_destroy(&condattr);
750 return VK_ERROR_INITIALIZATION_FAILED;
751 }
752 pthread_condattr_destroy(&condattr);
753 return VK_SUCCESS;
754 }
755 */
756 static VkResult
757 check_physical_device_features(VkPhysicalDevice physicalDevice,
758 const VkPhysicalDeviceFeatures *features)
759 {
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);
769 }
770
771 return VK_SUCCESS;
772 }
773 static int libresoc_get_device_extension_index(const char *name)
774 {
775 for (unsigned i = 0; i < LIBRESOC_DEVICE_EXTENSION_COUNT; ++i) {
776 if (strcmp(name, libresoc_device_extensions[i].extensionName) == 0)
777 return i;
778 }
779 return -1;
780 }
781
782 static int
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)
787 {
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;
793 return VK_SUCCESS;
794 }
795
796 static void
797 libresoc_queue_finish(struct libresoc_queue *queue)
798 {
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);
804 // }
805 // pthread_cond_destroy(&queue->thread_cond);
806 // pthread_mutex_destroy(&queue->pending_mutex);
807 // pthread_mutex_destroy(&queue->thread_mutex);
808 //
809 // if (queue->hw_ctx)
810 // queue->device->ws->ctx_destroy(queue->hw_ctx);
811 //
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);
834 }
835 VkResult
836 libresoc_CreateDevice(VkPhysicalDevice physicalDevice,
837 const VkDeviceCreateInfo *pCreateInfo,
838 const VkAllocationCallbacks *pAllocator,
839 VkDevice *pDevice)
840 {
841 if (getenv("LIBRESOC_TRACE")) {
842 fprintf(stderr, "CreateDevice called \n");
843 }
844 LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
845 VkResult result;
846 struct libresoc_device *device;
847
848 /* Check enabled features */
849 if (pCreateInfo->pEnabledFeatures) {
850 result = check_physical_device_features(physicalDevice,
851 pCreateInfo->pEnabledFeatures);
852 if (result != VK_SUCCESS)
853 return result;
854 }
855
856 device = vk_zalloc2(&physical_device->instance->alloc, pAllocator,
857 sizeof(*device), 8,
858 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
859 if (!device)
860 return vk_error(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
861
862 vk_device_init(&device->vk, pCreateInfo,
863 &physical_device->instance->alloc, pAllocator);
864
865 device->instance = physical_device->instance;
866 device->physical_device = physical_device;
867
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);
874 }
875
876 device->enabled_extensions.extensions[index] = true;
877 }
878
879 libresoc_device_init_dispatch(device);
880
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);
886
887
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;
892 goto fail;
893 }
894
895 memset(device->queues[qfi], 0, queue_create->queueCount * sizeof(struct libresoc_queue));
896
897 device->queue_count[qfi] = queue_create->queueCount;
898
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,
902 global_priority);
903 if (result != VK_SUCCESS)
904 goto fail;
905 }
906 }
907
908 if (result != VK_SUCCESS)
909 goto fail;
910
911 VkPipelineCacheCreateInfo ci;
912 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
913 ci.pNext = NULL;
914 ci.flags = 0;
915 ci.pInitialData = NULL;
916 ci.initialDataSize = 0;
917 VkPipelineCache pc;
918 result = libresoc_CreatePipelineCache(libresoc_device_to_handle(device),
919 &ci, NULL, &pc);
920 if (result != VK_SUCCESS)
921 goto fail;
922
923 *pDevice = libresoc_device_to_handle(device);
924 return VK_SUCCESS;
925
926 fail:
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]);
933 }
934
935 vk_free(&device->vk.alloc, device);
936 return result;
937 }
938
939 void
940 libresoc_DestroyDevice(VkDevice _device,
941 const VkAllocationCallbacks *pAllocator)
942 {
943 if (getenv("LIBRESOC_TRACE")) {
944 fprintf(stderr, "DestroyDevice called. \n");
945 }
946 /* FIXME: stub */
947 }
948
949 void
950 libresoc_GetDeviceQueue(VkDevice _device,
951 uint32_t queueNodeIndex,
952 uint32_t queueIndex,
953 VkQueue *pQueue)
954 {
955 if (getenv("LIBRESOC_TRACE")) {
956 fprintf(stderr, "GetDeviceQueue called. \n");
957 }
958 /* FIXME: stub */
959 }