#include <sys/sysinfo.h>
#include <unistd.h>
+#include "util/debug.h"
+#include "util/driconf.h"
#include "libresoc_private.h"
#include "vk_util.h"
+#include "vk_alloc.h"
+
+struct libresoc_deferred_queue_submission {
+ struct libresoc_queue *queue;
+ VkCommandBuffer *cmd_buffers;
+ uint32_t cmd_buffer_count;
+
+ /* Sparse bindings that happen on a queue. */
+ VkSparseBufferMemoryBindInfo *buffer_binds;
+ uint32_t buffer_bind_count;
+ VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
+ uint32_t image_opaque_bind_count;
+
+ bool flush_caches;
+ VkShaderStageFlags wait_dst_stage_mask;
+ struct libresoc_semaphore_part **wait_semaphores;
+ uint32_t wait_semaphore_count;
+ struct libresoc_semaphore_part **signal_semaphores;
+ uint32_t signal_semaphore_count;
+ VkFence fence;
+
+ uint64_t *wait_values;
+ uint64_t *signal_values;
+
+ struct libresoc_semaphore_part *temporary_semaphore_parts;
+ uint32_t temporary_semaphore_part_count;
+
+ struct list_head queue_pending_list;
+ uint32_t submission_wait_count;
+ struct libresoc_timeline_waiter *wait_nodes;
+
+ struct list_head processing_list;
+};
+
+struct libresoc_queue_submission {
+ const VkCommandBuffer *cmd_buffers;
+ uint32_t cmd_buffer_count;
+
+ /* Sparse bindings that happen on a queue. */
+ const VkSparseBufferMemoryBindInfo *buffer_binds;
+ uint32_t buffer_bind_count;
+ const VkSparseImageOpaqueMemoryBindInfo *image_opaque_binds;
+ uint32_t image_opaque_bind_count;
+
+ bool flush_caches;
+ VkPipelineStageFlags wait_dst_stage_mask;
+ const VkSemaphore *wait_semaphores;
+ uint32_t wait_semaphore_count;
+ const VkSemaphore *signal_semaphores;
+ uint32_t signal_semaphore_count;
+ VkFence fence;
+
+ const uint64_t *wait_values;
+ uint32_t wait_value_count;
+ const uint64_t *signal_values;
+ uint32_t signal_value_count;
+};
+
+void
+libresoc_free_memory(struct libresoc_device *device,
+ const VkAllocationCallbacks* pAllocator,
+ struct libresoc_device_memory *mem)
+{
+ if (mem == NULL)
+ return;
+
+ vk_object_base_finish(&mem->base);
+ vk_free2(&device->vk.alloc, pAllocator, mem);
+}
+
+static VkResult libresoc_alloc_memory(struct libresoc_device *device,
+ const VkMemoryAllocateInfo* pAllocateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDeviceMemory* pMem)
+{
+ struct libresoc_device_memory *mem;
+ VkResult result;
+ uint32_t flags = 0;
+
+ assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
+
+ const VkImportMemoryFdInfoKHR *import_info =
+ vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
+ const VkMemoryDedicatedAllocateInfo *dedicate_info =
+ vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
+ const VkExportMemoryAllocateInfo *export_info =
+ vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
+ const VkImportMemoryHostPointerInfoEXT *host_ptr_info =
+ vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_HOST_POINTER_INFO_EXT);
+
+ const struct wsi_memory_allocate_info *wsi_info =
+ vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA);
+
+
+ mem = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*mem), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (mem == NULL)
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_object_base_init(&device->vk, &mem->base,
+ VK_OBJECT_TYPE_DEVICE_MEMORY);
+
+ if (dedicate_info) {
+ mem->image = libresoc_image_from_handle(dedicate_info->image);
+ //mem->buffer = libresoc_buffer_from_handle(dedicate_info->buffer);
+ } else {
+ mem->image = NULL;
+ //mem->buffer = NULL;
+ }
+
+ // float priority_float = 0.5;
+ // const struct VkMemoryPriorityAllocateInfoEXT *priority_ext =
+ // vk_find_struct_const(pAllocateInfo->pNext,
+ // MEMORY_PRIORITY_ALLOCATE_INFO_EXT);
+ // if (priority_ext)
+ // priority_float = priority_ext->priority;
+
+ // unsigned priority = MIN2(LIBRESOC_BO_PRIORITY_APPLICATION_MAX - 1,
+ // (int)(priority_float * LIBRESOC_BO_PRIORITY_APPLICATION_MAX));
+
+ mem->user_ptr = NULL;
+ //mem->bo = NULL;
+
+
+ if (import_info) {
+ assert(import_info->handleType ==
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
+ import_info->handleType ==
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
+ // mem->bo = device->ws->buffer_from_fd(device->ws, import_info->fd,
+ // priority, NULL);
+ // if (!mem->bo) {
+ // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ // goto fail;
+ // } else {
+ // close(import_info->fd);
+ // }
+
+ // if (mem->image && mem->image->plane_count == 1 &&
+ // !vk_format_is_depth_or_stencil(mem->image->vk_format)) {
+ // struct radeon_bo_metadata metadata;
+ // device->ws->buffer_get_metadata(mem->bo, &metadata);
+
+ // struct libresoc_image_create_info create_info = {
+ // .no_metadata_planes = true,
+ // .bo_metadata = &metadata
+ // };
+
+ // /* This gives a basic ability to import radeonsi images
+ // * that don't have DCC. This is not guaranteed by any
+ // * spec and can be removed after we support modifiers. */
+ // result = libresoc_image_create_layout(device, create_info, mem->image);
+ // if (result != VK_SUCCESS) {
+ // device->ws->buffer_destroy(mem->bo);
+ // goto fail;
+ // }
+ // }
+ } else if (host_ptr_info) {
+ // assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
+ // mem->bo = device->ws->buffer_from_ptr(device->ws, host_ptr_info->pHostPointer,
+ // pAllocateInfo->allocationSize,
+ // priority);
+ // if (!mem->bo) {
+ // result = VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ // goto fail;
+ // } else {
+ // mem->user_ptr = host_ptr_info->pHostPointer;
+ // }
+ } else {
+ uint64_t alloc_size = align_u64(pAllocateInfo->allocationSize, 4096);
+ uint32_t heap_index;
+
+ heap_index = device->physical_device->memory_properties.memoryTypes[pAllocateInfo->memoryTypeIndex].heapIndex;
+ // domain = device->physical_device->memory_domains[pAllocateInfo->memoryTypeIndex];
+ // flags |= device->physical_device->memory_flags[pAllocateInfo->memoryTypeIndex];
+
+ // if (!dedicate_info && !import_info && (!export_info || !export_info->handleTypes)) {
+ // flags |= RADEON_FLAG_NO_INTERPROCESS_SHARING;
+ // if (device->use_global_bo_list) {
+ // flags |= RADEON_FLAG_PREFER_LOCAL_BO;
+ // }
+ // }
+
+ if (device->overallocation_disallowed) {
+ uint64_t total_size =
+ device->physical_device->memory_properties.memoryHeaps[heap_index].size;
+
+ mtx_lock(&device->overallocation_mutex);
+ if (device->allocated_memory_size[heap_index] + alloc_size > total_size) {
+ mtx_unlock(&device->overallocation_mutex);
+ result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ goto fail;
+ }
+ device->allocated_memory_size[heap_index] += alloc_size;
+ mtx_unlock(&device->overallocation_mutex);
+ }
+
+ // mem->bo = device->ws->buffer_create(device->ws, alloc_size, device->physical_device->rad_info.max_alignment,
+ // domain, flags, priority);
+
+ // if (!mem->bo) {
+ // if (device->overallocation_disallowed) {
+ // mtx_lock(&device->overallocation_mutex);
+ // device->allocated_memory_size[heap_index] -= alloc_size;
+ // mtx_unlock(&device->overallocation_mutex);
+ // }
+ // result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
+ // goto fail;
+ // }
+
+ mem->heap_index = heap_index;
+ mem->alloc_size = alloc_size;
+ }
+
+ // if (!wsi_info) {
+ // result = libresoc_bo_list_add(device, mem->bo);
+ // if (result != VK_SUCCESS)
+ // goto fail;
+ // }
+
+ *pMem = libresoc_device_memory_to_handle(mem);
+
+ return VK_SUCCESS;
+
+fail:
+ libresoc_free_memory(device, pAllocator,mem);
+
+ return result;
+}
+
+VkResult libresoc_AllocateMemory(
+ VkDevice _device,
+ const VkMemoryAllocateInfo* pAllocateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkDeviceMemory* pMem)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ return libresoc_alloc_memory(device, pAllocateInfo, pAllocator, pMem);
+}
+
+void libresoc_FreeMemory(
+ VkDevice _device,
+ VkDeviceMemory _mem,
+ const VkAllocationCallbacks* pAllocator)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _mem);
+
+ libresoc_free_memory(device, pAllocator, mem);
+}
+static VkResult
+libresoc_create_pthread_cond(pthread_cond_t *cond)
+{
+ pthread_condattr_t condattr;
+ if (pthread_condattr_init(&condattr)) {
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
+ pthread_condattr_destroy(&condattr);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ if (pthread_cond_init(cond, &condattr)) {
+ pthread_condattr_destroy(&condattr);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+ pthread_condattr_destroy(&condattr);
+ return VK_SUCCESS;
+}
VkResult
libresoc_EnumerateInstanceExtensionProperties(const char *pLayerName,
return vk_outarray_status(&out);
}
+static void *
+default_alloc_func(void *pUserData, size_t size, size_t align,
+ VkSystemAllocationScope allocationScope)
+{
+ return malloc(size);
+}
+
+static void *
+default_realloc_func(void *pUserData, void *pOriginal, size_t size,
+ size_t align, VkSystemAllocationScope allocationScope)
+{
+ return realloc(pOriginal, size);
+}
+
+static void
+default_free_func(void *pUserData, void *pMemory)
+{
+ free(pMemory);
+}
+
+static const VkAllocationCallbacks default_alloc = {
+ .pUserData = NULL,
+ .pfnAllocation = default_alloc_func,
+ .pfnReallocation = default_realloc_func,
+ .pfnFree = default_free_func,
+};
+
+static const struct debug_control libresoc_debug_options[] = {
+ {"nofastclears", LIBRESOC_DEBUG_NO_FAST_CLEARS},
+ {"nodcc", LIBRESOC_DEBUG_NO_DCC},
+ {"shaders", LIBRESOC_DEBUG_DUMP_SHADERS},
+ {"nocache", LIBRESOC_DEBUG_NO_CACHE},
+ {"shaderstats", LIBRESOC_DEBUG_DUMP_SHADER_STATS},
+ {"nohiz", LIBRESOC_DEBUG_NO_HIZ},
+ {"nocompute", LIBRESOC_DEBUG_NO_COMPUTE_QUEUE},
+ {"allbos", LIBRESOC_DEBUG_ALL_BOS},
+ {"noibs", LIBRESOC_DEBUG_NO_IBS},
+ {"spirv", LIBRESOC_DEBUG_DUMP_SPIRV},
+ {"vmfaults", LIBRESOC_DEBUG_VM_FAULTS},
+ {"zerovram", LIBRESOC_DEBUG_ZERO_VRAM},
+ {"syncshaders", LIBRESOC_DEBUG_SYNC_SHADERS},
+ {"preoptir", LIBRESOC_DEBUG_PREOPTIR},
+ {"nodynamicbounds", LIBRESOC_DEBUG_NO_DYNAMIC_BOUNDS},
+ {"nooutoforder", LIBRESOC_DEBUG_NO_OUT_OF_ORDER},
+ {"info", LIBRESOC_DEBUG_INFO},
+ {"errors", LIBRESOC_DEBUG_ERRORS},
+ {"startup", LIBRESOC_DEBUG_STARTUP},
+ {"checkir", LIBRESOC_DEBUG_CHECKIR},
+ {"nothreadllvm", LIBRESOC_DEBUG_NOTHREADLLVM},
+ {"nobinning", LIBRESOC_DEBUG_NOBINNING},
+ {"nongg", LIBRESOC_DEBUG_NO_NGG},
+ {"allentrypoints", LIBRESOC_DEBUG_ALL_ENTRYPOINTS},
+ {"metashaders", LIBRESOC_DEBUG_DUMP_META_SHADERS},
+ {"nomemorycache", LIBRESOC_DEBUG_NO_MEMORY_CACHE},
+ {"llvm", LIBRESOC_DEBUG_LLVM},
+ {"forcecompress", LIBRESOC_DEBUG_FORCE_COMPRESS},
+ {NULL, 0}
+};
+
+const char *
+libresoc_get_debug_option_name(int id)
+{
+ assert(id < ARRAY_SIZE(libresoc_debug_options) - 1);
+ return libresoc_debug_options[id].string;
+}
+
+static const char libresoc_dri_options_xml[] =
+DRI_CONF_BEGIN
+ DRI_CONF_SECTION_PERFORMANCE
+ DRI_CONF_ADAPTIVE_SYNC("true")
+ DRI_CONF_VK_X11_OVERRIDE_MIN_IMAGE_COUNT(0)
+ DRI_CONF_VK_X11_STRICT_IMAGE_COUNT("false")
+ DRI_CONF_VK_X11_ENSURE_MIN_IMAGE_COUNT("false")
+ DRI_CONF_SECTION_END
+
+ DRI_CONF_SECTION_DEBUG
+ DRI_CONF_VK_WSI_FORCE_BGRA8_UNORM_FIRST("false")
+ DRI_CONF_SECTION_END
+DRI_CONF_END;
+
+static void libresoc_init_dri_options(struct libresoc_instance *instance)
+{
+ driParseOptionInfo(&instance->available_dri_options, libresoc_dri_options_xml);
+ driParseConfigFiles(&instance->dri_options,
+ &instance->available_dri_options,
+ 0, "libresoc", NULL,
+ instance->app_info.app_name,
+ instance->app_info.app_version,
+ instance->engineName,
+ instance->engineVersion);
+}
+
VkResult
libresoc_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
if (getenv("LIBRESOC_TRACE")) {
fprintf(stderr, "CreateInstance called. \n");
}
- /* FIXME: stub */
- return VK_SUCCESS;
+ struct libresoc_instance *instance;
+
+ instance = vk_zalloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (!instance)
+ return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_object_base_init(NULL, &instance->base, VK_OBJECT_TYPE_INSTANCE);
+
+ if (pAllocator)
+ instance->alloc = *pAllocator;
+ else
+ instance->alloc = default_alloc;
+ if (pCreateInfo->pApplicationInfo) {
+ const VkApplicationInfo *app = pCreateInfo->pApplicationInfo;
+
+ instance->engineName =
+ vk_strdup(&instance->alloc, app->pEngineName,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ instance->engineVersion = app->engineVersion;
+ instance->apiVersion = app->apiVersion;
+ }
+ instance->debug_flags = parse_debug_string(getenv("LIBRESOC_DEBUG"),
+ libresoc_debug_options);
+ /*TODO : enable extensions*/
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ int idx;
+ for (idx = 0; idx < LIBRESOC_INSTANCE_EXTENSION_COUNT; idx++) {
+ if (!strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+ libresoc_instance_extensions[idx].extensionName))
+ break;
+ }
+
+ if (idx >= LIBRESOC_INSTANCE_EXTENSION_COUNT ||
+ !libresoc_instance_extensions_supported.extensions[idx]) {
+ vk_object_base_finish(&instance->base);
+ vk_free2(&default_alloc, pAllocator, instance);
+ return vk_error(instance, VK_ERROR_EXTENSION_NOT_PRESENT);
+ }
+
+ instance->enabled_extensions.extensions[idx] = true;
+ }
+ for (unsigned i = 0; i < ARRAY_SIZE(instance->dispatch.entrypoints); i++) {
+ /* Vulkan requires that entrypoints for extensions which have
+ * not been enabled must not be advertised.
+ */
+ if (!libresoc_instance_entrypoint_is_enabled(i, instance->apiVersion,
+ &instance->enabled_extensions)) {
+ instance->dispatch.entrypoints[i] = NULL;
+ } else {
+ instance->dispatch.entrypoints[i] =
+ libresoc_instance_dispatch_table.entrypoints[i];
+ }
+ }
+ for (unsigned i = 0; i < ARRAY_SIZE(instance->physical_device_dispatch.entrypoints); i++) {
+ /* Vulkan requires that entrypoints for extensions which have
+ * not been enabled must not be advertised.
+ */
+ if (!libresoc_physical_device_entrypoint_is_enabled(i, instance->apiVersion,
+ &instance->enabled_extensions)) {
+ instance->physical_device_dispatch.entrypoints[i] = NULL;
+ } else {
+ instance->physical_device_dispatch.entrypoints[i] =
+ libresoc_physical_device_dispatch_table.entrypoints[i];
+ }
+ }
+
+ for (unsigned i = 0; i < ARRAY_SIZE(instance->device_dispatch.entrypoints); i++) {
+ /* Vulkan requires that entrypoints for extensions which have
+ * not been enabled must not be advertised.
+ */
+ if (!libresoc_device_entrypoint_is_enabled(i, instance->apiVersion,
+ &instance->enabled_extensions, NULL)) {
+ instance->device_dispatch.entrypoints[i] = NULL;
+ } else {
+ instance->device_dispatch.entrypoints[i] =
+ libresoc_device_dispatch_table.entrypoints[i];
+ }
+ }
+ instance->physical_devices_enumerated = false;
+ list_inithead(&instance->physical_devices);
+ libresoc_init_dri_options(instance);
+ *pInstance = libresoc_instance_to_handle(instance);
+
+ return VK_SUCCESS;
}
void
/* FIXME: stub */
}
+static void
+libresoc_physical_device_init_mem_types(struct libresoc_physical_device *device)
+{
+ uint64_t visible_vram_size = 65536; //TODO: some dummy value
+ uint64_t vram_size = 65536; //TODO: some dummy value
+ int vram_index = -1, visible_vram_index = -1;
+ device->memory_properties.memoryHeapCount = 0;
+ if (vram_size > 0) {
+ vram_index = device->memory_properties.memoryHeapCount++;
+ device->memory_properties.memoryHeaps[vram_index] = (VkMemoryHeap) {
+ .size = vram_size,
+ .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
+ };
+ }
+
+ if (visible_vram_size) {
+ visible_vram_index = device->memory_properties.memoryHeapCount++;
+ device->memory_properties.memoryHeaps[visible_vram_index] = (VkMemoryHeap) {
+ .size = visible_vram_size,
+ .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
+ };
+ }
+ unsigned type_count = 0;
+
+ if (vram_index >= 0 || visible_vram_index >= 0) {
+ device->memory_properties.memoryTypes[type_count++] = (VkMemoryType) {
+ .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
+ .heapIndex = vram_index >= 0 ? vram_index : visible_vram_index,
+ };
+ }
+
+ if (visible_vram_index >= 0) {
+ device->memory_properties.memoryTypes[type_count++] = (VkMemoryType) {
+ .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
+ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
+ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
+ .heapIndex = visible_vram_index,
+ };
+ }
+
+ device->memory_properties.memoryTypeCount = type_count;
+
+
+}
+static VkResult
+libresoc_physical_device_try_create(struct libresoc_instance *instance,
+ struct libresoc_physical_device **device_out)
+{
+ VkResult result;
+ int fd = -1;
+ int master_fd = -1;
+
+ struct libresoc_physical_device *device =
+ vk_zalloc2(&instance->alloc, NULL, sizeof(*device), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ if (!device) {
+ result = vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+ return result;
+ }
+
+ device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
+ device->instance = instance;
+
+ device->master_fd = master_fd;
+ device->local_fd = fd;
+ libresoc_physical_device_init_mem_types(device);
+
+ libresoc_physical_device_get_supported_extensions(device,
+ &device->supported_extensions);
+ result = libresoc_init_wsi(device);
+ if (result != VK_SUCCESS) {
+ return result;
+ }
+ snprintf(device->name, sizeof(device->name),
+ "LIBRE-SOC DEVICE");
+ *device_out = device;
+//TODO: incase of failures need to deallocate and cleanup various allocation properly.
+ return VK_SUCCESS;
+
+}
+static VkResult
+libresoc_enumerate_physical_devices(struct libresoc_instance *instance)
+{
+
+ if (instance->physical_devices_enumerated)
+ return VK_SUCCESS;
+
+ instance->physical_devices_enumerated = true;
+ VkResult result = VK_SUCCESS;
+ /* the driver creates a null
+ * device that allows to test the compiler without having a physical device
+ */
+ struct libresoc_physical_device *pdevice;
+
+ result = libresoc_physical_device_try_create(instance, &pdevice);
+ if (result != VK_SUCCESS)
+ return result;
+
+ list_addtail(&pdevice->link, &instance->physical_devices);
+ return VK_SUCCESS;
+
+}
+
VkResult
libresoc_EnumeratePhysicalDevices(VkInstance _instance,
uint32_t *pPhysicalDeviceCount,
if (getenv("LIBRESOC_TRACE")) {
fprintf(stderr, "EnumeratePhysicalDevices called\n");
}
- /* FIXME: stub */
- return VK_SUCCESS;
+ LIBRESOC_FROM_HANDLE(libresoc_instance, instance, _instance);
+ VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
+
+ VkResult result = libresoc_enumerate_physical_devices(instance);
+ if (result != VK_SUCCESS)
+ return result;
+
+ list_for_each_entry(struct libresoc_physical_device, pdevice,
+ &instance->physical_devices, link) {
+ vk_outarray_append(&out, i) {
+ *i = libresoc_physical_device_to_handle(pdevice);
+ }
+ }
+
+ return vk_outarray_status(&out);
}
void
if (getenv("LIBRESOC_TRACE")) {
fprintf(stderr, "GetPhysicalDeviceFeatures called. \n");
}
- /* FIXME: stub */
+ //LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
+ memset(pFeatures, 0, sizeof(*pFeatures));
+
+ *pFeatures = (VkPhysicalDeviceFeatures) {
+ .robustBufferAccess = true,
+ .fullDrawIndexUint32 = true,
+ .imageCubeArray = true,
+ .independentBlend = true,
+ .geometryShader = true,
+ .tessellationShader = true,
+ .sampleRateShading = true,
+ .dualSrcBlend = true,
+ .logicOp = true,
+ .multiDrawIndirect = true,
+ .drawIndirectFirstInstance = true,
+ .depthClamp = true,
+ .depthBiasClamp = true,
+ .fillModeNonSolid = true,
+ .depthBounds = true,
+ .wideLines = true,
+ .largePoints = true,
+ .alphaToOne = true,
+ .multiViewport = true,
+ .samplerAnisotropy = true,
+ .textureCompressionETC2 = false,
+ .textureCompressionASTC_LDR = false,
+ .textureCompressionBC = true,
+ .occlusionQueryPrecise = true,
+ .pipelineStatisticsQuery = true,
+ .vertexPipelineStoresAndAtomics = true,
+ .fragmentStoresAndAtomics = true,
+ .shaderTessellationAndGeometryPointSize = true,
+ .shaderImageGatherExtended = true,
+ .shaderStorageImageExtendedFormats = true,
+ .shaderStorageImageMultisample = true,
+ .shaderUniformBufferArrayDynamicIndexing = true,
+ .shaderSampledImageArrayDynamicIndexing = true,
+ .shaderStorageBufferArrayDynamicIndexing = true,
+ .shaderStorageImageArrayDynamicIndexing = true,
+ .shaderStorageImageReadWithoutFormat = true,
+ .shaderStorageImageWriteWithoutFormat = true,
+ .shaderClipDistance = true,
+ .shaderCullDistance = true,
+ .shaderFloat64 = true,
+ .shaderInt64 = true,
+ .shaderInt16 = true,
+ .sparseBinding = true,
+ .variableMultisampleRate = true,
+ .shaderResourceMinLod = true,
+ .inheritedQueries = true,
+ };
+}
+
+static size_t
+libresoc_max_descriptor_set_size()
+{
+ /* make sure that the entire descriptor set is addressable with a signed
+ * 32-bit int. So the sum of all limits scaled by descriptor size has to
+ * be at most 2 GiB. the combined image & samples object count as one of
+ * both. This limit is for the pipeline layout, not for the set layout, but
+ * there is no set limit, so we just set a pipeline limit. I don't think
+ * any app is going to hit this soon. */
+ return ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS
+ - MAX_INLINE_UNIFORM_BLOCK_SIZE * MAX_INLINE_UNIFORM_BLOCK_COUNT) /
+ (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
+ 32 /* storage buffer, 32 due to potential space wasted on alignment */ +
+ 32 /* sampler, largest when combined with image */ +
+ 64 /* sampled image */ +
+ 64 /* storage image */);
}
void
if (getenv("LIBRESOC_TRACE")) {
fprintf(stderr, "GetPhysicalDeviceProperties called. \n");
}
- /* FIXME: stub */
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
+ VkSampleCountFlags sample_counts = 0xf;
+
+ size_t max_descriptor_set_size = libresoc_max_descriptor_set_size();
+
+ VkPhysicalDeviceLimits limits = {
+ .maxImageDimension1D = (1 << 14),
+ .maxImageDimension2D = (1 << 14),
+ .maxImageDimension3D = (1 << 11),
+ .maxImageDimensionCube = (1 << 14),
+ .maxImageArrayLayers = (1 << 11),
+ .maxTexelBufferElements = UINT32_MAX,
+ .maxUniformBufferRange = UINT32_MAX,
+ .maxStorageBufferRange = UINT32_MAX,
+ .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
+ .maxMemoryAllocationCount = UINT32_MAX,
+ .maxSamplerAllocationCount = 64 * 1024,
+ .bufferImageGranularity = 64, /* A cache line */
+ .sparseAddressSpaceSize = LIBRESOC_MAX_MEMORY_ALLOCATION_SIZE, /* buffer max size */
+ .maxBoundDescriptorSets = MAX_SETS,
+ .maxPerStageDescriptorSamplers = max_descriptor_set_size,
+ .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
+ .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
+ .maxPerStageDescriptorSampledImages = max_descriptor_set_size,
+ .maxPerStageDescriptorStorageImages = max_descriptor_set_size,
+ .maxPerStageDescriptorInputAttachments = max_descriptor_set_size,
+ .maxPerStageResources = max_descriptor_set_size,
+ .maxDescriptorSetSamplers = max_descriptor_set_size,
+ .maxDescriptorSetUniformBuffers = max_descriptor_set_size,
+ .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
+ .maxDescriptorSetStorageBuffers = max_descriptor_set_size,
+ .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
+ .maxDescriptorSetSampledImages = max_descriptor_set_size,
+ .maxDescriptorSetStorageImages = max_descriptor_set_size,
+ .maxDescriptorSetInputAttachments = max_descriptor_set_size,
+ .maxVertexInputAttributes = MAX_VERTEX_ATTRIBS,
+ .maxVertexInputBindings = MAX_VBS,
+ .maxVertexInputAttributeOffset = 2047,
+ .maxVertexInputBindingStride = 2048,
+ .maxVertexOutputComponents = 128,
+ .maxTessellationGenerationLevel = 64,
+ .maxTessellationPatchSize = 32,
+ .maxTessellationControlPerVertexInputComponents = 128,
+ .maxTessellationControlPerVertexOutputComponents = 128,
+ .maxTessellationControlPerPatchOutputComponents = 120,
+ .maxTessellationControlTotalOutputComponents = 4096,
+ .maxTessellationEvaluationInputComponents = 128,
+ .maxTessellationEvaluationOutputComponents = 128,
+ .maxGeometryShaderInvocations = 127,
+ .maxGeometryInputComponents = 64,
+ .maxGeometryOutputComponents = 128,
+ .maxGeometryOutputVertices = 256,
+ .maxGeometryTotalOutputComponents = 1024,
+ .maxFragmentInputComponents = 128,
+ .maxFragmentOutputAttachments = 8,
+ .maxFragmentDualSrcAttachments = 1,
+ .maxFragmentCombinedOutputResources = 8,
+ .maxComputeSharedMemorySize = 32768,
+ .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
+ .maxComputeWorkGroupInvocations = 1024,
+ .maxComputeWorkGroupSize = {
+ 1024,
+ 1024,
+ 1024
+ },
+ .subPixelPrecisionBits = 8,
+ .subTexelPrecisionBits = 8,
+ .mipmapPrecisionBits = 8,
+ .maxDrawIndexedIndexValue = UINT32_MAX,
+ .maxDrawIndirectCount = UINT32_MAX,
+ .maxSamplerLodBias = 16,
+ .maxSamplerAnisotropy = 16,
+ .maxViewports = MAX_VIEWPORTS,
+ .maxViewportDimensions = { (1 << 14), (1 << 14) },
+ .viewportBoundsRange = { INT16_MIN, INT16_MAX },
+ .viewportSubPixelBits = 8,
+ .minMemoryMapAlignment = 4096, /* A page */
+ .minTexelBufferOffsetAlignment = 4,
+ .minUniformBufferOffsetAlignment = 4,
+ .minStorageBufferOffsetAlignment = 4,
+ .minTexelOffset = -32,
+ .maxTexelOffset = 31,
+ .minTexelGatherOffset = -32,
+ .maxTexelGatherOffset = 31,
+ .minInterpolationOffset = -2,
+ .maxInterpolationOffset = 2,
+ .subPixelInterpolationOffsetBits = 8,
+ .maxFramebufferWidth = (1 << 14),
+ .maxFramebufferHeight = (1 << 14),
+ .maxFramebufferLayers = (1 << 10),
+ .framebufferColorSampleCounts = sample_counts,
+ .framebufferDepthSampleCounts = sample_counts,
+ .framebufferStencilSampleCounts = sample_counts,
+ .framebufferNoAttachmentsSampleCounts = sample_counts,
+ .maxColorAttachments = MAX_RTS,
+ .sampledImageColorSampleCounts = sample_counts,
+ .sampledImageIntegerSampleCounts = sample_counts,
+ .sampledImageDepthSampleCounts = sample_counts,
+ .sampledImageStencilSampleCounts = sample_counts,
+ .storageImageSampleCounts = sample_counts,
+ .maxSampleMaskWords = 1,
+ .timestampComputeAndGraphics = true,
+ .timestampPeriod = 1000000.0 /* FIXME /pdevice->rad_info.clock_crystal_freq*/,
+ .maxClipDistances = 8,
+ .maxCullDistances = 8,
+ .maxCombinedClipAndCullDistances = 8,
+ .discreteQueuePriorities = 2,
+ .pointSizeRange = { 0.0, 8191.875 },
+ .lineWidthRange = { 0.0, 8191.875 },
+ .pointSizeGranularity = (1.0 / 8.0),
+ .lineWidthGranularity = (1.0 / 8.0),
+ .strictLines = false, /* FINISHME */
+ .standardSampleLocations = true,
+ .optimalBufferCopyOffsetAlignment = 128,
+ .optimalBufferCopyRowPitchAlignment = 128,
+ .nonCoherentAtomSize = 64,
+ };
+
+ *pProperties = (VkPhysicalDeviceProperties) {
+ .apiVersion = libresoc_physical_device_api_version(pdevice),
+ .driverVersion = vk_get_driver_version(),
+ .vendorID = 1, //TODO: some dummy value
+ .deviceID = 1, //TODO: dome dummy value
+ .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
+ .limits = limits,
+ .sparseProperties = {0},
+ };
+
+ strcpy(pProperties->deviceName, pdevice->name);
+ memcpy(pProperties->pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
+}
+
+static void libresoc_get_physical_device_queue_family_properties(
+ struct libresoc_physical_device* pdevice,
+ uint32_t* pCount,
+ VkQueueFamilyProperties** pQueueFamilyProperties)
+{
+ int num_queue_families = 1;
+ int idx;
+
+ if (pQueueFamilyProperties == NULL) {
+ *pCount = num_queue_families;
+ return;
+ }
+
+ if (!*pCount)
+ return;
+
+ idx = 0;
+ if (*pCount >= 1) {
+ *pQueueFamilyProperties[idx] = (VkQueueFamilyProperties) {
+ .queueFlags = VK_QUEUE_GRAPHICS_BIT |
+ VK_QUEUE_COMPUTE_BIT |
+ VK_QUEUE_TRANSFER_BIT |
+ VK_QUEUE_SPARSE_BINDING_BIT,
+ .queueCount = 1,
+ .timestampValidBits = 64,
+ .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 },
+ };
+ idx++;
+ }
+
+ *pCount = idx;
}
void
if (getenv("LIBRESOC_TRACE")) {
fprintf(stderr, "GetPhysicalDeviceQueueFamilyProperites called. \n");
}
- /* FIXME: stub */
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
+ if (!pQueueFamilyProperties) {
+ libresoc_get_physical_device_queue_family_properties(pdevice, pCount, NULL);
+ return;
+ }
+ VkQueueFamilyProperties *properties[] = {
+ pQueueFamilyProperties + 0,
+ pQueueFamilyProperties + 1,
+ pQueueFamilyProperties + 2,
+ };
+ libresoc_get_physical_device_queue_family_properties(pdevice, pCount, properties);
+ assert(*pCount <= 3);
}
void
if (getenv("LIBRESOC_TRACE")) {
fprintf(stderr, "GetPhysicalDEviceMemoryProperties called. \n");
}
- /* FIXME: stub */
-}
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
-void
-libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
-
- if (getenv("LIBRESOC_TRACE")) {
- fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
- }
+ *pMemoryProperties = physical_device->memory_properties;
/* FIXME: stub */
}
-VkResult
- libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
-{
- if (getenv("LIBRESOC_TRACE")) {
- fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
- }
-
- /* FIXME: stub */
- return VK_SUCCESS;
-}
- void
- libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
- {
- if (getenv("LIBRESOC_TRACE")) {
- fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
- }
- /* FIXME: stub */
- }
+//void
+//libresoc_GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
+//
+// if (getenv("LIBRESOC_TRACE")) {
+// fprintf(stderr, "GetPhysicalDeviceFormatProperties called. \n");
+// }
+// /* FIXME: stub */
+//}
+
+//VkResult
+// libresoc_GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* pImageFormatProperties)
+//{
+// if (getenv("LIBRESOC_TRACE")) {
+// fprintf(stderr, "GetPhysicalDEviceImageFormatProperties called. \n");
+// }
+//
+// /* FIXME: stub */
+// return VK_SUCCESS;
+//}
+// void
+// libresoc_GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling, uint32_t* pPropertyCount, VkSparseImageFormatProperties* pProperties)
+// {
+// if (getenv("LIBRESOC_TRACE")) {
+// fprintf(stderr, "GetPhysicalDeviceSparseImageFormatProperties called. \n");
+// }
+// /* FIXME: stub */
+// }
PFN_vkVoidFunction
libresoc_GetInstanceProcAddr(VkInstance _instance,
const char *pName)
idx = libresoc_get_physical_device_entrypoint_index(pName);
if (idx >= 0)
- return instance->physicalDevice.dispatch.entrypoints[idx];
+ return instance->physical_device_dispatch.entrypoints[idx];
idx = libresoc_get_device_entrypoint_index(pName);
if (idx >= 0)
if (idx < 0)
return NULL;
- return instance->physicalDevice.dispatch.entrypoints[idx];
+ return instance->physical_device_dispatch.entrypoints[idx];
}
VkResult
if (getenv("LIBRESOC_TRACE")) {
fprintf(stderr, "EnumerateDeviceExtensionProperties called for layer: %s \n", pLayerName);
}
- /* FIXME: stub */
- return VK_SUCCESS;
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, device, physicalDevice);
+ VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
+
+ for (int i = 0; i < LIBRESOC_DEVICE_EXTENSION_COUNT; i++) {
+ if (device->supported_extensions.extensions[i]) {
+ vk_outarray_append(&out, prop) {
+ *prop = libresoc_device_extensions[i];
+ }
+ }
+ }
+
+ return vk_outarray_status(&out);
}
+static void
+libresoc_device_init_dispatch(struct libresoc_device *device)
+{
+ const struct libresoc_instance *instance = device->physical_device->instance;
+ const struct libresoc_device_dispatch_table *dispatch_table_layer = NULL;
+
+ for (unsigned i = 0; i < ARRAY_SIZE(device->dispatch.entrypoints); i++) {
+ /* Vulkan requires that entrypoints for extensions which have not been
+ * enabled must not be advertised.
+ */
+ if (!libresoc_device_entrypoint_is_enabled(i, instance->apiVersion,
+ &instance->enabled_extensions,
+ &device->enabled_extensions)) {
+ device->dispatch.entrypoints[i] = NULL;
+ } else if (dispatch_table_layer &&
+ dispatch_table_layer->entrypoints[i]) {
+ device->dispatch.entrypoints[i] =
+ dispatch_table_layer->entrypoints[i];
+ } else {
+ device->dispatch.entrypoints[i] =
+ libresoc_device_dispatch_table.entrypoints[i];
+ }
+ }
+}
+
+static VkResult
+check_physical_device_features(VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceFeatures *features)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
+ VkPhysicalDeviceFeatures supported_features;
+ libresoc_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
+ VkBool32 *supported_feature = (VkBool32 *)&supported_features;
+ VkBool32 *enabled_feature = (VkBool32 *)features;
+ unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
+ for (uint32_t i = 0; i < num_features; i++) {
+ if (enabled_feature[i] && !supported_feature[i])
+ return vk_error(physical_device->instance, VK_ERROR_FEATURE_NOT_PRESENT);
+ }
+
+ return VK_SUCCESS;
+}
+static int libresoc_get_device_extension_index(const char *name)
+{
+ for (unsigned i = 0; i < LIBRESOC_DEVICE_EXTENSION_COUNT; ++i) {
+ if (strcmp(name, libresoc_device_extensions[i].extensionName) == 0)
+ return i;
+ }
+ return -1;
+}
+
+static int
+libresoc_queue_init(struct libresoc_device *device, struct libresoc_queue *queue,
+ uint32_t queue_family_index, int idx,
+ VkDeviceQueueCreateFlags flags,
+ const VkDeviceQueueGlobalPriorityCreateInfoEXT *global_priority)
+{
+ queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
+ queue->device = device;
+ queue->queue_family_index = queue_family_index;
+ queue->queue_idx = idx;
+ queue->flags = flags;
+ list_inithead(&queue->pending_submissions);
+ pthread_mutex_init(&queue->pending_mutex, NULL);
+
+ pthread_mutex_init(&queue->thread_mutex, NULL);
+ //queue->thread_submission = NULL;
+ queue->thread_running = queue->thread_exit = false;
+ VkResult result = libresoc_create_pthread_cond(&queue->thread_cond);
+ if (result != VK_SUCCESS)
+ return vk_error(device->instance, result);
+
+ return VK_SUCCESS;
+}
+
+static void
+libresoc_queue_finish(struct libresoc_queue *queue)
+{
+//TODO: understand and enable following code
+// if (queue->thread_running) {
+// p_atomic_set(&queue->thread_exit, true);
+// pthread_cond_broadcast(&queue->thread_cond);
+// pthread_join(queue->submission_thread, NULL);
+// }
+// pthread_cond_destroy(&queue->thread_cond);
+// pthread_mutex_destroy(&queue->pending_mutex);
+// pthread_mutex_destroy(&queue->thread_mutex);
+//
+// if (queue->hw_ctx)
+// queue->device->ws->ctx_destroy(queue->hw_ctx);
+//
+// if (queue->initial_full_flush_preamble_cs)
+// queue->device->ws->cs_destroy(queue->initial_full_flush_preamble_cs);
+// if (queue->initial_preamble_cs)
+// queue->device->ws->cs_destroy(queue->initial_preamble_cs);
+// if (queue->continue_preamble_cs)
+// queue->device->ws->cs_destroy(queue->continue_preamble_cs);
+// if (queue->descriptor_bo)
+// queue->device->ws->buffer_destroy(queue->descriptor_bo);
+// if (queue->scratch_bo)
+// queue->device->ws->buffer_destroy(queue->scratch_bo);
+// if (queue->esgs_ring_bo)
+// queue->device->ws->buffer_destroy(queue->esgs_ring_bo);
+// if (queue->gsvs_ring_bo)
+// queue->device->ws->buffer_destroy(queue->gsvs_ring_bo);
+// if (queue->tess_rings_bo)
+// queue->device->ws->buffer_destroy(queue->tess_rings_bo);
+// if (queue->gds_bo)
+// queue->device->ws->buffer_destroy(queue->gds_bo);
+// if (queue->gds_oa_bo)
+// queue->device->ws->buffer_destroy(queue->gds_oa_bo);
+// if (queue->compute_scratch_bo)
+// queue->device->ws->buffer_destroy(queue->compute_scratch_bo);
+}
VkResult
libresoc_CreateDevice(VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo *pCreateInfo,
if (getenv("LIBRESOC_TRACE")) {
fprintf(stderr, "CreateDevice called \n");
}
- /* FIXME: stub */
- return VK_SUCCESS;
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, physical_device, physicalDevice);
+ VkResult result;
+ struct libresoc_device *device;
+
+ /* Check enabled features */
+ if (pCreateInfo->pEnabledFeatures) {
+ result = check_physical_device_features(physicalDevice,
+ pCreateInfo->pEnabledFeatures);
+ if (result != VK_SUCCESS)
+ return result;
+ }
+
+ device = vk_zalloc2(&physical_device->instance->alloc, pAllocator,
+ sizeof(*device), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+ if (!device)
+ return vk_error(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_device_init(&device->vk, pCreateInfo,
+ &physical_device->instance->alloc, pAllocator);
+
+ device->instance = physical_device->instance;
+ device->physical_device = physical_device;
+
+ for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+ const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
+ int index = libresoc_get_device_extension_index(ext_name);
+ if (index < 0 || !physical_device->supported_extensions.extensions[index]) {
+ vk_free(&device->vk.alloc, device);
+ return vk_error(physical_device->instance, VK_ERROR_EXTENSION_NOT_PRESENT);
+ }
+
+ device->enabled_extensions.extensions[index] = true;
+ }
+
+ libresoc_device_init_dispatch(device);
+
+ for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
+ const VkDeviceQueueCreateInfo *queue_create = &pCreateInfo->pQueueCreateInfos[i];
+ uint32_t qfi = queue_create->queueFamilyIndex;
+ const VkDeviceQueueGlobalPriorityCreateInfoEXT *global_priority =
+ vk_find_struct_const(queue_create->pNext, DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT);
+
+
+ device->queues[qfi] = vk_alloc(&device->vk.alloc,
+ queue_create->queueCount * sizeof(struct libresoc_queue), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
+ if (!device->queues[qfi]) {
+ result = VK_ERROR_OUT_OF_HOST_MEMORY;
+ goto fail;
+ }
+
+ memset(device->queues[qfi], 0, queue_create->queueCount * sizeof(struct libresoc_queue));
+
+ device->queue_count[qfi] = queue_create->queueCount;
+
+ for (unsigned q = 0; q < queue_create->queueCount; q++) {
+ result = libresoc_queue_init(device, &device->queues[qfi][q],
+ qfi, q, queue_create->flags,
+ global_priority);
+ if (result != VK_SUCCESS)
+ goto fail;
+ }
+ }
+
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ VkPipelineCacheCreateInfo ci;
+ ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ ci.pNext = NULL;
+ ci.flags = 0;
+ ci.pInitialData = NULL;
+ ci.initialDataSize = 0;
+ VkPipelineCache pc;
+ result = libresoc_CreatePipelineCache(libresoc_device_to_handle(device),
+ &ci, NULL, &pc);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ *pDevice = libresoc_device_to_handle(device);
+ return VK_SUCCESS;
+
+fail:
+ libresoc_DestroyPipelineCache(libresoc_device_to_handle(device), pc, NULL);
+ for (unsigned i = 0; i < LIBRESOC_MAX_QUEUE_FAMILIES; i++) {
+ for (unsigned q = 0; q < device->queue_count[i]; q++)
+ libresoc_queue_finish(&device->queues[i][q]);
+ if (device->queue_count[i])
+ vk_free(&device->vk.alloc, device->queues[i]);
+ }
+
+ vk_free(&device->vk.alloc, device);
+ return result;
}
void
/* FIXME: stub */
}
-void
-libresoc_GetDeviceQueue(VkDevice _device,
- uint32_t queueNodeIndex,
- uint32_t queueIndex,
- VkQueue *pQueue)
+void libresoc_GetDeviceQueue(
+ VkDevice _device,
+ uint32_t queueFamilyIndex,
+ uint32_t queueIndex,
+ VkQueue* pQueue)
{
if (getenv("LIBRESOC_TRACE")) {
fprintf(stderr, "GetDeviceQueue called. \n");
}
- /* FIXME: stub */
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ struct libresoc_queue *queue;
+
+ queue = &device->queues[queueFamilyIndex][queueIndex];
+ *pQueue = libresoc_queue_to_handle(queue);
+}
+
+VkResult libresoc_QueueWaitIdle(
+ VkQueue _queue)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
+
+ pthread_mutex_lock(&queue->pending_mutex);
+ while (!list_is_empty(&queue->pending_submissions)) {
+ pthread_cond_wait(&queue->device->timeline_cond, &queue->pending_mutex);
+ }
+ pthread_mutex_unlock(&queue->pending_mutex);
+
+ return VK_SUCCESS;
+}
+
+VkResult libresoc_DeviceWaitIdle(
+ VkDevice _device)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+
+ for (unsigned i = 0; i < LIBRESOC_MAX_QUEUE_FAMILIES; i++) {
+ for (unsigned q = 0; q < device->queue_count[i]; q++) {
+ VkResult result =
+ libresoc_QueueWaitIdle(libresoc_queue_to_handle(&device->queues[i][q]));
+
+ if (result != VK_SUCCESS)
+ return result;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+void libresoc_GetPhysicalDeviceProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceProperties2 *pProperties)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
+ libresoc_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
+ //TODO: add more stuffs when required
+}
+
+void libresoc_GetPhysicalDeviceFeatures2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceFeatures2 *pFeatures)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
+ libresoc_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
+}
+
+void libresoc_GetPhysicalDeviceQueueFamilyProperties2(
+ VkPhysicalDevice physicalDevice,
+ uint32_t* pCount,
+ VkQueueFamilyProperties2 *pQueueFamilyProperties)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_physical_device, pdevice, physicalDevice);
+ if (!pQueueFamilyProperties) {
+ libresoc_get_physical_device_queue_family_properties(pdevice, pCount, NULL);
+ return;
+ }
+ VkQueueFamilyProperties *properties[] = {
+ &pQueueFamilyProperties[0].queueFamilyProperties,
+ &pQueueFamilyProperties[1].queueFamilyProperties,
+ &pQueueFamilyProperties[2].queueFamilyProperties,
+ };
+ libresoc_get_physical_device_queue_family_properties(pdevice, pCount, properties);
+ assert(*pCount <= 3);
+}
+
+static void
+libresoc_get_memory_budget_properties(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryBudgetPropertiesEXT *memoryBudget)
+{
+//TODO: stub
+}
+
+void libresoc_GetPhysicalDeviceMemoryProperties2(
+ VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
+{
+ libresoc_GetPhysicalDeviceMemoryProperties(physicalDevice,
+ &pMemoryProperties->memoryProperties);
+
+ VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget =
+ vk_find_struct(pMemoryProperties->pNext,
+ PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT);
+ if (memory_budget)
+ libresoc_get_memory_budget_properties(physicalDevice, memory_budget);
+}
+
+VkResult libresoc_CreateSemaphore(
+ VkDevice _device,
+ const VkSemaphoreCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSemaphore* pSemaphore)
+{
+ //TODO: minimal things as of now, add more complex code as required
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ struct libresoc_semaphore *sem = vk_alloc2(&device->vk.alloc, pAllocator,
+ sizeof(*sem), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!sem)
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_object_base_init(&device->vk, &sem->base,
+ VK_OBJECT_TYPE_SEMAPHORE);
+
+ *pSemaphore = libresoc_semaphore_to_handle(sem);
+ return VK_SUCCESS;
+}
+
+void libresoc_GetImageMemoryRequirements(
+ VkDevice _device,
+ VkImage _image,
+ VkMemoryRequirements* pMemoryRequirements)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ LIBRESOC_FROM_HANDLE(libresoc_image, image, _image);
+
+ pMemoryRequirements->memoryTypeBits = (1u << device->physical_device->memory_properties.memoryTypeCount) - 1;
+
+ pMemoryRequirements->size = image->size;
+ pMemoryRequirements->alignment = image->alignment;
+}
+
+void libresoc_GetImageMemoryRequirements2(
+ VkDevice device,
+ const VkImageMemoryRequirementsInfo2 *pInfo,
+ VkMemoryRequirements2 *pMemoryRequirements)
+{
+ libresoc_GetImageMemoryRequirements(device, pInfo->image,
+ &pMemoryRequirements->memoryRequirements);
+}
+
+VkResult libresoc_BindImageMemory2(VkDevice device,
+ uint32_t bindInfoCount,
+ const VkBindImageMemoryInfo *pBindInfos)
+{
+ for (uint32_t i = 0; i < bindInfoCount; ++i) {
+ LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, pBindInfos[i].memory);
+ LIBRESOC_FROM_HANDLE(libresoc_image, image, pBindInfos[i].image);
+
+ if (mem) {
+ // image->bo = mem->bo;
+ // image->offset = pBindInfos[i].memoryOffset;
+ } else {
+ // image->bo = NULL;
+ // image->offset = 0;
+ }
+ }
+ return VK_SUCCESS;
+}
+
+
+VkResult libresoc_BindImageMemory(
+ VkDevice device,
+ VkImage image,
+ VkDeviceMemory memory,
+ VkDeviceSize memoryOffset)
+{
+ const VkBindImageMemoryInfo info = {
+ .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
+ .image = image,
+ .memory = memory,
+ .memoryOffset = memoryOffset
+ };
+
+ return libresoc_BindImageMemory2(device, 1, &info);
+}
+
+static VkResult libresoc_queue_submit(struct libresoc_queue *queue,
+ const struct libresoc_queue_submission *submission)
+{
+ return VK_SUCCESS;
+ // struct libresoc_deferred_queue_submission *deferred = NULL;
+
+ // VkResult result = libresoc_create_deferred_submission(queue, submission, &deferred);
+ // if (result != VK_SUCCESS)
+ // return result;
+
+ // struct list_head processing_list;
+ // list_inithead(&processing_list);
+
+ // result = libresoc_queue_enqueue_submission(deferred, &processing_list);
+ // if (result != VK_SUCCESS) {
+ // /* If anything is in the list we leak. */
+ // assert(list_is_empty(&processing_list));
+ // return result;
+ // }
+ // return libresoc_process_submissions(&processing_list);
+}
+
+/* Signals fence as soon as all the work currently put on queue is done. */
+static VkResult libresoc_signal_fence(struct libresoc_queue *queue,
+ VkFence fence)
+{
+ return libresoc_queue_submit(queue, &(struct libresoc_queue_submission) {
+ .fence = fence
+ });
+}
+
+static bool libresoc_submit_has_effects(const VkSubmitInfo *info)
+{
+ return info->commandBufferCount ||
+ info->waitSemaphoreCount ||
+ info->signalSemaphoreCount;
+}
+
+VkResult libresoc_QueueSubmit(
+ VkQueue _queue,
+ uint32_t submitCount,
+ const VkSubmitInfo* pSubmits,
+ VkFence fence)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_queue, queue, _queue);
+ VkResult result;
+ uint32_t fence_idx = 0;
+ bool flushed_caches = false;
+
+ if (fence != VK_NULL_HANDLE) {
+ for (uint32_t i = 0; i < submitCount; ++i)
+ if (libresoc_submit_has_effects(pSubmits + i))
+ fence_idx = i;
+ } else
+ fence_idx = UINT32_MAX;
+
+ for (uint32_t i = 0; i < submitCount; i++) {
+ if (!libresoc_submit_has_effects(pSubmits + i) && fence_idx != i)
+ continue;
+
+ VkPipelineStageFlags wait_dst_stage_mask = 0;
+ for (unsigned j = 0; j < pSubmits[i].waitSemaphoreCount; ++j) {
+ wait_dst_stage_mask |= pSubmits[i].pWaitDstStageMask[j];
+ }
+
+ const VkTimelineSemaphoreSubmitInfo *timeline_info =
+ vk_find_struct_const(pSubmits[i].pNext, TIMELINE_SEMAPHORE_SUBMIT_INFO);
+
+ result = libresoc_queue_submit(queue, &(struct libresoc_queue_submission) {
+ .cmd_buffers = pSubmits[i].pCommandBuffers,
+ .cmd_buffer_count = pSubmits[i].commandBufferCount,
+ .wait_dst_stage_mask = wait_dst_stage_mask,
+ .flush_caches = !flushed_caches,
+ .wait_semaphores = pSubmits[i].pWaitSemaphores,
+ .wait_semaphore_count = pSubmits[i].waitSemaphoreCount,
+ .signal_semaphores = pSubmits[i].pSignalSemaphores,
+ .signal_semaphore_count = pSubmits[i].signalSemaphoreCount,
+ .fence = i == fence_idx ? fence : VK_NULL_HANDLE,
+ .wait_values = timeline_info ? timeline_info->pWaitSemaphoreValues : NULL,
+ .wait_value_count = timeline_info && timeline_info->pWaitSemaphoreValues ? timeline_info->waitSemaphoreValueCount : 0,
+ .signal_values = timeline_info ? timeline_info->pSignalSemaphoreValues : NULL,
+ .signal_value_count = timeline_info && timeline_info->pSignalSemaphoreValues ? timeline_info->signalSemaphoreValueCount : 0,
+ });
+ if (result != VK_SUCCESS)
+ return result;
+
+ flushed_caches = true;
+ }
+
+ if (fence != VK_NULL_HANDLE && !submitCount) {
+ result = libresoc_signal_fence(queue, fence);
+ if (result != VK_SUCCESS)
+ return result;
+ }
+
+ return VK_SUCCESS;
}
+
+VkResult libresoc_CreateFence(
+ VkDevice _device,
+ const VkFenceCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFence* pFence)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ const VkExportFenceCreateInfo *export =
+ vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO);
+ VkExternalFenceHandleTypeFlags handleTypes =
+ export ? export->handleTypes : 0;
+ struct libresoc_fence *fence;
+
+ fence = vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*fence), 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+ if (!fence)
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ vk_object_base_init(&device->vk, &fence->base, VK_OBJECT_TYPE_FENCE);
+
+ // if (device->always_use_syncobj || handleTypes) {
+ // fence->permanent.kind = LIBRESOC_FENCE_SYNCOBJ;
+
+ // bool create_signaled = false;
+ // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
+ // create_signaled = true;
+
+ // int ret = device->ws->create_syncobj(device->ws, create_signaled,
+ // &fence->permanent.syncobj);
+ // if (ret) {
+ // libresoc_destroy_fence(device, pAllocator, fence);
+ // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+ // }
+ // } else {
+ // fence->permanent.kind = LIBRESOC_FENCE_WINSYS;
+
+ // fence->permanent.fence = device->ws->create_fence();
+ // if (!fence->permanent.fence) {
+ // vk_free2(&device->vk.alloc, pAllocator, fence);
+ // libresoc_destroy_fence(device, pAllocator, fence);
+ // return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+ // }
+ // if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT)
+ // device->ws->signal_fence(fence->permanent.fence);
+ // }
+
+ *pFence = libresoc_fence_to_handle(fence);
+
+ return VK_SUCCESS;
+}
+
+VkResult libresoc_MapMemory(
+ VkDevice _device,
+ VkDeviceMemory _memory,
+ VkDeviceSize offset,
+ VkDeviceSize size,
+ VkMemoryMapFlags flags,
+ void** ppData)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _memory);
+
+ if (mem == NULL) {
+ *ppData = NULL;
+ return VK_SUCCESS;
+ }
+
+ if (mem->user_ptr)
+ *ppData = mem->user_ptr;
+ // else
+ // *ppData = device->ws->buffer_map(mem->bo);
+
+ if (*ppData) {
+ *ppData += offset;
+ return VK_SUCCESS;
+ }
+
+ return vk_error(device->instance, VK_ERROR_MEMORY_MAP_FAILED);
+}
+
+void libresoc_UnmapMemory(
+ VkDevice _device,
+ VkDeviceMemory _memory)
+{
+ LIBRESOC_FROM_HANDLE(libresoc_device, device, _device);
+ LIBRESOC_FROM_HANDLE(libresoc_device_memory, mem, _memory);
+
+ if (mem == NULL)
+ return;
+
+ // if (mem->user_ptr == NULL)
+ // device->ws->buffer_unmap(mem->bo);
+}
+
+VkResult libresoc_WaitForFences(
+ VkDevice _device,
+ uint32_t fenceCount,
+ const VkFence* pFences,
+ VkBool32 waitAll,
+ uint64_t timeout)
+{
+ //TODO: stub
+ return VK_SUCCESS;
+}
+
+VkResult libresoc_ResetFences(VkDevice _device,
+ uint32_t fenceCount,
+ const VkFence *pFences)
+{
+
+ //TODO: stub
+ return VK_SUCCESS;
+}
+
+VkResult libresoc_CreateFramebuffer(
+ VkDevice _device,
+ const VkFramebufferCreateInfo* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkFramebuffer* pFramebuffer)
+{
+ //TODO: stub
+ return VK_SUCCESS;
+}
+void libresoc_DestroyBuffer(
+ VkDevice _device,
+ VkBuffer _buffer,
+ const VkAllocationCallbacks* pAllocator)
+{}
+
+void libresoc_DestroyFence(
+ VkDevice _device,
+ VkFence _fence,
+ const VkAllocationCallbacks* pAllocator)
+{}