From ac2916a48d2d3ae9bc602f4489e55456ac5b7e5c Mon Sep 17 00:00:00 2001 From: Vivek Pandya Date: Sun, 30 Aug 2020 13:47:17 +0530 Subject: [PATCH] Add code to few more essential methods in libresoc_device.c Currently code failes in libresoc_CreateDevice() because it requires implementation for libresoc_CreatePipelineCache(). --- src/libre-soc/vulkan/libresoc_constants.h | 94 ++++ src/libre-soc/vulkan/libresoc_device.c | 571 +++++++++++++++++++++- src/libre-soc/vulkan/libresoc_private.h | 25 +- 3 files changed, 671 insertions(+), 19 deletions(-) create mode 100644 src/libre-soc/vulkan/libresoc_constants.h diff --git a/src/libre-soc/vulkan/libresoc_constants.h b/src/libre-soc/vulkan/libresoc_constants.h new file mode 100644 index 00000000000..48b0a586307 --- /dev/null +++ b/src/libre-soc/vulkan/libresoc_constants.h @@ -0,0 +1,94 @@ +/* + * Copyright © 2016 Red Hat. + * Copyright © 2016 Bas Nieuwenhuizen + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef LIBRESOC_CONSTANTS_H +#define LIBRESOC_CONSTANTS_H + +#define ATI_VENDOR_ID 0x1002 + +#define MAX_VBS 32 +#define MAX_VERTEX_ATTRIBS 32 +#define MAX_RTS 8 +#define MAX_VIEWPORTS 16 +#define MAX_SCISSORS 16 +#define MAX_DISCARD_RECTANGLES 4 +#define MAX_SAMPLE_LOCATIONS 32 +#define MAX_PUSH_CONSTANTS_SIZE 128 +#define MAX_PUSH_DESCRIPTORS 32 +#define MAX_DYNAMIC_UNIFORM_BUFFERS 16 +#define MAX_DYNAMIC_STORAGE_BUFFERS 8 +#define MAX_DYNAMIC_BUFFERS (MAX_DYNAMIC_UNIFORM_BUFFERS + MAX_DYNAMIC_STORAGE_BUFFERS) +#define MAX_SAMPLES_LOG2 4 +#define NUM_META_FS_KEYS 12 +#define LIBRESOC_MAX_DRM_DEVICES 8 +#define MAX_VIEWS 8 +#define MAX_SO_STREAMS 4 +#define MAX_SO_BUFFERS 4 +#define MAX_SO_OUTPUTS 64 +#define MAX_INLINE_UNIFORM_BLOCK_SIZE (4ull * 1024 * 1024) +#define MAX_INLINE_UNIFORM_BLOCK_COUNT 64 +#define MAX_BIND_POINTS 2 /* compute + graphics */ + +#define NUM_DEPTH_CLEAR_PIPELINES 3 +#define NUM_DEPTH_DECOMPRESS_PIPELINES 3 + +/* + * This is the point we switch from using CP to compute shader + * for certain buffer operations. + */ +#define LIBRESOC_BUFFER_OPS_CS_THRESHOLD 4096 + +#define LIBRESOC_BUFFER_UPDATE_THRESHOLD 1024 + +/* descriptor index into scratch ring offsets */ +#define RING_SCRATCH 0 +#define RING_ESGS_VS 1 +#define RING_ESGS_GS 2 +#define RING_GSVS_VS 3 +#define RING_GSVS_GS 4 +#define RING_HS_TESS_FACTOR 5 +#define RING_HS_TESS_OFFCHIP 6 +#define RING_PS_SAMPLE_POSITIONS 7 + +/* max number of descriptor sets */ +#define MAX_SETS 32 + +/* Make sure everything is addressable by a signed 32-bit int, and + * our largest descriptors are 96 bytes. + */ +#define LIBRESOC_MAX_PER_SET_DESCRIPTORS ((1ull << 31 ) / 96) + +/* Our buffer size fields allow only 2**32 - 1. We round that down to a multiple + * of 4 bytes so we can align buffer sizes up. + */ +#define LIBRESOC_MAX_MEMORY_ALLOCATION_SIZE 0xFFFFFFFCull + +/* Number of invocations in each subgroup. */ +#define LIBRESOC_SUBGROUP_SIZE 64 + +#endif /* LIBRESOC_CONSTANTS_H */ + diff --git a/src/libre-soc/vulkan/libresoc_device.c b/src/libre-soc/vulkan/libresoc_device.c index 8c0f576a151..d7290de6962 100644 --- a/src/libre-soc/vulkan/libresoc_device.c +++ b/src/libre-soc/vulkan/libresoc_device.c @@ -101,7 +101,72 @@ libresoc_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, 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; + } /*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); *pInstance = libresoc_instance_to_handle(instance); return VK_SUCCESS; @@ -134,6 +199,8 @@ libresoc_physical_device_try_create(struct libresoc_instance *instance, device->_loader_data.loaderMagic = ICD_LOADER_MAGIC; device->instance = instance; + snprintf(device->name, sizeof(device->name), + "LIBRE-SOC DEVICE"); *device_out = device; return VK_SUCCESS; @@ -143,6 +210,10 @@ 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 @@ -150,7 +221,11 @@ libresoc_enumerate_physical_devices(struct libresoc_instance *instance) struct libresoc_physical_device *pdevice; result = libresoc_physical_device_try_create(instance, &pdevice); - return result; + if (result != VK_SUCCESS) + return result; + + list_addtail(&pdevice->link, &instance->physical_devices); + return VK_SUCCESS; } @@ -169,13 +244,14 @@ libresoc_EnumeratePhysicalDevices(VkInstance _instance, if (result != VK_SUCCESS) return result; - vk_outarray_append(&out, i) { - *i = libresoc_physical_device_to_handle(&instance->physical_device); + 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); - /* FIXME: stub */ - return VK_SUCCESS; } void @@ -185,7 +261,75 @@ libresoc_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, 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 @@ -195,7 +339,169 @@ libresoc_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, 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, + .deviceID = 1, + .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 @@ -206,7 +512,18 @@ libresoc_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, 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 @@ -293,7 +610,7 @@ libresoc_GetInstanceProcAddr(VkInstance _instance, idx = libresoc_get_physical_device_entrypoint_index(pName); if (idx >= 0) - return instance->physical_device.dispatch.entrypoints[idx]; + return instance->physical_device_dispatch.entrypoints[idx]; idx = libresoc_get_device_entrypoint_index(pName); if (idx >= 0) @@ -364,7 +681,7 @@ vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance, if (idx < 0) return NULL; - return instance->physical_device.dispatch.entrypoints[idx]; + return instance->physical_device_dispatch.entrypoints[idx]; } VkResult @@ -376,10 +693,145 @@ libresoc_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, 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 +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; +} +*/ +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; + 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, @@ -389,8 +841,99 @@ libresoc_CreateDevice(VkPhysicalDevice physicalDevice, 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 diff --git a/src/libre-soc/vulkan/libresoc_private.h b/src/libre-soc/vulkan/libresoc_private.h index 5aba3eb4142..1cb3b0519b4 100644 --- a/src/libre-soc/vulkan/libresoc_private.h +++ b/src/libre-soc/vulkan/libresoc_private.h @@ -4,7 +4,7 @@ * based in part on anv driver which is: * Copyright © 2015 Intel Corporation * - * based in part on radv driver which is: + * based in part on libresoc driver which is: * Copyright © 2016 Red Hat. * Copyright © 2016 Bas Nieuwenhuizen * @@ -35,20 +35,21 @@ #include #include -//#include "common/libresoc_device_info.h" - #include "vk_debug_report.h" #include "util/xmlconfig.h" #include "vk_object.h" #include "libresoc_entrypoints.h" #include "libresoc_extensions.h" +#include "libresoc_constants.h" +#define LIBRESOC_MAX_QUEUE_FAMILIES 1 struct libresoc_instance; struct libresoc_device { VK_LOADER_DATA _loader_data; + struct vk_device vk; VkAllocationCallbacks alloc; struct libresoc_instance *instance; @@ -56,6 +57,11 @@ struct libresoc_device { struct libresoc_device_extension_table enabled_extensions; struct libresoc_device_dispatch_table dispatch; + struct libresoc_queue *queues[LIBRESOC_MAX_QUEUE_FAMILIES]; + int queue_count[LIBRESOC_MAX_QUEUE_FAMILIES]; + struct radeon_cmdbuf *empty_cs[LIBRESOC_MAX_QUEUE_FAMILIES]; + struct libresoc_physical_device *physical_device; + /* FIXME: stub */ }; @@ -63,11 +69,13 @@ struct libresoc_device { struct libresoc_physical_device { VK_LOADER_DATA _loader_data; + struct list_head link; struct libresoc_instance *instance; struct libresoc_device_extension_table supported_extensions; struct libresoc_physical_device_dispatch_table dispatch; + char name[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; /* FIXME: stub */ }; @@ -85,14 +93,19 @@ struct libresoc_instance { VkAllocationCallbacks alloc; + uint32_t apiVersion; + + char * engineName; + uint32_t engineVersion; struct libresoc_app_info app_info; + bool physical_devices_enumerated; struct libresoc_instance_extension_table enabled_extensions; struct libresoc_instance_dispatch_table dispatch; struct libresoc_device_dispatch_table device_dispatch; - + struct libresoc_physical_device_dispatch_table physical_device_dispatch; int physical_device_count; - struct libresoc_physical_device physical_device; + struct list_head physical_devices; struct vk_debug_report_instance debug_report_callbacks; }; @@ -102,6 +115,8 @@ struct libresoc_queue { struct libresoc_device *device; + uint32_t queue_family_index; + int queue_idx; VkDeviceQueueCreateFlags flags; /* FIXME: stub */ -- 2.30.2