Updated code generation so that for vertex shader output position is written at last...
[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 "util/debug.h"
32 #include "util/driconf.h"
33 #include "libresoc_private.h"
34 #include "compiler/glsl_types.h"
35 #include "vk_util.h"
36 #include "vk_alloc.h"
37
38 struct libresoc_deferred_queue_submission {
39 struct libresoc_queue *queue;
40 VkCommandBuffer *cmd_buffers;
41 uint32_t cmd_buffer_count;
42
43 /* Sparse bindings that happen on a queue. */
44 VkSparseBufferMemoryBindInfo *buffer_binds;
45 uint32_t buffer_bind_count;
46 VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
47 uint32_t image_opaque_bind_count;
48
49 bool flush_caches;
50 VkShaderStageFlags wait_dst_stage_mask;
51 struct libresoc_semaphore_part **wait_semaphores;
52 uint32_t wait_semaphore_count;
53 struct libresoc_semaphore_part **signal_semaphores;
54 uint32_t signal_semaphore_count;
55 VkFence fence;
56
57 uint64_t *wait_values;
58 uint64_t *signal_values;
59
60 struct libresoc_semaphore_part *temporary_semaphore_parts;
61 uint32_t temporary_semaphore_part_count;
62
63 struct list_head queue_pending_list;
64 uint32_t submission_wait_count;
65 struct libresoc_timeline_waiter *wait_nodes;
66
67 struct list_head processing_list;
68 };
69
70 struct libresoc_queue_submission {
71 const VkCommandBuffer *cmd_buffers;
72 uint32_t cmd_buffer_count;
73
74 /* Sparse bindings that happen on a queue. */
75 const VkSparseBufferMemoryBindInfo *buffer_binds;
76 uint32_t buffer_bind_count;
77 const VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
78 uint32_t image_opaque_bind_count;
79
80 bool flush_caches;
81 VkPipelineStageFlags wait_dst_stage_mask;
82 const VkSemaphore *wait_semaphores;
83 uint32_t wait_semaphore_count;
84 const VkSemaphore *signal_semaphores;
85 uint32_t signal_semaphore_count;
86 VkFence fence;
87
88 const uint64_t *wait_values;
89 uint32_t wait_value_count;
90 const uint64_t *signal_values;
91 uint32_t signal_value_count;
92 };
93
94 static uint32_t libresoc_surface_max_layer_count(struct libresoc_image_view *iview)
95 {
96 return iview->type == VK_IMAGE_VIEW_TYPE_3D ? iview->extent.depth : (iview->base_layer + iview->layer_count);
97 }
98
99 void
100 libresoc_free_memory(struct libresoc_device *device,
101 const VkAllocationCallbacks* pAllocator,
102 struct libresoc_device_memory *mem)
103 {
104 if (mem == NULL)
105 return;
106
107 vk_object_base_finish(&mem->base);
108 vk_free2(&device->vk.alloc, pAllocator, mem);
109 }
110
111 static VkResult libresoc_alloc_memory(struct libresoc_device *device,
112 const VkMemoryAllocateInfo* pAllocateInfo,
113 const VkAllocationCallbacks* pAllocator,
114 VkDeviceMemory* pMem)
115 {
116 struct libresoc_device_memory *mem;
117 VkResult result;
118 // uint32_t flags = 0;
119
120 assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
121
122 const VkImportMemoryFdInfoKHR *import_info =
123 vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
124 // const VkMemoryDedicatedAllocateInfo *dedicate_info =
125 // vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
126 // const VkExportMemoryAllocateInfo *export_info =
127 // vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
128 const VkImportMemoryHostPointerInfoEXT *host_ptr_info =
129 vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_HOST_POINTER_INFO_EXT);
130
131 // const struct wsi_memory_allocate_info *wsi_info =
132 // vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA);
133
134
135 mem = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*mem), 8,
136 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
137 if (mem == NULL)
138 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
139
140 vk_object_base_init(&device->vk, &mem->base,
141 VK_OBJECT_TYPE_DEVICE_MEMORY);
142
143 // if (dedicate_info) {
144 // mem->image = libresoc_image_from_handle(dedicate_info->image);
145 // mem->buffer = libresoc_buffer_from_handle(dedicate_info->buffer);
146 // } else {
147 // mem->image = NULL;
148 // mem->buffer = NULL;
149 // }
150
151 // float priority_float = 0.5;
152 // const struct VkMemoryPriorityAllocateInfoEXT *priority_ext =
153 // vk_find_struct_const(pAllocateInfo->pNext,
154 // MEMORY_PRIORITY_ALLOCATE_INFO_EXT);
155 // if (priority_ext)
156 // priority_float = priority_ext->priority;
157
158 // unsigned priority = MIN2(LIBRESOC_BO_PRIORITY_APPLICATION_MAX - 1,
159 // (int)(priority_float * LIBRESOC_BO_PRIORITY_APPLICATION_MAX));
160
161 mem->user_ptr = NULL;
162 //mem->bo = NULL;
163
164
165 if (import_info) {
166 assert(import_info->handleType ==
167 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
168 import_info->handleType ==
169 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
170 // mem->bo = device->ws->buffer_from_fd(device->ws, import_info->fd,
171 // priority, NULL);
172 // if (!mem->bo) {
173 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
174 // goto fail;
175 // } else {
176 // close(import_info->fd);
177 // }
178
179 // if (mem->image && mem->image->plane_count == 1 &&
180 // !vk_format_is_depth_or_stencil(mem->image->vk_format)) {
181 // struct radeon_bo_metadata metadata;
182 // device->ws->buffer_get_metadata(mem->bo, &metadata);
183
184 // struct libresoc_image_create_info create_info = {
185 // .no_metadata_planes = true,
186 // .bo_metadata = &metadata
187 // };
188
189 // /* This gives a basic ability to import radeonsi images
190 // * that don't have DCC. This is not guaranteed by any
191 // * spec and can be removed after we support modifiers. */
192 // result = libresoc_image_create_layout(device, create_info, mem->image);
193 // if (result != VK_SUCCESS) {
194 // device->ws->buffer_destroy(mem->bo);
195 // goto fail;
196 // }
197 // }
198 } else if (host_ptr_info) {
199 // assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
200 // mem->bo = device->ws->buffer_from_ptr(device->ws, host_ptr_info->pHostPointer,
201 // pAllocateInfo->allocationSize,
202 // priority);
203 // if (!mem->bo) {
204 // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
205 // goto fail;
206 // } else {
207 // mem->user_ptr = host_ptr_info->pHostPointer;
208 // }
209 } else {
210 uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
211 uint32_t heap_index;
212
213 heap_index = device->physical_device->memory_properties.memoryTypes[pAllocateInfo->memoryTypeIndex].heapIndex;
214 // domain = device->physical_device->memory_domains[pAllocateInfo->memoryTypeIndex];
215 // flags |= device->physical_device->memory_flags[pAllocateInfo->memoryTypeIndex];
216
217 // if (!dedicate_info && !import_info && (!export_info || !export_info->handleTypes)) {
218 // flags |= RADEON_FLAG_NO_INTERPROCESS_SHARING;
219 // if (device->use_global_bo_list) {
220 // flags |= RADEON_FLAG_PREFER_LOCAL_BO;
221 // }
222 // }
223
224 if (device->overallocation_disallowed) {
225 uint64_t total_size =
226 device->physical_device->memory_properties.memoryHeaps[heap_index].size;
227
228 mtx_lock(&device->overallocation_mutex);
229 if (device->allocated_memory_size[heap_index] + alloc_size > total_size) {
230 mtx_unlock(&device->overallocation_mutex);
231 result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
232 goto fail;
233 }
234 device->allocated_memory_size[heap_index] += alloc_size;
235 mtx_unlock(&device->overallocation_mutex);
236 }
237
238 mem->bytes = vk_zalloc2(&device->vk.alloc, pAllocator, alloc_size, 8,
239 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
240 // mem->bo = device->ws->buffer_create(device->ws, alloc_size, device->physical_device->rad_info.max_alignment,
241 // domain, flags, priority);
242
243 // if (!mem->bo) {
244 // if (device->overallocation_disallowed) {
245 // mtx_lock(&device->overallocation_mutex);
246 // device->allocated_memory_size[heap_index] -= alloc_size;
247 // mtx_unlock(&device->overallocation_mutex);
248 // }
249 // result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
250 // goto fail;
251 // }
252
253 mem->heap_index = heap_index;
254 mem->alloc_size = alloc_size;
255 }
256
257 // if (!wsi_info) {
258 // result = libresoc_bo_list_add(device, mem->bo);
259 // if (result != VK_SUCCESS)
260 // goto fail;
261 // }
262
263 *pMem = libresoc_device_memory_to_handle(mem);
264
265 return VK_SUCCESS;
266
267 fail:
268 libresoc_free_memory(device, pAllocator,mem);
269
270 return result;
271 }
272
273 VkResult libresoc_AllocateMemory(
274 VkDevice _device,
275 const VkMemoryAllocateInfo* pAllocateInfo,
276 const VkAllocationCallbacks* pAllocator,
277 VkDeviceMemory* pMem)
278 {
279 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
280 return libresoc_alloc_memory(device, pAllocateInfo, pAllocator, pMem);
281 }
282
283 void libresoc_FreeMemory(
284 VkDevice _device,
285 VkDeviceMemory _mem,
286 const VkAllocationCallbacks* pAllocator)
287 {
288 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
289 LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _mem);
290
291 libresoc_free_memory(device, pAllocator, mem);
292 }
293 static VkResult
294 libresoc_create_pthread_cond(pthread_cond_t *cond)
295 {
296 pthread_condattr_t condattr;
297 if (pthread_condattr_init(&condattr)) {
298 return VK_ERROR_INITIALIZATION_FAILED;
299 }
300
301 if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
302 pthread_condattr_destroy(&condattr);
303 return VK_ERROR_INITIALIZATION_FAILED;
304 }
305 if (pthread_cond_init(cond, &condattr)) {
306 pthread_condattr_destroy(&condattr);
307 return VK_ERROR_INITIALIZATION_FAILED;
308 }
309 pthread_condattr_destroy(&condattr);
310 return VK_SUCCESS;
311 }
312
313 VkResult
314 libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName,
315 uint32_t *pPropertyCount,
316 VkExtensionProperties *pProperties)
317 {
318 if (getenv("LIBRESOC_TRACE")) {
319 fprintf(stderr, "EnumerateInstanceExtensionProperties called for: %s \n", pLayerName);
320 }
321 VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
322
323 for (int i = 0; i < LIBRESOC_INSTANCE_EXTENSION_COUNT; i++) {
324 if (libresoc_instance_extensions_supported.extensions[i]) {
325 vk_outarray_append(&out, prop) {
326 *prop = libresoc_instance_extensions[i];
327 }
328 }
329 }
330
331 return vk_outarray_status(&out);
332 }
333
334 static void *
335 default_alloc_func(void *pUserData, size_t size, size_t align,
336 VkSystemAllocationScope allocationScope)
337 {
338 return malloc(size);
339 }
340
341 static void *
342 default_realloc_func(void *pUserData, void *pOriginal, size_t size,
343 size_t align, VkSystemAllocationScope allocationScope)
344 {
345 return realloc(pOriginal, size);
346 }
347
348 static void
349 default_free_func(void *pUserData, void *pMemory)
350 {
351 free(pMemory);
352 }
353
354 static const VkAllocationCallbacks default_alloc = {
355 .pUserData = NULL,
356 .pfnAllocation = default_alloc_func,
357 .pfnReallocation = default_realloc_func,
358 .pfnFree = default_free_func,
359 };
360
361 static const struct debug_control libresoc_debug_options[] = {
362 {"nofastclears", LIBRESOC_DEBUG_NO_FAST_CLEARS},
363 {"nodcc", LIBRESOC_DEBUG_NO_DCC},
364 {"shaders", LIBRESOC_DEBUG_DUMP_SHADERS},
365 {"nocache", LIBRESOC_DEBUG_NO_CACHE},
366 {"shaderstats", LIBRESOC_DEBUG_DUMP_SHADER_STATS},
367 {"nohiz", LIBRESOC_DEBUG_NO_HIZ},
368 {"nocompute", LIBRESOC_DEBUG_NO_COMPUTE_QUEUE},
369 {"allbos", LIBRESOC_DEBUG_ALL_BOS},
370 {"noibs", LIBRESOC_DEBUG_NO_IBS},
371 {"spirv", LIBRESOC_DEBUG_DUMP_SPIRV},
372 {"vmfaults", LIBRESOC_DEBUG_VM_FAULTS},
373 {"zerovram", LIBRESOC_DEBUG_ZERO_VRAM},
374 {"syncshaders", LIBRESOC_DEBUG_SYNC_SHADERS},
375 {"preoptir", LIBRESOC_DEBUG_PREOPTIR},
376 {"nodynamicbounds", LIBRESOC_DEBUG_NO_DYNAMIC_BOUNDS},
377 {"nooutoforder", LIBRESOC_DEBUG_NO_OUT_OF_ORDER},
378 {"info", LIBRESOC_DEBUG_INFO},
379 {"errors", LIBRESOC_DEBUG_ERRORS},
380 {"startup", LIBRESOC_DEBUG_STARTUP},
381 {"checkir", LIBRESOC_DEBUG_CHECKIR},
382 {"nothreadllvm", LIBRESOC_DEBUG_NOTHREADLLVM},
383 {"nobinning", LIBRESOC_DEBUG_NOBINNING},
384 {"nongg", LIBRESOC_DEBUG_NO_NGG},
385 {"allentrypoints", LIBRESOC_DEBUG_ALL_ENTRYPOINTS},
386 {"metashaders", LIBRESOC_DEBUG_DUMP_META_SHADERS},
387 {"nomemorycache", LIBRESOC_DEBUG_NO_MEMORY_CACHE},
388 {"llvm", LIBRESOC_DEBUG_LLVM},
389 {"forcecompress", LIBRESOC_DEBUG_FORCE_COMPRESS},
390 {"nir", LIBRESOC_DEBUG_DUMP_NIR},
391 {NULL, 0}
392 };
393
394 const char *
395 libresoc_get_debug_option_name(int id)
396 {
397 assert(id < ARRAY_SIZE(libresoc_debug_options) - 1);
398 return libresoc_debug_options[id].string;
399 }
400
401 static const char libresoc_dri_options_xml[] =
402 DRI_CONF_BEGIN
403 DRI_CONF_SECTION_PERFORMANCE
404 DRI_CONF_ADAPTIVE_SYNC("true")
405 DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
406 DRI_CONF_VK_X11_STRICT_IMAGE_COUNT("false")
407 DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT("false")
408 DRI_CONF_SECTION_END
409
410 DRI_CONF_SECTION_DEBUG
411 DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST("false")
412 DRI_CONF_SECTION_END
413 DRI_CONF_END;
414
415 static void libresoc_init_dri_options(struct libresoc_instance *instance)
416 {
417 driParseOptionInfo(&instance->available_dri_options, libresoc_dri_options_xml);
418 driParseConfigFiles(&instance->dri_options,
419 &instance->available_dri_options,
420 0, "libresoc", NULL,
421 instance->app_info.app_name,
422 instance->app_info.app_version,
423 instance->engineName,
424 instance->engineVersion);
425 }
426
427 VkResult
428 libresoc_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
429 const VkAllocationCallbacks *pAllocator,
430 VkInstance *pInstance)
431 {
432 if (getenv("LIBRESOC_TRACE")) {
433 fprintf(stderr, "CreateInstance called. \n");
434 }
435 struct libresoc_instance *instance;
436
437 instance = vk_zalloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
438 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
439 if (!instance)
440 return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
441
442 vk_object_base_init(NULL, &instance->base, VK_OBJECT_TYPE_INSTANCE);
443
444 if (pAllocator)
445 instance->alloc = *pAllocator;
446 else
447 instance->alloc = default_alloc;
448 if (pCreateInfo->pApplicationInfo) {
449 const VkApplicationInfo *app = pCreateInfo->pApplicationInfo;
450
451 instance->engineName =
452 vk_strdup(&instance->alloc, app->pEngineName,
453 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
454 instance->engineVersion = app->engineVersion;
455 instance->apiVersion = app->apiVersion;
456 }
457 instance->debug_flags = parse_debug_string(getenv("LIBRESOC_DEBUG"),
458 libresoc_debug_options);
459 /*TODO : enable extensions*/
460 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
461 int idx;
462 for (idx = 0; idx < LIBRESOC_INSTANCE_EXTENSION_COUNT; idx++) {
463 if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i],
464 libresoc_instance_extensions[idx].extensionName))
465 break;
466 }
467
468 if (idx >= LIBRESOC_INSTANCE_EXTENSION_COUNT ||
469 !libresoc_instance_extensions_supported.extensions[idx]) {
470 vk_object_base_finish(&instance->base);
471 vk_free2(&default_alloc, pAllocator, instance);
472 return vk_error(instance, VK_ERROR_EXTENSION_NOT_PRESENT);
473 }
474
475 instance->enabled_extensions.extensions[idx] = true;
476 }
477 for (unsigned i = 0; i < ARRAY_SIZE(instance->dispatch.entrypoints); i++) {
478 /* Vulkan requires that entrypoints for extensions which have
479 * not been enabled must not be advertised.
480 */
481 if (!libresoc_instance_entrypoint_is_enabled(i, instance->apiVersion,
482 &instance->enabled_extensions)) {
483 instance->dispatch.entrypoints[i] = NULL;
484 } else {
485 instance->dispatch.entrypoints[i] =
486 libresoc_instance_dispatch_table.entrypoints[i];
487 }
488 }
489 for (unsigned i = 0; i < ARRAY_SIZE(instance->physical_device_dispatch.entrypoints); i++) {
490 /* Vulkan requires that entrypoints for extensions which have
491 * not been enabled must not be advertised.
492 */
493 if (!libresoc_physical_device_entrypoint_is_enabled(i, instance->apiVersion,
494 &instance->enabled_extensions)) {
495 instance->physical_device_dispatch.entrypoints[i] = NULL;
496 } else {
497 instance->physical_device_dispatch.entrypoints[i] =
498 libresoc_physical_device_dispatch_table.entrypoints[i];
499 }
500 }
501
502 for (unsigned i = 0; i < ARRAY_SIZE(instance->device_dispatch.entrypoints); i++) {
503 /* Vulkan requires that entrypoints for extensions which have
504 * not been enabled must not be advertised.
505 */
506 if (!libresoc_device_entrypoint_is_enabled(i, instance->apiVersion,
507 &instance->enabled_extensions, NULL)) {
508 instance->device_dispatch.entrypoints[i] = NULL;
509 } else {
510 instance->device_dispatch.entrypoints[i] =
511 libresoc_device_dispatch_table.entrypoints[i];
512 }
513 }
514 instance->physical_devices_enumerated = false;
515 list_inithead(&instance->physical_devices);
516 glsl_type_singleton_init_or_ref();
517 libresoc_init_dri_options(instance);
518 InitLLVM(&instance->llvm_ref);
519 *pInstance = libresoc_instance_to_handle(instance);
520
521 return VK_SUCCESS;
522 }
523
524 void
525 libresoc_DestroyInstance(VkInstance _instance,
526 const VkAllocationCallbacks *pAllocator)
527 {
528 if (getenv("LIBRESOC_TRACE")) {
529 fprintf(stderr, "DestroyInstance called. \n");
530 }
531 /* FIXME: stub */
532 }
533
534 static void
535 libresoc_physical_device_init_mem_types(struct libresoc_physical_device *device)
536 {
537 uint64_t visible_vram_size = 65536; //TODO: some dummy value
538 uint64_t vram_size = 65536; //TODO: some dummy value
539 int vram_index = -1, visible_vram_index = -1;
540 device->memory_properties.memoryHeapCount = 0;
541 if (vram_size > 0) {
542 vram_index = device->memory_properties.memoryHeapCount++;
543 device->memory_properties.memoryHeaps[vram_index] = (VkMemoryHeap) {
544 .size = vram_size,
545 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
546 };
547 }
548
549 if (visible_vram_size) {
550 visible_vram_index = device->memory_properties.memoryHeapCount++;
551 device->memory_properties.memoryHeaps[visible_vram_index] = (VkMemoryHeap) {
552 .size = visible_vram_size,
553 .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
554 };
555 }
556 unsigned type_count = 0;
557
558 if (vram_index >= 0 || visible_vram_index >= 0) {
559 device->memory_properties.memoryTypes[type_count++] = (VkMemoryType) {
560 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
561 .heapIndex = vram_index >= 0 ? vram_index : visible_vram_index,
562 };
563 }
564
565 if (visible_vram_index >= 0) {
566 device->memory_properties.memoryTypes[type_count++] = (VkMemoryType) {
567 .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
568 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
569 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
570 .heapIndex = visible_vram_index,
571 };
572 }
573
574 device->memory_properties.memoryTypeCount = type_count;
575
576
577 }
578 static VkResult
579 libresoc_physical_device_try_create(struct libresoc_instance *instance,
580 struct libresoc_physical_device **device_out)
581 {
582 VkResult result;
583 int fd = -1;
584 int master_fd = -1;
585
586 struct libresoc_physical_device *device =
587 vk_zalloc2(&instance->alloc, NULL, sizeof(*device), 8,
588 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
589 if (!device) {
590 result = vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
591 return result;
592 }
593
594 device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
595 device->instance = instance;
596
597 device->master_fd = master_fd;
598 device->local_fd = fd;
599 libresoc_physical_device_init_mem_types(device);
600
601 libresoc_physical_device_get_supported_extensions(device,
602 &device->supported_extensions);
603 result = libresoc_init_wsi(device);
604 if (result != VK_SUCCESS) {
605 return result;
606 }
607 snprintf(device->name, sizeof(device->name),
608 "LIBRE-SOC DEVICE");
609 *device_out = device;
610 //TODO: incase of failures need to deallocate and cleanup various allocation properly.
611 return VK_SUCCESS;
612
613 }
614 static VkResult
615 libresoc_enumerate_physical_devices(struct libresoc_instance *instance)
616 {
617
618 if (instance->physical_devices_enumerated)
619 return VK_SUCCESS;
620
621 instance->physical_devices_enumerated = true;
622 VkResult result = VK_SUCCESS;
623 /* the driver creates a null
624 * device that allows to test the compiler without having a physical device
625 */
626 struct libresoc_physical_device *pdevice;
627
628 result = libresoc_physical_device_try_create(instance, &pdevice);
629 if (result != VK_SUCCESS)
630 return result;
631
632 list_addtail(&pdevice->link, &instance->physical_devices);
633 return VK_SUCCESS;
634
635 }
636
637 VkResult
638 libresoc_EnumeratePhysicalDevices(VkInstance _instance,
639 uint32_t *pPhysicalDeviceCount,
640 VkPhysicalDevice *pPhysicalDevices)
641 {
642 if (getenv("LIBRESOC_TRACE")) {
643 fprintf(stderr, "EnumeratePhysicalDevices called\n");
644 }
645 LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
646 VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
647
648 VkResult result = libresoc_enumerate_physical_devices(instance);
649 if (result != VK_SUCCESS)
650 return result;
651
652 list_for_each_entry(struct libresoc_physical_device, pdevice,
653 &instance->physical_devices, link) {
654 vk_outarray_append(&out, i) {
655 *i = libresoc_physical_device_to_handle(pdevice);
656 }
657 }
658
659 return vk_outarray_status(&out);
660 }
661
662 void
663 libresoc_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
664 VkPhysicalDeviceFeatures *pFeatures)
665 {
666 if (getenv("LIBRESOC_TRACE")) {
667 fprintf(stderr, "GetPhysicalDeviceFeatures called. \n");
668 }
669 //LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
670 memset(pFeatures, 0, sizeof(*pFeatures));
671
672 *pFeatures = (VkPhysicalDeviceFeatures) {
673 .robustBufferAccess = true,
674 .fullDrawIndexUint32 = true,
675 .imageCubeArray = true,
676 .independentBlend = true,
677 .geometryShader = true,
678 .tessellationShader = true,
679 .sampleRateShading = true,
680 .dualSrcBlend = true,
681 .logicOp = true,
682 .multiDrawIndirect = true,
683 .drawIndirectFirstInstance = true,
684 .depthClamp = true,
685 .depthBiasClamp = true,
686 .fillModeNonSolid = true,
687 .depthBounds = true,
688 .wideLines = true,
689 .largePoints = true,
690 .alphaToOne = true,
691 .multiViewport = true,
692 .samplerAnisotropy = true,
693 .textureCompressionETC2 = false,
694 .textureCompressionASTC_LDR = false,
695 .textureCompressionBC = true,
696 .occlusionQueryPrecise = true,
697 .pipelineStatisticsQuery = true,
698 .vertexPipelineStoresAndAtomics = true,
699 .fragmentStoresAndAtomics = true,
700 .shaderTessellationAndGeometryPointSize = true,
701 .shaderImageGatherExtended = true,
702 .shaderStorageImageExtendedFormats = true,
703 .shaderStorageImageMultisample = true,
704 .shaderUniformBufferArrayDynamicIndexing = true,
705 .shaderSampledImageArrayDynamicIndexing = true,
706 .shaderStorageBufferArrayDynamicIndexing = true,
707 .shaderStorageImageArrayDynamicIndexing = true,
708 .shaderStorageImageReadWithoutFormat = true,
709 .shaderStorageImageWriteWithoutFormat = true,
710 .shaderClipDistance = true,
711 .shaderCullDistance = true,
712 .shaderFloat64 = true,
713 .shaderInt64 = true,
714 .shaderInt16 = true,
715 .sparseBinding = true,
716 .variableMultisampleRate = true,
717 .shaderResourceMinLod = true,
718 .inheritedQueries = true,
719 };
720 }
721
722 static size_t
723 libresoc_max_descriptor_set_size()
724 {
725 /* make sure that the entire descriptor set is addressable with a signed
726 * 32-bit int. So the sum of all limits scaled by descriptor size has to
727 * be at most 2 GiB. the combined image & samples object count as one of
728 * both. This limit is for the pipeline layout, not for the set layout, but
729 * there is no set limit, so we just set a pipeline limit. I don't think
730 * any app is going to hit this soon. */
731 return ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS
732 - MAX_INLINE_UNIFORM_BLOCK_SIZE * MAX_INLINE_UNIFORM_BLOCK_COUNT) /
733 (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
734 32 /* storage buffer, 32 due to potential space wasted on alignment */ +
735 32 /* sampler, largest when combined with image */ +
736 64 /* sampled image */ +
737 64 /* storage image */);
738 }
739
740 void
741 libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
742 VkPhysicalDeviceProperties *pProperties)
743 {
744 if (getenv("LIBRESOC_TRACE")) {
745 fprintf(stderr, "GetPhysicalDeviceProperties called. \n");
746 }
747 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
748 VkSampleCountFlags sample_counts = 0xf;
749
750 size_t max_descriptor_set_size = libresoc_max_descriptor_set_size();
751
752 VkPhysicalDeviceLimits limits = {
753 .maxImageDimension1D = (1 << 14),
754 .maxImageDimension2D = (1 << 14),
755 .maxImageDimension3D = (1 << 11),
756 .maxImageDimensionCube = (1 << 14),
757 .maxImageArrayLayers = (1 << 11),
758 .maxTexelBufferElements = UINT32_MAX,
759 .maxUniformBufferRange = UINT32_MAX,
760 .maxStorageBufferRange = UINT32_MAX,
761 .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
762 .maxMemoryAllocationCount = UINT32_MAX,
763 .maxSamplerAllocationCount = 64 * 1024,
764 .bufferImageGranularity = 64, /* A cache line */
765 .sparseAddressSpaceSize = LIBRESOC_MAX_MEMORY_ALLOCATION_SIZE, /* buffer max size */
766 .maxBoundDescriptorSets = MAX_SETS,
767 .maxPerStageDescriptorSamplers = max_descriptor_set_size,
768 .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
769 .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
770 .maxPerStageDescriptorSampledImages = max_descriptor_set_size,
771 .maxPerStageDescriptorStorageImages = max_descriptor_set_size,
772 .maxPerStageDescriptorInputAttachments = max_descriptor_set_size,
773 .maxPerStageResources = max_descriptor_set_size,
774 .maxDescriptorSetSamplers = max_descriptor_set_size,
775 .maxDescriptorSetUniformBuffers = max_descriptor_set_size,
776 .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
777 .maxDescriptorSetStorageBuffers = max_descriptor_set_size,
778 .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
779 .maxDescriptorSetSampledImages = max_descriptor_set_size,
780 .maxDescriptorSetStorageImages = max_descriptor_set_size,
781 .maxDescriptorSetInputAttachments = max_descriptor_set_size,
782 .maxVertexInputAttributes = MAX_VERTEX_ATTRIBS,
783 .maxVertexInputBindings = MAX_VBS,
784 .maxVertexInputAttributeOffset = 2047,
785 .maxVertexInputBindingStride = 2048,
786 .maxVertexOutputComponents = 128,
787 .maxTessellationGenerationLevel = 64,
788 .maxTessellationPatchSize = 32,
789 .maxTessellationControlPerVertexInputComponents = 128,
790 .maxTessellationControlPerVertexOutputComponents = 128,
791 .maxTessellationControlPerPatchOutputComponents = 120,
792 .maxTessellationControlTotalOutputComponents = 4096,
793 .maxTessellationEvaluationInputComponents = 128,
794 .maxTessellationEvaluationOutputComponents = 128,
795 .maxGeometryShaderInvocations = 127,
796 .maxGeometryInputComponents = 64,
797 .maxGeometryOutputComponents = 128,
798 .maxGeometryOutputVertices = 256,
799 .maxGeometryTotalOutputComponents = 1024,
800 .maxFragmentInputComponents = 128,
801 .maxFragmentOutputAttachments = 8,
802 .maxFragmentDualSrcAttachments = 1,
803 .maxFragmentCombinedOutputResources = 8,
804 .maxComputeSharedMemorySize = 32768,
805 .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
806 .maxComputeWorkGroupInvocations = 1024,
807 .maxComputeWorkGroupSize = {
808 1024,
809 1024,
810 1024
811 },
812 .subPixelPrecisionBits = 8,
813 .subTexelPrecisionBits = 8,
814 .mipmapPrecisionBits = 8,
815 .maxDrawIndexedIndexValue = UINT32_MAX,
816 .maxDrawIndirectCount = UINT32_MAX,
817 .maxSamplerLodBias = 16,
818 .maxSamplerAnisotropy = 16,
819 .maxViewports = MAX_VIEWPORTS,
820 .maxViewportDimensions = { (1 << 14), (1 << 14) },
821 .viewportBoundsRange = { INT16_MIN, INT16_MAX },
822 .viewportSubPixelBits = 8,
823 .minMemoryMapAlignment = 4096, /* A page */
824 .minTexelBufferOffsetAlignment = 4,
825 .minUniformBufferOffsetAlignment = 4,
826 .minStorageBufferOffsetAlignment = 4,
827 .minTexelOffset = -32,
828 .maxTexelOffset = 31,
829 .minTexelGatherOffset = -32,
830 .maxTexelGatherOffset = 31,
831 .minInterpolationOffset = -2,
832 .maxInterpolationOffset = 2,
833 .subPixelInterpolationOffsetBits = 8,
834 .maxFramebufferWidth = (1 << 14),
835 .maxFramebufferHeight = (1 << 14),
836 .maxFramebufferLayers = (1 << 10),
837 .framebufferColorSampleCounts = sample_counts,
838 .framebufferDepthSampleCounts = sample_counts,
839 .framebufferStencilSampleCounts = sample_counts,
840 .framebufferNoAttachmentsSampleCounts = sample_counts,
841 .maxColorAttachments = MAX_RTS,
842 .sampledImageColorSampleCounts = sample_counts,
843 .sampledImageIntegerSampleCounts = sample_counts,
844 .sampledImageDepthSampleCounts = sample_counts,
845 .sampledImageStencilSampleCounts = sample_counts,
846 .storageImageSampleCounts = sample_counts,
847 .maxSampleMaskWords = 1,
848 .timestampComputeAndGraphics = true,
849 .timestampPeriod = 1000000.0 /* FIXME /pdevice->rad_info.clock_crystal_freq*/,
850 .maxClipDistances = 8,
851 .maxCullDistances = 8,
852 .maxCombinedClipAndCullDistances = 8,
853 .discreteQueuePriorities = 2,
854 .pointSizeRange = { 0.0, 8191.875 },
855 .lineWidthRange = { 0.0, 8191.875 },
856 .pointSizeGranularity = (1.0 / 8.0),
857 .lineWidthGranularity = (1.0 / 8.0),
858 .strictLines = false, /* FINISHME */
859 .standardSampleLocations = true,
860 .optimalBufferCopyOffsetAlignment = 128,
861 .optimalBufferCopyRowPitchAlignment = 128,
862 .nonCoherentAtomSize = 64,
863 };
864
865 *pProperties = (VkPhysicalDeviceProperties) {
866 .apiVersion = libresoc_physical_device_api_version(pdevice),
867 .driverVersion = vk_get_driver_version(),
868 .vendorID = 1, //TODO: some dummy value
869 .deviceID = 1, //TODO: dome dummy value
870 .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
871 .limits = limits,
872 .sparseProperties = {0},
873 };
874
875 strcpy(pProperties->deviceName, pdevice->name);
876 memcpy(pProperties->pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
877 }
878
879 static void libresoc_get_physical_device_queue_family_properties(
880 struct libresoc_physical_device* pdevice,
881 uint32_t* pCount,
882 VkQueueFamilyProperties** pQueueFamilyProperties)
883 {
884 int num_queue_families = 1;
885 int idx;
886
887 if (pQueueFamilyProperties == NULL) {
888 *pCount = num_queue_families;
889 return;
890 }
891
892 if (!*pCount)
893 return;
894
895 idx = 0;
896 if (*pCount >= 1) {
897 *pQueueFamilyProperties[idx] = (VkQueueFamilyProperties) {
898 .queueFlags = VK_QUEUE_GRAPHICS_BIT |
899 VK_QUEUE_COMPUTE_BIT |
900 VK_QUEUE_TRANSFER_BIT |
901 VK_QUEUE_SPARSE_BINDING_BIT,
902 .queueCount = 1,
903 .timestampValidBits = 64,
904 .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 },
905 };
906 idx++;
907 }
908
909 *pCount = idx;
910 }
911
912 void
913 libresoc_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
914 uint32_t *pCount,
915 VkQueueFamilyProperties *pQueueFamilyProperties)
916 {
917 if (getenv("LIBRESOC_TRACE")) {
918 fprintf(stderr, "GetPhysicalDeviceQueueFamilyProperites called. \n");
919 }
920 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
921 if (!pQueueFamilyProperties) {
922 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, NULL);
923 return;
924 }
925 VkQueueFamilyProperties *properties[] = {
926 pQueueFamilyProperties + 0,
927 pQueueFamilyProperties + 1,
928 pQueueFamilyProperties + 2,
929 };
930 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, properties);
931 assert(*pCount <= 3);
932 }
933
934 void
935 libresoc_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
936 VkPhysicalDeviceMemoryProperties *pMemoryProperties)
937 {
938 if (getenv("LIBRESOC_TRACE")) {
939 fprintf(stderr, "GetPhysicalDEviceMemoryProperties called. \n");
940 }
941 LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
942
943 *pMemoryProperties = physical_device->memory_properties;
944 /* FIXME: stub */
945 }
946
947 //void
948 //libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
949 //
950 // if (getenv("LIBRESOC_TRACE")) {
951 // fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
952 // }
953 // /* FIXME: stub */
954 //}
955
956 //VkResult
957 // libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
958 //{
959 // if (getenv("LIBRESOC_TRACE")) {
960 // fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
961 // }
962 //
963 // /* FIXME: stub */
964 // return VK_SUCCESS;
965 //}
966 // void
967 // libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
968 // {
969 // if (getenv("LIBRESOC_TRACE")) {
970 // fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
971 // }
972 // /* FIXME: stub */
973 // }
974 PFN_vkVoidFunction
975 libresoc_GetInstanceProcAddr(VkInstance _instance,
976 const char *pName)
977 {
978 if (getenv("LIBRESOC_TRACE")) {
979 fprintf(stderr, "GetInstanceProcAddr called for: %s \n", pName);
980 }
981 LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
982
983 /* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly
984 * when we have to return valid function pointers, NULL, or it's left
985 * undefined. See the table for exact details.
986 */
987 if (pName == NULL)
988 return NULL;
989
990 #define LOOKUP_LIBRESOC_ENTRYPOINT(entrypoint) \
991 if (strcmp(pName, "vk" #entrypoint) == 0) \
992 return (PFN_vkVoidFunction)libresoc_##entrypoint
993
994 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateInstanceExtensionProperties);
995 LOOKUP_LIBRESOC_ENTRYPOINT(CreateInstance);
996 LOOKUP_LIBRESOC_ENTRYPOINT(DestroyInstance);
997 LOOKUP_LIBRESOC_ENTRYPOINT(EnumeratePhysicalDevices);
998 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFeatures);
999 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceFormatProperties);
1000 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceImageFormatProperties);
1001 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceProperties);
1002 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceQueueFamilyProperties);
1003 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceMemoryProperties);
1004 LOOKUP_LIBRESOC_ENTRYPOINT(GetDeviceProcAddr);
1005 LOOKUP_LIBRESOC_ENTRYPOINT(CreateDevice);
1006 LOOKUP_LIBRESOC_ENTRYPOINT(EnumerateDeviceExtensionProperties);
1007 LOOKUP_LIBRESOC_ENTRYPOINT(GetPhysicalDeviceSparseImageFormatProperties);
1008
1009
1010 #undef LOOKUP_LIBRESOC_ENTRYPOINT
1011
1012 if (instance == NULL)
1013 return NULL;
1014
1015 int idx = libresoc_get_instance_entrypoint_index(pName);
1016 if (idx >= 0)
1017 return instance->dispatch.entrypoints[idx];
1018
1019 idx = libresoc_get_physical_device_entrypoint_index(pName);
1020 if (idx >= 0)
1021 return instance->physical_device_dispatch.entrypoints[idx];
1022
1023 idx = libresoc_get_device_entrypoint_index(pName);
1024 if (idx >= 0)
1025 return instance->device_dispatch.entrypoints[idx];
1026
1027 return NULL;
1028 }
1029
1030 /* With version 1+ of the loader interface the ICD should expose
1031 * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
1032 */
1033 PUBLIC
1034 VKAPI_ATTR PFN_vkVoidFunction
1035 VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance,
1036 const char *pName);
1037
1038 PUBLIC
1039 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1040 vk_icdGetInstanceProcAddr(VkInstance instance,
1041 const char* pName)
1042 {
1043 if (getenv("LIBRESOC_TRACE")) {
1044 fprintf(stderr, "vk_icdGetInstanceProcAddr called for: %s \n", pName);
1045 }
1046 return libresoc_GetInstanceProcAddr(instance, pName);
1047 }
1048
1049 PFN_vkVoidFunction
1050 libresoc_GetDeviceProcAddr(VkDevice _device,
1051 const char *pName)
1052 {
1053 if (getenv("LIBRESOC_TRACE")) {
1054 fprintf(stderr, "GetDeviceProcAddr called for: %s \n", pName);
1055 }
1056 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1057
1058 if (!device || !pName)
1059 return NULL;
1060
1061 int idx = libresoc_get_device_entrypoint_index(pName);
1062 if (idx < 0)
1063 return NULL;
1064
1065 return device->dispatch.entrypoints[idx];
1066 }
1067
1068 /* With version 4+ of the loader interface the ICD should expose
1069 * vk_icdGetPhysicalDeviceProcAddr()
1070 */
1071 PUBLIC
1072 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1073 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
1074 const char* pName);
1075
1076 PFN_vkVoidFunction
1077 vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,
1078 const char* pName)
1079 {
1080 if (getenv("LIBRESOC_TRACE")) {
1081 fprintf(stderr, "vk_icdGetPhysicalDeviceProcAddr called for: %s \n", pName);
1082 }
1083 LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
1084
1085 if (!pName || !instance)
1086 return NULL;
1087
1088 int idx = libresoc_get_physical_device_entrypoint_index(pName);
1089 if (idx < 0)
1090 return NULL;
1091
1092 return instance->physical_device_dispatch.entrypoints[idx];
1093 }
1094
1095 VkResult
1096 libresoc_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1097 const char *pLayerName,
1098 uint32_t *pPropertyCount,
1099 VkExtensionProperties *pProperties)
1100 {
1101 if (getenv("LIBRESOC_TRACE")) {
1102 fprintf(stderr, "EnumerateDeviceExtensionProperties called for layer: %s \n", pLayerName);
1103 }
1104 LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
1105 VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
1106
1107 for (int i = 0; i < LIBRESOC_DEVICE_EXTENSION_COUNT; i++) {
1108 if (device->supported_extensions.extensions[i]) {
1109 vk_outarray_append(&out, prop) {
1110 *prop = libresoc_device_extensions[i];
1111 }
1112 }
1113 }
1114
1115 return vk_outarray_status(&out);
1116 }
1117
1118 static void
1119 libresoc_device_init_dispatch(struct libresoc_device *device)
1120 {
1121 const struct libresoc_instance *instance = device->physical_device->instance;
1122 const struct libresoc_device_dispatch_table *dispatch_table_layer = NULL;
1123
1124 for (unsigned i = 0; i < ARRAY_SIZE(device->dispatch.entrypoints); i++) {
1125 /* Vulkan requires that entrypoints for extensions which have not been
1126 * enabled must not be advertised.
1127 */
1128 if (!libresoc_device_entrypoint_is_enabled(i, instance->apiVersion,
1129 &instance->enabled_extensions,
1130 &device->enabled_extensions)) {
1131 device->dispatch.entrypoints[i] = NULL;
1132 } else if (dispatch_table_layer &&
1133 dispatch_table_layer->entrypoints[i]) {
1134 device->dispatch.entrypoints[i] =
1135 dispatch_table_layer->entrypoints[i];
1136 } else {
1137 device->dispatch.entrypoints[i] =
1138 libresoc_device_dispatch_table.entrypoints[i];
1139 }
1140 }
1141 }
1142
1143 static VkResult
1144 check_physical_device_features(VkPhysicalDevice physicalDevice,
1145 const VkPhysicalDeviceFeatures *features)
1146 {
1147 LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
1148 VkPhysicalDeviceFeatures supported_features;
1149 libresoc_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
1150 VkBool32 *supported_feature = (VkBool32 *)&supported_features;
1151 VkBool32 *enabled_feature = (VkBool32 *)features;
1152 unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
1153 for (uint32_t i = 0; i < num_features; i++) {
1154 if (enabled_feature[i] && !supported_feature[i])
1155 return vk_error(physical_device->instance, VK_ERROR_FEATURE_NOT_PRESENT);
1156 }
1157
1158 return VK_SUCCESS;
1159 }
1160 static int libresoc_get_device_extension_index(const char *name)
1161 {
1162 for (unsigned i = 0; i < LIBRESOC_DEVICE_EXTENSION_COUNT; ++i) {
1163 if (strcmp(name, libresoc_device_extensions[i].extensionName) == 0)
1164 return i;
1165 }
1166 return -1;
1167 }
1168
1169 static int
1170 libresoc_queue_init(struct libresoc_device *device, struct libresoc_queue *queue,
1171 uint32_t queue_family_index, int idx,
1172 VkDeviceQueueCreateFlags flags,
1173 const VkDeviceQueueGlobalPriorityCreateInfoEXT *global_priority)
1174 {
1175 queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
1176 queue->device = device;
1177 queue->queue_family_index = queue_family_index;
1178 queue->queue_idx = idx;
1179 queue->flags = flags;
1180 list_inithead(&queue->pending_submissions);
1181 pthread_mutex_init(&queue->pending_mutex, NULL);
1182
1183 pthread_mutex_init(&queue->thread_mutex, NULL);
1184 //queue->thread_submission = NULL;
1185 queue->thread_running = queue->thread_exit = false;
1186 VkResult result = libresoc_create_pthread_cond(&queue->thread_cond);
1187 if (result != VK_SUCCESS)
1188 return vk_error(device->instance, result);
1189
1190 return VK_SUCCESS;
1191 }
1192
1193 static void
1194 libresoc_queue_finish(struct libresoc_queue *queue)
1195 {
1196 //TODO: understand and enable following code
1197 // if (queue->thread_running) {
1198 // p_atomic_set(&queue->thread_exit, true);
1199 // pthread_cond_broadcast(&queue->thread_cond);
1200 // pthread_join(queue->submission_thread, NULL);
1201 // }
1202 // pthread_cond_destroy(&queue->thread_cond);
1203 // pthread_mutex_destroy(&queue->pending_mutex);
1204 // pthread_mutex_destroy(&queue->thread_mutex);
1205 //
1206 // if (queue->hw_ctx)
1207 // queue->device->ws->ctx_destroy(queue->hw_ctx);
1208 //
1209 // if (queue->initial_full_flush_preamble_cs)
1210 // queue->device->ws->cs_destroy(queue->initial_full_flush_preamble_cs);
1211 // if (queue->initial_preamble_cs)
1212 // queue->device->ws->cs_destroy(queue->initial_preamble_cs);
1213 // if (queue->continue_preamble_cs)
1214 // queue->device->ws->cs_destroy(queue->continue_preamble_cs);
1215 // if (queue->descriptor_bo)
1216 // queue->device->ws->buffer_destroy(queue->descriptor_bo);
1217 // if (queue->scratch_bo)
1218 // queue->device->ws->buffer_destroy(queue->scratch_bo);
1219 // if (queue->esgs_ring_bo)
1220 // queue->device->ws->buffer_destroy(queue->esgs_ring_bo);
1221 // if (queue->gsvs_ring_bo)
1222 // queue->device->ws->buffer_destroy(queue->gsvs_ring_bo);
1223 // if (queue->tess_rings_bo)
1224 // queue->device->ws->buffer_destroy(queue->tess_rings_bo);
1225 // if (queue->gds_bo)
1226 // queue->device->ws->buffer_destroy(queue->gds_bo);
1227 // if (queue->gds_oa_bo)
1228 // queue->device->ws->buffer_destroy(queue->gds_oa_bo);
1229 // if (queue->compute_scratch_bo)
1230 // queue->device->ws->buffer_destroy(queue->compute_scratch_bo);
1231 }
1232 VkResult
1233 libresoc_CreateDevice(VkPhysicalDevice physicalDevice,
1234 const VkDeviceCreateInfo *pCreateInfo,
1235 const VkAllocationCallbacks *pAllocator,
1236 VkDevice *pDevice)
1237 {
1238 if (getenv("LIBRESOC_TRACE")) {
1239 fprintf(stderr, "CreateDevice called \n");
1240 }
1241 LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
1242 VkResult result;
1243 struct libresoc_device *device;
1244
1245 /* Check enabled features */
1246 if (pCreateInfo->pEnabledFeatures) {
1247 result = check_physical_device_features(physicalDevice,
1248 pCreateInfo->pEnabledFeatures);
1249 if (result != VK_SUCCESS)
1250 return result;
1251 }
1252
1253 device = vk_zalloc2(&physical_device->instance->alloc, pAllocator,
1254 sizeof(*device), 8,
1255 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1256 if (!device)
1257 return vk_error(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1258
1259 vk_device_init(&device->vk, pCreateInfo,
1260 &physical_device->instance->alloc, pAllocator);
1261
1262 device->instance = physical_device->instance;
1263 device->physical_device = physical_device;
1264
1265 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
1266 const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
1267 int index = libresoc_get_device_extension_index(ext_name);
1268 if (index < 0 || !physical_device->supported_extensions.extensions[index]) {
1269 vk_free(&device->vk.alloc, device);
1270 return vk_error(physical_device->instance, VK_ERROR_EXTENSION_NOT_PRESENT);
1271 }
1272
1273 device->enabled_extensions.extensions[index] = true;
1274 }
1275
1276 libresoc_device_init_dispatch(device);
1277
1278 for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
1279 const VkDeviceQueueCreateInfo *queue_create = &pCreateInfo->pQueueCreateInfos[i];
1280 uint32_t qfi = queue_create->queueFamilyIndex;
1281 const VkDeviceQueueGlobalPriorityCreateInfoEXT *global_priority =
1282 vk_find_struct_const(queue_create->pNext, DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT);
1283
1284
1285 device->queues[qfi] = vk_alloc(&device->vk.alloc,
1286 queue_create->queueCount * sizeof(struct libresoc_queue), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1287 if (!device->queues[qfi]) {
1288 result = VK_ERROR_OUT_OF_HOST_MEMORY;
1289 goto fail;
1290 }
1291
1292 memset(device->queues[qfi], 0, queue_create->queueCount * sizeof(struct libresoc_queue));
1293
1294 device->queue_count[qfi] = queue_create->queueCount;
1295
1296 for (unsigned q = 0; q < queue_create->queueCount; q++) {
1297 result = libresoc_queue_init(device, &device->queues[qfi][q],
1298 qfi, q, queue_create->flags,
1299 global_priority);
1300 if (result != VK_SUCCESS)
1301 goto fail;
1302 }
1303 }
1304
1305 if (result != VK_SUCCESS)
1306 goto fail;
1307
1308 VkPipelineCacheCreateInfo ci;
1309 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1310 ci.pNext = NULL;
1311 ci.flags = 0;
1312 ci.pInitialData = NULL;
1313 ci.initialDataSize = 0;
1314 VkPipelineCache pc;
1315 result = libresoc_CreatePipelineCache(libresoc_device_to_handle(device),
1316 &ci, NULL, &pc);
1317 if (result != VK_SUCCESS)
1318 goto fail;
1319
1320 *pDevice = libresoc_device_to_handle(device);
1321 return VK_SUCCESS;
1322
1323 fail:
1324 libresoc_DestroyPipelineCache(libresoc_device_to_handle(device), pc, NULL);
1325 for (unsigned i = 0; i < LIBRESOC_MAX_QUEUE_FAMILIES; i++) {
1326 for (unsigned q = 0; q < device->queue_count[i]; q++)
1327 libresoc_queue_finish(&device->queues[i][q]);
1328 if (device->queue_count[i])
1329 vk_free(&device->vk.alloc, device->queues[i]);
1330 }
1331
1332 vk_free(&device->vk.alloc, device);
1333 return result;
1334 }
1335
1336 void
1337 libresoc_DestroyDevice(VkDevice _device,
1338 const VkAllocationCallbacks *pAllocator)
1339 {
1340 if (getenv("LIBRESOC_TRACE")) {
1341 fprintf(stderr, "DestroyDevice called. \n");
1342 }
1343 /* FIXME: stub */
1344 }
1345
1346 void libresoc_GetDeviceQueue(
1347 VkDevice _device,
1348 uint32_t queueFamilyIndex,
1349 uint32_t queueIndex,
1350 VkQueue* pQueue)
1351 {
1352 if (getenv("LIBRESOC_TRACE")) {
1353 fprintf(stderr, "GetDeviceQueue called. \n");
1354 }
1355 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1356 struct libresoc_queue *queue;
1357
1358 queue = &device->queues[queueFamilyIndex][queueIndex];
1359 *pQueue = libresoc_queue_to_handle(queue);
1360 }
1361
1362 VkResult libresoc_QueueWaitIdle(
1363 VkQueue _queue)
1364 {
1365 LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
1366
1367 pthread_mutex_lock(&queue->pending_mutex);
1368 while (!list_is_empty(&queue->pending_submissions)) {
1369 pthread_cond_wait(&queue->device->timeline_cond, &queue->pending_mutex);
1370 }
1371 pthread_mutex_unlock(&queue->pending_mutex);
1372
1373 return VK_SUCCESS;
1374 }
1375
1376 VkResult libresoc_DeviceWaitIdle(
1377 VkDevice _device)
1378 {
1379 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1380
1381 for (unsigned i = 0; i < LIBRESOC_MAX_QUEUE_FAMILIES; i++) {
1382 for (unsigned q = 0; q < device->queue_count[i]; q++) {
1383 VkResult result =
1384 libresoc_QueueWaitIdle(libresoc_queue_to_handle(&device->queues[i][q]));
1385
1386 if (result != VK_SUCCESS)
1387 return result;
1388 }
1389 }
1390 return VK_SUCCESS;
1391 }
1392
1393 void libresoc_GetPhysicalDeviceProperties2(
1394 VkPhysicalDevice physicalDevice,
1395 VkPhysicalDeviceProperties2 *pProperties)
1396 {
1397 // LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
1398 libresoc_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
1399 //TODO: add more stuffs when required
1400 }
1401
1402 void libresoc_GetPhysicalDeviceFeatures2(
1403 VkPhysicalDevice physicalDevice,
1404 VkPhysicalDeviceFeatures2 *pFeatures)
1405 {
1406 // LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
1407 libresoc_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
1408 }
1409
1410 void libresoc_GetPhysicalDeviceQueueFamilyProperties2(
1411 VkPhysicalDevice physicalDevice,
1412 uint32_t* pCount,
1413 VkQueueFamilyProperties2 *pQueueFamilyProperties)
1414 {
1415 LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
1416 if (!pQueueFamilyProperties) {
1417 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, NULL);
1418 return;
1419 }
1420 VkQueueFamilyProperties *properties[] = {
1421 &pQueueFamilyProperties[0].queueFamilyProperties,
1422 &pQueueFamilyProperties[1].queueFamilyProperties,
1423 &pQueueFamilyProperties[2].queueFamilyProperties,
1424 };
1425 libresoc_get_physical_device_queue_family_properties(pdevice, pCount, properties);
1426 assert(*pCount <= 3);
1427 }
1428
1429 static void
1430 libresoc_get_memory_budget_properties(VkPhysicalDevice physicalDevice,
1431 VkPhysicalDeviceMemoryBudgetPropertiesEXT *memoryBudget)
1432 {
1433 //TODO: stub
1434 }
1435
1436 void libresoc_GetPhysicalDeviceMemoryProperties2(
1437 VkPhysicalDevice physicalDevice,
1438 VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
1439 {
1440 libresoc_GetPhysicalDeviceMemoryProperties(physicalDevice,
1441 &pMemoryProperties->memoryProperties);
1442
1443 VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget =
1444 vk_find_struct(pMemoryProperties->pNext,
1445 PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT);
1446 if (memory_budget)
1447 libresoc_get_memory_budget_properties(physicalDevice, memory_budget);
1448 }
1449
1450 VkResult libresoc_CreateSemaphore(
1451 VkDevice _device,
1452 const VkSemaphoreCreateInfo* pCreateInfo,
1453 const VkAllocationCallbacks* pAllocator,
1454 VkSemaphore* pSemaphore)
1455 {
1456 //TODO: minimal things as of now, add more complex code as required
1457 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1458 struct libresoc_semaphore *sem = vk_alloc2(&device->vk.alloc, pAllocator,
1459 sizeof(*sem), 8,
1460 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1461 if (!sem)
1462 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1463
1464 vk_object_base_init(&device->vk, &sem->base,
1465 VK_OBJECT_TYPE_SEMAPHORE);
1466
1467 *pSemaphore = libresoc_semaphore_to_handle(sem);
1468 return VK_SUCCESS;
1469 }
1470
1471 void libresoc_GetImageMemoryRequirements(
1472 VkDevice _device,
1473 VkImage _image,
1474 VkMemoryRequirements* pMemoryRequirements)
1475 {
1476 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1477 LIBRESOC_FROM_HANDLE(libresoc_image, image, _image);
1478
1479 pMemoryRequirements->memoryTypeBits = (1u << device->physical_device->memory_properties.memoryTypeCount) - 1;
1480
1481 pMemoryRequirements->size = image->size;
1482 pMemoryRequirements->alignment = image->alignment;
1483 }
1484
1485 void libresoc_GetImageMemoryRequirements2(
1486 VkDevice device,
1487 const VkImageMemoryRequirementsInfo2 *pInfo,
1488 VkMemoryRequirements2 *pMemoryRequirements)
1489 {
1490 libresoc_GetImageMemoryRequirements(device, pInfo->image,
1491 &pMemoryRequirements->memoryRequirements);
1492 }
1493
1494 VkResult libresoc_BindImageMemory2(VkDevice device,
1495 uint32_t bindInfoCount,
1496 const VkBindImageMemoryInfo *pBindInfos)
1497 {
1498 for (uint32_t i = 0; i < bindInfoCount; ++i) {
1499 LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, pBindInfos[i].memory);
1500 LIBRESOC_FROM_HANDLE(libresoc_image, image, pBindInfos[i].image);
1501
1502 if (mem) {
1503 image->bytes = mem->bytes;
1504 // image->offset = pBindInfos[i].memoryOffset;
1505 } else {
1506 // image->bo = NULL;
1507 // image->offset = 0;
1508 }
1509 }
1510 return VK_SUCCESS;
1511 }
1512
1513
1514 VkResult libresoc_BindImageMemory(
1515 VkDevice device,
1516 VkImage image,
1517 VkDeviceMemory memory,
1518 VkDeviceSize memoryOffset)
1519 {
1520 const VkBindImageMemoryInfo info = {
1521 .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
1522 .image = image,
1523 .memory = memory,
1524 .memoryOffset = memoryOffset
1525 };
1526
1527 return libresoc_BindImageMemory2(device, 1, &info);
1528 }
1529
1530 // static VkResult libresoc_queue_submit(struct libresoc_queue *queue,
1531 // const struct libresoc_queue_submission *submission)
1532 // {
1533 // return VK_SUCCESS;
1534 // struct libresoc_deferred_queue_submission *deferred = NULL;
1535
1536 // VkResult result = libresoc_create_deferred_submission(queue, submission, &deferred);
1537 // if (result != VK_SUCCESS)
1538 // return result;
1539
1540 // struct list_head processing_list;
1541 // list_inithead(&processing_list);
1542
1543 // result = libresoc_queue_enqueue_submission(deferred, &processing_list);
1544 // if (result != VK_SUCCESS) {
1545 // /* If anything is in the list we leak. */
1546 // assert(list_is_empty(&processing_list));
1547 // return result;
1548 // }
1549 // return libresoc_process_submissions(&processing_list);
1550 // }
1551
1552 /* Signals fence as soon as all the work currently put on queue is done. */
1553 // static VkResult libresoc_signal_fence(struct libresoc_queue *queue,
1554 // VkFence fence)
1555 // {
1556 // return libresoc_queue_submit(queue, &(struct libresoc_queue_submission) {
1557 // .fence = fence
1558 // });
1559 // }
1560
1561 // static bool libresoc_submit_has_effects(const VkSubmitInfo *info)
1562 // {
1563 // return info->commandBufferCount ||
1564 // info->waitSemaphoreCount ||
1565 // info->signalSemaphoreCount;
1566 // }
1567
1568 static int double_triarea(const struct int4 *a, const struct int4 *b, const struct int4 *c)
1569 {
1570 return (b->x - a->x) * (c->y - a->y) - (b->y - a->y) * (c->x - a->x);
1571 }
1572
1573 static void MinMax(struct int4 *coords, struct int4 *minwin, struct int4 *maxwin)
1574 {
1575 minwin->x = INT_MAX;
1576 minwin->y = INT_MAX;
1577 minwin->z = INT_MAX;
1578 minwin->w = INT_MAX;
1579 maxwin->x = INT_MIN;
1580 maxwin->y = INT_MIN;
1581 maxwin->z = INT_MIN;
1582 maxwin->w = INT_MIN;
1583
1584 for(int i = 0; i < 3; i++)
1585 {
1586 for(int c = 0; c < 4; c++)
1587 {
1588 minwin->v[c] = (minwin->v[c] < coords[i].v[c]) ? minwin->v[c] : coords[i].v[c];
1589 maxwin->v[c] = (maxwin->v[c] > coords[i].v[c]) ? maxwin->v[c] : coords[i].v[c];
1590 }
1591 }
1592 }
1593
1594 static float clamp01(float in)
1595 {
1596 return in > 1.0f ? 1.0f : (in < 0.0f ? 0.0f : in);
1597 }
1598
1599 static void ProcessTriangles(struct TriangleWork *work)
1600 {
1601 struct GPUState *state = work->state;
1602 LIBRESOC_FROM_HANDLE(libresoc_image, img, state->col[0]);
1603 LIBRESOC_FROM_HANDLE(libresoc_pipeline, pipeline, state->pipeline);
1604 const uint32_t w = img->width;
1605 const uint32_t h = img->height;
1606 byte *bytes = img->bytes;
1607
1608 for(int y = work->minwin.y; y < work->maxwin.y; y++)
1609 {
1610 for(int x = work->minwin.x; x < work->maxwin.x; x++)
1611 {
1612 const int PAx = work->tri[0].x - x;
1613 const int PAy = work->tri[0].y - y;
1614
1615 const int ux = (work->ACx * PAy) - (work->ACy * PAx);
1616 const int uy = (PAx * work->ABy) - (PAy * work->ABx);
1617
1618 struct int4 b;
1619 b.x = (work->area2 - (ux + uy));
1620 b.y = ux;
1621 b.z = uy;
1622 b.w = 0;
1623
1624 // if (b.x >= 0 && b.y >= 0 && b.z >= 0)
1625 // {
1626 struct float4 n;
1627 n.x = (float)b.x;
1628 n.y = (float)b.y;
1629 n.z = (float)b.z;
1630 n.w = 0.0f;
1631 float pixdepth = n.x * work->depth.x + n.y * work->depth.y + n.z * work->depth.z;
1632
1633 n.x *= work->invw.x;
1634 n.y *= work->invw.y;
1635 n.z *= work->invw.z;
1636
1637 float invlen = 1.0f / (n.x + n.y + n.z);
1638 n.x *= invlen;
1639 n.y *= invlen;
1640 n.z *= invlen;
1641
1642 struct float4 pix;
1643 const int bpp = 4;
1644 pipeline->fs(state, pixdepth, &n, work->vsout, &pix);
1645 bytes[(y * w + x) * bpp + 2] = (byte)(clamp01(pix.x) * 255.0f);
1646 bytes[(y * w + x) * bpp + 1] = (byte)(clamp01(pix.y) * 255.0f);
1647 bytes[(y * w + x) * bpp + 0] = (byte)(clamp01(pix.z) * 255.0f);
1648 // }
1649
1650 }
1651 }
1652 }
1653
1654 static uint32_t GetIndex(struct GPUState *state, uint32_t vertexIndex, bool indexed)
1655 {
1656 LIBRESOC_FROM_HANDLE(libresoc_buffer, buf, state->ib.buffer);
1657 if(!indexed)
1658 return vertexIndex;
1659
1660 const byte *ib = buf->bytes + state->ib.offset;
1661
1662 if(state->ib.indexType == VK_INDEX_TYPE_UINT16)
1663 {
1664 uint16_t *i16 = (uint16_t *)ib;
1665 i16 += vertexIndex;
1666 return *i16;
1667 }
1668 else
1669 {
1670 uint32_t *i32 = (uint32_t *)ib;
1671 i32 += vertexIndex;
1672 return *i32;
1673 }
1674 }
1675
1676 static void ClearTarget(VkImage target, const VkClearColorValue *col)
1677 {
1678
1679 LIBRESOC_FROM_HANDLE(libresoc_image, img, target);
1680 byte *bits = img->bytes;
1681 const uint32_t w = img->width;
1682 const uint32_t h = img->height;
1683 const uint32_t bpp = 4;
1684
1685 byte eval[4];
1686 eval[2] = (byte)(col->float32[0] * 255.0f);
1687 eval[1] = (byte)(col->float32[1] * 255.0f);
1688 eval[0] = (byte)(col->float32[2] * 255.0f);
1689 eval[3] = (byte)(col->float32[3] * 255.0f);
1690
1691 if(bpp == 1)
1692 {
1693 memset(bits, eval[2], w * h);
1694 }
1695 else if(bpp == 4)
1696 {
1697 for(uint32_t y = 0; y < h; y++)
1698 {
1699 for(uint32_t x = 0; x < w; x++)
1700 {
1701 memcpy(&bits[(y * w + x) * bpp], eval, 4);
1702 }
1703 }
1704 }
1705 }
1706
1707 static void DrawTriangles(struct GPUState *state, int numVerts, uint32_t first, bool indexed)
1708 {
1709 LIBRESOC_FROM_HANDLE(libresoc_image, img, state->col[0]);
1710 LIBRESOC_FROM_HANDLE(libresoc_pipeline, pipeline, state->pipeline);
1711 const uint32_t w = img->width;
1712 const uint32_t h = img->height;
1713 struct VertexCacheEntry *vertices;
1714 vertices = (struct VertexCacheEntry *)malloc(sizeof(struct VertexCacheEntry) * numVerts);
1715
1716 int lastVert = numVerts - 3;
1717 uint32_t vertexIndex = first;
1718 // Shed Triangles
1719 struct VertexCacheEntry tri[4];
1720 // For now we support only VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1721 for(int v = 0; v <= lastVert; v += 3)
1722 {
1723 pipeline->vs(state, GetIndex(state, vertexIndex, indexed), &tri[0]);
1724 vertexIndex++;
1725 pipeline->vs(state, GetIndex(state, vertexIndex, indexed), &tri[1]);
1726 vertexIndex++;
1727 pipeline->vs(state, GetIndex(state, vertexIndex, indexed), &tri[2]);
1728 vertexIndex++;
1729 vertices[v] = tri[0];
1730 vertices[v + 1] = tri[1];
1731 vertices[v + 2] = tri[2];
1732 }
1733
1734 struct int4 *winCords;
1735 winCords = (struct int4 *)malloc(sizeof(struct int4) * numVerts);
1736 // ToWindow
1737 for(int v =0; v <= lastVert; ++v)
1738 {
1739 struct int4 win;
1740
1741 win.x = (int)((vertices[v].position.x / vertices[v].position.w + 1.0f) * 0.5f * w);
1742 win.y = (int)((vertices[v].position.y * -1.0f / vertices[v].position.w + 1.0f) * 0.5f * h);
1743 winCords[v] = win;
1744 }
1745
1746
1747 for(int i = 0; i <= lastVert; i += 3)
1748 {
1749
1750 // culling can be done here
1751 int area2 = double_triarea(&winCords[i + 0], &winCords[i + 1], &winCords[i + 2]);
1752
1753
1754 int area2_flipped = area2;
1755 struct TriangleWork work;
1756
1757 struct int4 minwin, maxwin;
1758 MinMax(&winCords[i], &minwin, &maxwin);
1759
1760 minwin.x = (0 > minwin.x) ? 0 : minwin.x;
1761 minwin.y = (0 > minwin.y) ? 0 : minwin.y;
1762 maxwin.x = ((int)(w - 1) < maxwin.x) ? (int)(w - 1) : maxwin.x;
1763 maxwin.y = ((int)(h - 1) < maxwin.y) ? (int)(h - 1) : maxwin.y;
1764
1765 work.state = state;
1766 work.ABx = winCords[i + 1].x - winCords[i + 0].x;
1767 work.ABy = winCords[i + 1].y - winCords[i + 0].y;
1768 work.ACx = winCords[i + 2].x - winCords[i + 0].x;
1769 work.ACy = winCords[i + 2].y - winCords[i + 0].y;
1770 work.vsout = &vertices[i];
1771 work.tri = &winCords[i];
1772 // work.barymul = barymul;
1773 work.area2 = area2;
1774 work.invarea = 1.0f / (float)(area2_flipped);
1775 work.invw.x = 1.0f / vertices[i + 0].position.w;
1776 work.invw.y = 1.0f / vertices[i + 1].position.w;
1777 work.invw.z = 1.0f / vertices[i + 2].position.w;
1778 work.invw.w = 0.0f;
1779 work.depth.x = vertices[i + 0].position.z * work.invw.x;
1780 work.depth.y = vertices[i + 1].position.z * work.invw.y;
1781 work.depth.z = vertices[i + 2].position.z * work.invw.z;
1782 work.depth.w = 0.0f;
1783
1784 const int blockSize = 32;
1785
1786 int xblocks = 1 + (maxwin.x - minwin.x) / blockSize;
1787 int yblocks = 1 + (maxwin.y - minwin.y) / blockSize;
1788
1789 {
1790
1791 for(int x = 0; x < xblocks; x++)
1792 {
1793 for(int y = 0; y < yblocks; y++)
1794 {
1795 work.minwin = minwin;
1796 work.minwin.x += blockSize * x;
1797 work.minwin.y += blockSize * y;
1798
1799 work.maxwin.x = (maxwin.x < work.minwin.x + blockSize) ? maxwin.x : work.minwin.x + blockSize;
1800 work.maxwin.y = (maxwin.y < work.minwin.y + blockSize) ? maxwin.y : work.minwin.y + blockSize;
1801 }
1802 }
1803 }
1804 // rasterize
1805 ProcessTriangles(&work);
1806
1807 }
1808 }
1809
1810 static void execute(VkCommandBuffer commandBuffer)
1811 {
1812 LIBRESOC_FROM_HANDLE(libresoc_cmd_buffer, cmd_buffer, commandBuffer);
1813 struct GPUState state = {0};
1814 list_for_each_entry(struct libresoc_cmd, lcmd,
1815 &cmd_buffer->cmd.link, link) {
1816 int *commandId = (int *)&lcmd->command;
1817 switch (*commandId) {
1818 case BeginRenderPassID:
1819 {
1820 LIBRESOC_FROM_HANDLE(libresoc_render_pass, render_pass, lcmd->command.beginRenderPass.renderPass);
1821 LIBRESOC_FROM_HANDLE(libresoc_framebuffer, frame_buffer, lcmd->command.beginRenderPass.framebuffer);
1822 LIBRESOC_FROM_HANDLE(libresoc_image, img, state.col[0]);
1823 struct libresoc_subpass subpass = render_pass->subpasses[0];
1824 struct libresoc_subpass_attachment attachment = subpass.attachments[0];
1825
1826 state.col[0] = (struct VkImage_T *)frame_buffer->attachments[attachment.attachment]->image;
1827
1828 int clearIdx = 0;
1829
1830 if(attachment.clear)
1831 {
1832 ClearTarget(state.col[0], &lcmd->command.beginRenderPass.clearval[clearIdx++].color);
1833 }
1834
1835 // VkRenderPass_T::Attachment &depth = subpass.depthAttachment;
1836
1837 // if(depth.idx >= 0)
1838 // {
1839 // state.depth = data.framebuffer->attachments[depth.idx]->image;
1840
1841 // if(depth.clear)
1842 // {
1843 // ClearTarget(state.depth, data.clearval[clearIdx++].depthStencil);
1844 // }
1845 // }
1846 break;
1847 }
1848 case EndRenderPassID:
1849 {
1850 state.col[0] = VK_NULL_HANDLE;
1851 break;
1852 }
1853 case BindPipelineID:
1854 {
1855 state.pipeline = lcmd->command.bindPipeline.pipeline;
1856 break;
1857 }
1858 case BindDescriptorSetsID:
1859 {
1860 state.sets[lcmd->command.bindDescriptorSets.idx] = lcmd->command.bindDescriptorSets.set;
1861 break;
1862 }
1863 case BindVBID:
1864 {
1865 state.vbs[lcmd->command.bindVB.slot].buffer = lcmd->command.bindVB.buffer;
1866 state.vbs[lcmd->command.bindVB.slot].offset = lcmd->command.bindVB.offset;
1867 break;
1868 }
1869 case BindIBID:
1870 {
1871 state.ib.buffer = lcmd->command.bindIB.buffer;
1872 state.ib.offset = lcmd->command.bindIB.offset;
1873 state.ib.indexType = lcmd->command.bindIB.indexType;
1874 break;
1875 }
1876 case SetViewportID:
1877 {
1878 state.view = lcmd->command.setViewport.view;
1879 break;
1880 }
1881 case SetScissorsID:
1882 break;
1883 case PushConstantsID:
1884 {
1885 memcpy(state.pushconsts + lcmd->command.pushConstants.offset,
1886 lcmd->command.pushConstants.values,
1887 lcmd->command.pushConstants.size);
1888 break;
1889 }
1890 case DrawID:
1891 {
1892 DrawTriangles(&state, lcmd->command.draw.vertexCount, lcmd->command.draw.firstVertex, false);
1893 break;
1894 }
1895 case DrawIndexedID:
1896 break;
1897 case CopyBuf2ImgID:
1898 break;
1899 case CopyBufID:
1900 break;
1901 case PipelineBarrierID:
1902 break;
1903 }
1904 }
1905 }
1906
1907 VkResult libresoc_QueueSubmit(
1908 VkQueue _queue,
1909 uint32_t submitCount,
1910 const VkSubmitInfo* pSubmits,
1911 VkFence fence)
1912 {
1913 // LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
1914 for(uint32_t i = 0; i < submitCount; i++)
1915 {
1916 for(uint32_t c = 0; c < pSubmits[i].commandBufferCount; c++)
1917 {
1918 execute(pSubmits[i].pCommandBuffers[c]);
1919 }
1920 }
1921 return VK_SUCCESS;
1922 }
1923
1924 VkResult libresoc_CreateFence(
1925 VkDevice _device,
1926 const VkFenceCreateInfo* pCreateInfo,
1927 const VkAllocationCallbacks* pAllocator,
1928 VkFence* pFence)
1929 {
1930 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1931 // const VkExportFenceCreateInfo *export =
1932 // vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO);
1933 // VkExternalFenceHandleTypeFlags handleTypes =
1934 // export ? export->handleTypes : 0;
1935 struct libresoc_fence *fence;
1936
1937 fence = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*fence), 8,
1938 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1939 if (!fence)
1940 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1941
1942 vk_object_base_init(&device->vk, &fence->base, VK_OBJECT_TYPE_FENCE);
1943
1944 // if (device->always_use_syncobj || handleTypes) {
1945 // fence->permanent.kind = LIBRESOC_FENCE_SYNCOBJ;
1946
1947 // bool create_signaled = false;
1948 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1949 // create_signaled = true;
1950
1951 // int ret = device->ws->create_syncobj(device->ws, create_signaled,
1952 // &fence->permanent.syncobj);
1953 // if (ret) {
1954 // libresoc_destroy_fence(device, pAllocator, fence);
1955 // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1956 // }
1957 // } else {
1958 // fence->permanent.kind = LIBRESOC_FENCE_WINSYS;
1959
1960 // fence->permanent.fence = device->ws->create_fence();
1961 // if (!fence->permanent.fence) {
1962 // vk_free2(&device->vk.alloc, pAllocator, fence);
1963 // libresoc_destroy_fence(device, pAllocator, fence);
1964 // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1965 // }
1966 // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
1967 // device->ws->signal_fence(fence->permanent.fence);
1968 // }
1969
1970 *pFence = libresoc_fence_to_handle(fence);
1971
1972 return VK_SUCCESS;
1973 }
1974
1975 VkResult libresoc_MapMemory(
1976 VkDevice _device,
1977 VkDeviceMemory _memory,
1978 VkDeviceSize offset,
1979 VkDeviceSize size,
1980 VkMemoryMapFlags flags,
1981 void** ppData)
1982 {
1983 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
1984 LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _memory);
1985
1986 if (mem == NULL) {
1987 *ppData = NULL;
1988 return VK_SUCCESS;
1989 }
1990
1991 if (mem->user_ptr)
1992 *ppData = mem->user_ptr;
1993 else
1994 *ppData = mem->bytes;
1995 //*ppData = device->ws->buffer_map(mem->bo);
1996
1997 if (*ppData) {
1998 *ppData += offset;
1999 return VK_SUCCESS;
2000 }
2001
2002 return vk_error(device->instance, VK_ERROR_MEMORY_MAP_FAILED);
2003 }
2004
2005 void libresoc_UnmapMemory(
2006 VkDevice _device,
2007 VkDeviceMemory _memory)
2008 {
2009 // LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
2010 LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _memory);
2011
2012 if (mem == NULL)
2013 return;
2014
2015 // if (mem->user_ptr == NULL)
2016 // device->ws->buffer_unmap(mem->bo);
2017 }
2018
2019 VkResult libresoc_WaitForFences(
2020 VkDevice _device,
2021 uint32_t fenceCount,
2022 const VkFence* pFences,
2023 VkBool32 waitAll,
2024 uint64_t timeout)
2025 {
2026 //TODO: stub
2027 return VK_SUCCESS;
2028 }
2029
2030 VkResult libresoc_ResetFences(VkDevice _device,
2031 uint32_t fenceCount,
2032 const VkFence *pFences)
2033 {
2034
2035 //TODO: stub
2036 return VK_SUCCESS;
2037 }
2038
2039 VkResult libresoc_CreateFramebuffer(
2040 VkDevice _device,
2041 const VkFramebufferCreateInfo* pCreateInfo,
2042 const VkAllocationCallbacks* pAllocator,
2043 VkFramebuffer* pFramebuffer)
2044 {
2045 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
2046 struct libresoc_framebuffer *framebuffer;
2047 const VkFramebufferAttachmentsCreateInfo *imageless_create_info =
2048 vk_find_struct_const(pCreateInfo->pNext,
2049 FRAMEBUFFER_ATTACHMENTS_CREATE_INFO);
2050
2051 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
2052
2053 size_t size = sizeof(*framebuffer);
2054 if (!imageless_create_info)
2055 size += sizeof(struct libresoc_image_view*) * pCreateInfo->attachmentCount;
2056 framebuffer = vk_alloc2(&device->vk.alloc, pAllocator, size, 8,
2057 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2058 if (framebuffer == NULL)
2059 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2060
2061 vk_object_base_init(&device->vk, &framebuffer->base,
2062 VK_OBJECT_TYPE_FRAMEBUFFER);
2063
2064 framebuffer->attachment_count = pCreateInfo->attachmentCount;
2065 framebuffer->width = pCreateInfo->width;
2066 framebuffer->height = pCreateInfo->height;
2067 framebuffer->layers = pCreateInfo->layers;
2068 if (imageless_create_info) {
2069 for (unsigned i = 0; i < imageless_create_info->attachmentImageInfoCount; ++i) {
2070 const VkFramebufferAttachmentImageInfo *attachment =
2071 imageless_create_info->pAttachmentImageInfos + i;
2072 framebuffer->width = MIN2(framebuffer->width, attachment->width);
2073 framebuffer->height = MIN2(framebuffer->height, attachment->height);
2074 framebuffer->layers = MIN2(framebuffer->layers, attachment->layerCount);
2075 }
2076 } else {
2077 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
2078 VkImageView _iview = pCreateInfo->pAttachments[i];
2079 struct libresoc_image_view *iview = libresoc_image_view_from_handle(_iview);
2080 framebuffer->attachments[i] = iview;
2081 framebuffer->width = MIN2(framebuffer->width, iview->extent.width);
2082 framebuffer->height = MIN2(framebuffer->height, iview->extent.height);
2083 framebuffer->layers = MIN2(framebuffer->layers, libresoc_surface_max_layer_count(iview));
2084 }
2085 }
2086
2087 *pFramebuffer = libresoc_framebuffer_to_handle(framebuffer);
2088 return VK_SUCCESS;
2089 }
2090
2091 void libresoc_DestroyFramebuffer(
2092 VkDevice _device,
2093 VkFramebuffer _fb,
2094 const VkAllocationCallbacks* pAllocator)
2095 {}
2096
2097 VkResult libresoc_CreateBuffer(
2098 VkDevice _device,
2099 const VkBufferCreateInfo* pCreateInfo,
2100 const VkAllocationCallbacks* pAllocator,
2101 VkBuffer* pBuffer)
2102 {
2103 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
2104 struct libresoc_buffer *buffer;
2105
2106 buffer = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*buffer), 8,
2107 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
2108 if (buffer == NULL)
2109 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2110
2111 vk_object_base_init(&device->vk, &buffer->base, VK_OBJECT_TYPE_BUFFER);
2112
2113 buffer->size = pCreateInfo->size;
2114 buffer->bytes = NULL;
2115 *pBuffer = libresoc_buffer_to_handle(buffer);
2116
2117 return VK_SUCCESS;
2118 }
2119
2120 void libresoc_DestroyBuffer(
2121 VkDevice _device,
2122 VkBuffer _buffer,
2123 const VkAllocationCallbacks* pAllocator)
2124 {}
2125
2126 void libresoc_GetBufferMemoryRequirements(
2127 VkDevice _device,
2128 VkBuffer _buffer,
2129 VkMemoryRequirements* pMemoryRequirements)
2130 {
2131 LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
2132 LIBRESOC_FROM_HANDLE(libresoc_buffer, buffer, _buffer);
2133
2134 pMemoryRequirements->memoryTypeBits = (1u << device->physical_device->memory_properties.memoryTypeCount) - 1;
2135
2136 pMemoryRequirements->alignment = 16;
2137
2138 pMemoryRequirements->size = align64(buffer->size, pMemoryRequirements->alignment);
2139 }
2140
2141 VkResult libresoc_BindBufferMemory(
2142 VkDevice device,
2143 VkBuffer _buffer,
2144 VkDeviceMemory _memory,
2145 VkDeviceSize memoryOffset)
2146 {
2147 LIBRESOC_FROM_HANDLE(libresoc_buffer, buffer, _buffer);
2148 LIBRESOC_FROM_HANDLE(libresoc_device_memory, memory, _memory);
2149 buffer->bytes = memory->bytes + memoryOffset;
2150 return VK_SUCCESS;
2151 }
2152
2153 void libresoc_DestroyFence(
2154 VkDevice _device,
2155 VkFence _fence,
2156 const VkAllocationCallbacks* pAllocator)
2157 {}
2158
2159
2160 void libresoc_DestroySemaphore(
2161 VkDevice _device,
2162 VkSemaphore _semaphore,
2163 const VkAllocationCallbacks* pAllocator)
2164 {}