#include "util/build_id.h"
#include "util/mesa-sha1.h"
#include "vk_util.h"
+#include "common/gen_defines.h"
#include "genxml/gen7_pack.h"
}
static VkResult
-anv_compute_heap_size(int fd, uint64_t *heap_size)
+anv_compute_heap_size(int fd, uint64_t gtt_size, uint64_t *heap_size)
{
- uint64_t gtt_size;
- if (anv_gem_get_context_param(fd, 0, I915_CONTEXT_PARAM_GTT_SIZE,
- >t_size) == -1) {
- /* If, for whatever reason, we can't actually get the GTT size from the
- * kernel (too old?) fall back to the aperture size.
- */
- anv_perf_warn(NULL, NULL,
- "Failed to get I915_CONTEXT_PARAM_GTT_SIZE: %m");
-
- if (anv_gem_get_aperture(fd, >t_size) == -1) {
- return vk_errorf(NULL, NULL, VK_ERROR_INITIALIZATION_FAILED,
- "failed to get aperture size: %m");
- }
- }
-
/* Query the total ram from the system */
struct sysinfo info;
sysinfo(&info);
static VkResult
anv_physical_device_init_heaps(struct anv_physical_device *device, int fd)
{
- /* The kernel query only tells us whether or not the kernel supports the
- * EXEC_OBJECT_SUPPORTS_48B_ADDRESS flag and not whether or not the
- * hardware has actual 48bit address support.
- */
- device->supports_48bit_addresses =
- (device->info.gen >= 8) && anv_gem_supports_48b_addresses(fd);
+ uint64_t gtt_size;
+ if (anv_gem_get_context_param(fd, 0, I915_CONTEXT_PARAM_GTT_SIZE,
+ >t_size) == -1) {
+ /* If, for whatever reason, we can't actually get the GTT size from the
+ * kernel (too old?) fall back to the aperture size.
+ */
+ anv_perf_warn(NULL, NULL,
+ "Failed to get I915_CONTEXT_PARAM_GTT_SIZE: %m");
- uint64_t heap_size;
- VkResult result = anv_compute_heap_size(fd, &heap_size);
+ if (anv_gem_get_aperture(fd, >t_size) == -1) {
+ return vk_errorf(NULL, NULL, VK_ERROR_INITIALIZATION_FAILED,
+ "failed to get aperture size: %m");
+ }
+ }
+
+ device->supports_48bit_addresses = (device->info.gen >= 8) &&
+ gtt_size > (4ULL << 30 /* GiB */);
+
+ uint64_t heap_size = 0;
+ VkResult result = anv_compute_heap_size(fd, gtt_size, &heap_size);
if (result != VK_SUCCESS)
return result;
static VkResult
anv_physical_device_init(struct anv_physical_device *device,
struct anv_instance *instance,
+ const char *primary_path,
const char *path)
{
VkResult result;
int fd;
+ int master_fd = -1;
brw_process_intel_debug_variable();
assert(strlen(path) < ARRAY_SIZE(device->path));
strncpy(device->path, path, ARRAY_SIZE(device->path));
- device->chipset_id = anv_gem_get_param(fd, I915_PARAM_CHIPSET_ID);
- if (!device->chipset_id) {
- result = vk_error(VK_ERROR_INCOMPATIBLE_DRIVER);
- goto fail;
+ device->no_hw = getenv("INTEL_NO_HW") != NULL;
+
+ const int pci_id_override = gen_get_pci_device_id_override();
+ if (pci_id_override < 0) {
+ device->chipset_id = anv_gem_get_param(fd, I915_PARAM_CHIPSET_ID);
+ if (!device->chipset_id) {
+ result = vk_error(VK_ERROR_INCOMPATIBLE_DRIVER);
+ goto fail;
+ }
+ } else {
+ device->chipset_id = pci_id_override;
+ device->no_hw = true;
}
device->name = gen_get_device_name(device->chipset_id);
intel_logw("Bay Trail Vulkan support is incomplete");
} else if (device->info.gen >= 8 && device->info.gen <= 10) {
/* Gen8-10 fully supported */
+ } else if (device->info.gen == 11) {
+ intel_logw("Vulkan is not yet fully supported on gen11.");
} else {
result = vk_errorf(device->instance, device,
VK_ERROR_INCOMPATIBLE_DRIVER,
device->has_syncobj = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_FENCE_ARRAY);
device->has_syncobj_wait = device->has_syncobj &&
anv_gem_supports_syncobj_wait(fd);
+ device->has_context_priority = anv_gem_has_context_priority(fd);
+
+ device->use_softpin = anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_SOFTPIN)
+ && device->supports_48bit_addresses;
+
+ device->has_context_isolation =
+ anv_gem_get_param(fd, I915_PARAM_HAS_CONTEXT_ISOLATION);
bool swizzled = anv_gem_get_bit6_swizzle(fd, I915_TILING_X);
device->compiler->shader_debug_log = compiler_debug_log;
device->compiler->shader_perf_log = compiler_perf_log;
device->compiler->supports_pull_constants = false;
- device->compiler->constant_buffer_0_is_relative = true;
+ device->compiler->constant_buffer_0_is_relative =
+ device->info.gen < 8 || !device->has_context_isolation;
isl_device_init(&device->isl_dev, &device->info, swizzled);
if (result != VK_SUCCESS)
goto fail;
+ if (instance->enabled_extensions.KHR_display) {
+ master_fd = open(primary_path, O_RDWR | O_CLOEXEC);
+ if (master_fd >= 0) {
+ /* prod the device with a GETPARAM call which will fail if
+ * we don't have permission to even render on this device
+ */
+ if (anv_gem_get_param(master_fd, I915_PARAM_CHIPSET_ID) == 0) {
+ close(master_fd);
+ master_fd = -1;
+ }
+ }
+ }
+ device->master_fd = master_fd;
+
result = anv_init_wsi(device);
if (result != VK_SUCCESS) {
ralloc_free(device->compiler);
anv_physical_device_get_supported_extensions(device,
&device->supported_extensions);
+
device->local_fd = fd;
+
return VK_SUCCESS;
fail:
close(fd);
+ if (master_fd != -1)
+ close(master_fd);
return result;
}
anv_finish_wsi(device);
ralloc_free(device->compiler);
close(device->local_fd);
+ if (device->master_fd >= 0)
+ close(device->master_fd);
}
static void *
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
- /* Check if user passed a debug report callback to be used during
- * Create/Destroy of instance.
- */
- const VkDebugReportCallbackCreateInfoEXT *ctor_cb =
- vk_find_struct_const(pCreateInfo->pNext,
- DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT);
-
- uint32_t client_version;
- if (pCreateInfo->pApplicationInfo &&
- pCreateInfo->pApplicationInfo->apiVersion != 0) {
- client_version = pCreateInfo->pApplicationInfo->apiVersion;
- } else {
- client_version = VK_MAKE_VERSION(1, 0, 0);
- }
-
- if (VK_MAKE_VERSION(1, 0, 0) > client_version ||
- client_version > VK_MAKE_VERSION(1, 0, 0xfff)) {
-
- if (ctor_cb && ctor_cb->flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
- ctor_cb->pfnCallback(VK_DEBUG_REPORT_ERROR_BIT_EXT,
- VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT,
- VK_NULL_HANDLE, /* No handle available yet. */
- __LINE__,
- 0,
- "anv",
- "incompatible driver version",
- ctor_cb->pUserData);
-
- return vk_errorf(NULL, NULL, VK_ERROR_INCOMPATIBLE_DRIVER,
- "Client requested version %d.%d.%d",
- VK_VERSION_MAJOR(client_version),
- VK_VERSION_MINOR(client_version),
- VK_VERSION_PATCH(client_version));
- }
-
struct anv_instance_extension_table enabled_extensions = {};
for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
int idx;
else
instance->alloc = default_alloc;
- instance->apiVersion = client_version;
+ if (pCreateInfo->pApplicationInfo &&
+ pCreateInfo->pApplicationInfo->apiVersion != 0) {
+ instance->apiVersion = pCreateInfo->pApplicationInfo->apiVersion;
+ } else {
+ anv_EnumerateInstanceVersion(&instance->apiVersion);
+ }
+
instance->enabled_extensions = enabled_extensions;
for (unsigned i = 0; i < ARRAY_SIZE(instance->dispatch.entrypoints); i++) {
result = anv_physical_device_init(&instance->physicalDevice,
instance,
+ devices[i]->nodes[DRM_NODE_PRIMARY],
devices[i]->nodes[DRM_NODE_RENDER]);
if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
break;
return result;
}
+static VkResult
+anv_instance_ensure_physical_device(struct anv_instance *instance)
+{
+ if (instance->physicalDeviceCount < 0) {
+ VkResult result = anv_enumerate_devices(instance);
+ if (result != VK_SUCCESS &&
+ result != VK_ERROR_INCOMPATIBLE_DRIVER)
+ return result;
+ }
+
+ return VK_SUCCESS;
+}
VkResult anv_EnumeratePhysicalDevices(
VkInstance _instance,
{
ANV_FROM_HANDLE(anv_instance, instance, _instance);
VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
- VkResult result;
- if (instance->physicalDeviceCount < 0) {
- result = anv_enumerate_devices(instance);
- if (result != VK_SUCCESS &&
- result != VK_ERROR_INCOMPATIBLE_DRIVER)
- return result;
+ VkResult result = anv_instance_ensure_physical_device(instance);
+ if (result != VK_SUCCESS)
+ return result;
+
+ if (instance->physicalDeviceCount == 0)
+ return VK_SUCCESS;
+
+ assert(instance->physicalDeviceCount == 1);
+ vk_outarray_append(&out, i) {
+ *i = anv_physical_device_to_handle(&instance->physicalDevice);
}
- if (instance->physicalDeviceCount > 0) {
- assert(instance->physicalDeviceCount == 1);
- vk_outarray_append(&out, i) {
- *i = anv_physical_device_to_handle(&instance->physicalDevice);
- }
+ return vk_outarray_status(&out);
+}
+
+VkResult anv_EnumeratePhysicalDeviceGroups(
+ VkInstance _instance,
+ uint32_t* pPhysicalDeviceGroupCount,
+ VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties)
+{
+ ANV_FROM_HANDLE(anv_instance, instance, _instance);
+ VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
+ pPhysicalDeviceGroupCount);
+
+ VkResult result = anv_instance_ensure_physical_device(instance);
+ if (result != VK_SUCCESS)
+ return result;
+
+ if (instance->physicalDeviceCount == 0)
+ return VK_SUCCESS;
+
+ assert(instance->physicalDeviceCount == 1);
+
+ vk_outarray_append(&out, p) {
+ p->physicalDeviceCount = 1;
+ memset(p->physicalDevices, 0, sizeof(p->physicalDevices));
+ p->physicalDevices[0] =
+ anv_physical_device_to_handle(&instance->physicalDevice);
+ p->subsetAllocation = VK_FALSE;
+
+ vk_foreach_struct(ext, p->pNext)
+ anv_debug_ignored_stype(ext->sType);
}
return vk_outarray_status(&out);
.shaderStorageImageArrayDynamicIndexing = true,
.shaderClipDistance = true,
.shaderCullDistance = true,
- .shaderFloat64 = pdevice->info.gen >= 8,
- .shaderInt64 = pdevice->info.gen >= 8,
- .shaderInt16 = false,
+ .shaderFloat64 = pdevice->info.gen >= 8 &&
+ pdevice->info.has_64bit_types,
+ .shaderInt64 = pdevice->info.gen >= 8 &&
+ pdevice->info.has_64bit_types,
+ .shaderInt16 = pdevice->info.gen >= 8,
.shaderResourceMinLod = false,
- .variableMultisampleRate = false,
+ .variableMultisampleRate = true,
.inheritedQueries = true,
};
pdevice->compiler->scalar_stage[MESA_SHADER_GEOMETRY];
}
-void anv_GetPhysicalDeviceFeatures2KHR(
+void anv_GetPhysicalDeviceFeatures2(
VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceFeatures2KHR* pFeatures)
+ VkPhysicalDeviceFeatures2* pFeatures)
{
anv_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
vk_foreach_struct(ext, pFeatures->pNext) {
switch (ext->sType) {
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHX: {
- VkPhysicalDeviceMultiviewFeaturesKHX *features =
- (VkPhysicalDeviceMultiviewFeaturesKHX *)ext;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
+ VkPhysicalDeviceProtectedMemoryFeatures *features = (void *)ext;
+ features->protectedMemory = VK_FALSE;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
+ VkPhysicalDeviceMultiviewFeatures *features =
+ (VkPhysicalDeviceMultiviewFeatures *)ext;
features->multiview = true;
features->multiviewGeometryShader = true;
features->multiviewTessellationShader = true;
break;
}
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR: {
- VkPhysicalDeviceVariablePointerFeaturesKHR *features = (void *)ext;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES: {
+ VkPhysicalDeviceVariablePointerFeatures *features = (void *)ext;
features->variablePointersStorageBuffer = true;
features->variablePointers = true;
break;
}
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR: {
- VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR *features =
- (VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR *) ext;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
+ VkPhysicalDeviceSamplerYcbcrConversionFeatures *features =
+ (VkPhysicalDeviceSamplerYcbcrConversionFeatures *) ext;
features->samplerYcbcrConversion = true;
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES: {
+ VkPhysicalDeviceShaderDrawParameterFeatures *features = (void *)ext;
+ features->shaderDrawParameters = true;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR: {
VkPhysicalDevice16BitStorageFeaturesKHR *features =
(VkPhysicalDevice16BitStorageFeaturesKHR *)ext;
+ ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
- features->storageBuffer16BitAccess = false;
- features->uniformAndStorageBuffer16BitAccess = false;
- features->storagePushConstant16 = false;
+ features->storageBuffer16BitAccess = pdevice->info.gen >= 8;
+ features->uniformAndStorageBuffer16BitAccess = pdevice->info.gen >= 8;
+ features->storagePushConstant16 = pdevice->info.gen >= 8;
features->storageInputOutput16 = false;
break;
}
.maxGeometryOutputComponents = 128,
.maxGeometryOutputVertices = 256,
.maxGeometryTotalOutputComponents = 1024,
- .maxFragmentInputComponents = 128,
+ .maxFragmentInputComponents = 112, /* 128 components - (POS, PSIZ, CLIP_DIST0, CLIP_DIST1) */
.maxFragmentOutputAttachments = 8,
.maxFragmentDualSrcAttachments = 1,
.maxFragmentCombinedOutputResources = 8,
pdevice->pipeline_cache_uuid, VK_UUID_SIZE);
}
-void anv_GetPhysicalDeviceProperties2KHR(
+void anv_GetPhysicalDeviceProperties2(
VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceProperties2KHR* pProperties)
+ VkPhysicalDeviceProperties2* pProperties)
{
ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
break;
}
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR: {
- VkPhysicalDeviceIDPropertiesKHR *id_props =
- (VkPhysicalDeviceIDPropertiesKHR *)ext;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
+ VkPhysicalDeviceIDProperties *id_props =
+ (VkPhysicalDeviceIDProperties *)ext;
memcpy(id_props->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
memcpy(id_props->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
/* The LUID is for Windows. */
break;
}
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES_KHX: {
- VkPhysicalDeviceMultiviewPropertiesKHX *properties =
- (VkPhysicalDeviceMultiviewPropertiesKHX *)ext;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
+ VkPhysicalDeviceMaintenance3Properties *props =
+ (VkPhysicalDeviceMaintenance3Properties *)ext;
+ /* This value doesn't matter for us today as our per-stage
+ * descriptors are the real limit.
+ */
+ props->maxPerSetDescriptors = 1024;
+ props->maxMemoryAllocationSize = MAX_MEMORY_ALLOCATION_SIZE;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {
+ VkPhysicalDeviceMultiviewProperties *properties =
+ (VkPhysicalDeviceMultiviewProperties *)ext;
properties->maxMultiviewViewCount = 16;
properties->maxMultiviewInstanceIndex = UINT32_MAX / 16;
break;
}
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES_KHR: {
- VkPhysicalDevicePointClippingPropertiesKHR *properties =
- (VkPhysicalDevicePointClippingPropertiesKHR *) ext;
- properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES_KHR;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
+ VkPhysicalDevicePointClippingProperties *properties =
+ (VkPhysicalDevicePointClippingProperties *) ext;
+ properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
anv_finishme("Implement pop-free point clipping");
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: {
+ VkPhysicalDeviceSubgroupProperties *properties = (void *)ext;
+
+ properties->subgroupSize = BRW_SUBGROUP_SIZE;
+
+ VkShaderStageFlags scalar_stages = 0;
+ for (unsigned stage = 0; stage < MESA_SHADER_STAGES; stage++) {
+ if (pdevice->compiler->scalar_stage[stage])
+ scalar_stages |= mesa_to_vk_shader_stage(stage);
+ }
+ properties->supportedStages = scalar_stages;
+
+ properties->supportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT |
+ VK_SUBGROUP_FEATURE_VOTE_BIT |
+ VK_SUBGROUP_FEATURE_ARITHMETIC_BIT |
+ VK_SUBGROUP_FEATURE_BALLOT_BIT |
+ VK_SUBGROUP_FEATURE_SHUFFLE_BIT |
+ VK_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT |
+ VK_SUBGROUP_FEATURE_CLUSTERED_BIT |
+ VK_SUBGROUP_FEATURE_QUAD_BIT;
+ properties->quadOperationsInAllStages = VK_TRUE;
+ break;
+ }
+
default:
anv_debug_ignored_stype(ext->sType);
break;
}
}
-void anv_GetPhysicalDeviceQueueFamilyProperties2KHR(
+void anv_GetPhysicalDeviceQueueFamilyProperties2(
VkPhysicalDevice physicalDevice,
uint32_t* pQueueFamilyPropertyCount,
- VkQueueFamilyProperties2KHR* pQueueFamilyProperties)
+ VkQueueFamilyProperties2* pQueueFamilyProperties)
{
VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
}
}
-void anv_GetPhysicalDeviceMemoryProperties2KHR(
+void anv_GetPhysicalDeviceMemoryProperties2(
VkPhysicalDevice physicalDevice,
- VkPhysicalDeviceMemoryProperties2KHR* pMemoryProperties)
+ VkPhysicalDeviceMemoryProperties2* pMemoryProperties)
{
anv_GetPhysicalDeviceMemoryProperties(physicalDevice,
&pMemoryProperties->memoryProperties);
}
}
+void
+anv_GetDeviceGroupPeerMemoryFeatures(
+ VkDevice device,
+ uint32_t heapIndex,
+ uint32_t localDeviceIndex,
+ uint32_t remoteDeviceIndex,
+ VkPeerMemoryFeatureFlags* pPeerMemoryFeatures)
+{
+ assert(localDeviceIndex == 0 && remoteDeviceIndex == 0);
+ *pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |
+ VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |
+ VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |
+ VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;
+}
+
PFN_vkVoidFunction anv_GetInstanceProcAddr(
VkInstance _instance,
const char* pName)
LOOKUP_ANV_ENTRYPOINT(EnumerateInstanceExtensionProperties);
LOOKUP_ANV_ENTRYPOINT(EnumerateInstanceLayerProperties);
+ LOOKUP_ANV_ENTRYPOINT(EnumerateInstanceVersion);
LOOKUP_ANV_ENTRYPOINT(CreateInstance);
#undef LOOKUP_ANV_ENTRYPOINT
{
queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
queue->device = device;
- queue->pool = &device->surface_state_pool;
+ queue->flags = 0;
}
static void
if (device->instance->physicalDevice.has_exec_async)
device->trivial_batch_bo.flags |= EXEC_OBJECT_ASYNC;
+ if (device->instance->physicalDevice.use_softpin)
+ device->trivial_batch_bo.flags |= EXEC_OBJECT_PINNED;
+
+ anv_vma_alloc(device, &device->trivial_batch_bo);
+
void *map = anv_gem_mmap(device, device->trivial_batch_bo.gem_handle,
0, 4096, 0);
{
const struct anv_dispatch_table *genX_table;
switch (device->info.gen) {
+ case 11:
+ genX_table = &gen11_dispatch_table;
+ break;
case 10:
genX_table = &gen10_dispatch_table;
break;
}
}
+static int
+vk_priority_to_gen(int priority)
+{
+ switch (priority) {
+ case VK_QUEUE_GLOBAL_PRIORITY_LOW_EXT:
+ return GEN_CONTEXT_LOW_PRIORITY;
+ case VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT:
+ return GEN_CONTEXT_MEDIUM_PRIORITY;
+ case VK_QUEUE_GLOBAL_PRIORITY_HIGH_EXT:
+ return GEN_CONTEXT_HIGH_PRIORITY;
+ case VK_QUEUE_GLOBAL_PRIORITY_REALTIME_EXT:
+ return GEN_CONTEXT_REALTIME_PRIORITY;
+ default:
+ unreachable("Invalid priority");
+ }
+}
+
+static void
+anv_device_init_hiz_clear_batch(struct anv_device *device)
+{
+ anv_bo_init_new(&device->hiz_clear_bo, device, 4096);
+ uint32_t *map = anv_gem_mmap(device, device->hiz_clear_bo.gem_handle,
+ 0, 4096, 0);
+
+ union isl_color_value hiz_clear = { .u32 = { 0, } };
+ hiz_clear.f32[0] = ANV_HZ_FC_VAL;
+
+ memcpy(map, hiz_clear.u32, sizeof(hiz_clear.u32));
+ anv_gem_munmap(map, device->hiz_clear_bo.size);
+}
+
VkResult anv_CreateDevice(
VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
}
}
+ /* Check requested queues and fail if we are requested to create any
+ * queues with flags we don't support.
+ */
+ assert(pCreateInfo->queueCreateInfoCount > 0);
+ for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
+ if (pCreateInfo->pQueueCreateInfos[i].flags != 0)
+ return vk_error(VK_ERROR_INITIALIZATION_FAILED);
+ }
+
+ /* Check if client specified queue priority. */
+ const VkDeviceQueueGlobalPriorityCreateInfoEXT *queue_priority =
+ vk_find_struct_const(pCreateInfo->pQueueCreateInfos[0].pNext,
+ DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_EXT);
+
+ VkQueueGlobalPriorityEXT priority =
+ queue_priority ? queue_priority->globalPriority :
+ VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT;
+
device = vk_alloc2(&physical_device->instance->alloc, pAllocator,
sizeof(*device), 8,
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
device->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
device->instance = physical_device->instance;
device->chipset_id = physical_device->chipset_id;
+ device->no_hw = physical_device->no_hw;
device->lost = false;
if (pAllocator)
goto fail_fd;
}
+ if (physical_device->use_softpin) {
+ if (pthread_mutex_init(&device->vma_mutex, NULL) != 0) {
+ result = vk_error(VK_ERROR_INITIALIZATION_FAILED);
+ goto fail_fd;
+ }
+
+ /* keep the page with address zero out of the allocator */
+ util_vma_heap_init(&device->vma_lo, LOW_HEAP_MIN_ADDRESS, LOW_HEAP_SIZE);
+ device->vma_lo_available =
+ physical_device->memory.heaps[physical_device->memory.heap_count - 1].size;
+
+ /* Leave the last 4GiB out of the high vma range, so that no state base
+ * address + size can overflow 48 bits. For more information see the
+ * comment about Wa32bitGeneralStateOffset in anv_allocator.c
+ */
+ util_vma_heap_init(&device->vma_hi, HIGH_HEAP_MIN_ADDRESS,
+ HIGH_HEAP_SIZE);
+ device->vma_hi_available = physical_device->memory.heap_count == 1 ? 0 :
+ physical_device->memory.heaps[0].size;
+ }
+
+ /* As per spec, the driver implementation may deny requests to acquire
+ * a priority above the default priority (MEDIUM) if the caller does not
+ * have sufficient privileges. In this scenario VK_ERROR_NOT_PERMITTED_EXT
+ * is returned.
+ */
+ if (physical_device->has_context_priority) {
+ int err = anv_gem_set_context_param(device->fd, device->context_id,
+ I915_CONTEXT_PARAM_PRIORITY,
+ vk_priority_to_gen(priority));
+ if (err != 0 && priority > VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_EXT) {
+ result = vk_error(VK_ERROR_NOT_PERMITTED_EXT);
+ goto fail_fd;
+ }
+ }
+
device->info = physical_device->info;
device->isl_dev = physical_device->isl_dev;
uint64_t bo_flags =
(physical_device->supports_48bit_addresses ? EXEC_OBJECT_SUPPORTS_48B_ADDRESS : 0) |
(physical_device->has_exec_async ? EXEC_OBJECT_ASYNC : 0) |
- (physical_device->has_exec_capture ? EXEC_OBJECT_CAPTURE : 0);
+ (physical_device->has_exec_capture ? EXEC_OBJECT_CAPTURE : 0) |
+ (physical_device->use_softpin ? EXEC_OBJECT_PINNED : 0);
anv_bo_pool_init(&device->batch_bo_pool, device, bo_flags);
if (result != VK_SUCCESS)
goto fail_batch_bo_pool;
- /* For the state pools we explicitly disable 48bit. */
- bo_flags = (physical_device->has_exec_async ? EXEC_OBJECT_ASYNC : 0) |
- (physical_device->has_exec_capture ? EXEC_OBJECT_CAPTURE : 0);
+ if (!physical_device->use_softpin)
+ bo_flags &= ~EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
- result = anv_state_pool_init(&device->dynamic_state_pool, device, 16384,
+ result = anv_state_pool_init(&device->dynamic_state_pool, device,
+ DYNAMIC_STATE_POOL_MIN_ADDRESS,
+ 16384,
bo_flags);
if (result != VK_SUCCESS)
goto fail_bo_cache;
- result = anv_state_pool_init(&device->instruction_state_pool, device, 16384,
+ result = anv_state_pool_init(&device->instruction_state_pool, device,
+ INSTRUCTION_STATE_POOL_MIN_ADDRESS,
+ 16384,
bo_flags);
if (result != VK_SUCCESS)
goto fail_dynamic_state_pool;
- result = anv_state_pool_init(&device->surface_state_pool, device, 4096,
+ result = anv_state_pool_init(&device->surface_state_pool, device,
+ SURFACE_STATE_POOL_MIN_ADDRESS,
+ 4096,
bo_flags);
if (result != VK_SUCCESS)
goto fail_instruction_state_pool;
+ if (physical_device->use_softpin) {
+ result = anv_state_pool_init(&device->binding_table_pool, device,
+ BINDING_TABLE_POOL_MIN_ADDRESS,
+ 4096,
+ bo_flags);
+ if (result != VK_SUCCESS)
+ goto fail_surface_state_pool;
+ }
+
result = anv_bo_init_new(&device->workaround_bo, device, 1024);
if (result != VK_SUCCESS)
- goto fail_surface_state_pool;
+ goto fail_binding_table_pool;
+
+ if (physical_device->use_softpin)
+ device->workaround_bo.flags |= EXEC_OBJECT_PINNED;
+
+ if (!anv_vma_alloc(device, &device->workaround_bo))
+ goto fail_workaround_bo;
anv_device_init_trivial_batch(device);
+ if (device->info.gen >= 10)
+ anv_device_init_hiz_clear_batch(device);
+
anv_scratch_pool_init(device, &device->scratch_pool);
anv_queue_init(device, &device->queue);
anv_scratch_pool_finish(device, &device->scratch_pool);
anv_gem_munmap(device->workaround_bo.map, device->workaround_bo.size);
anv_gem_close(device, device->workaround_bo.gem_handle);
+ fail_binding_table_pool:
+ if (physical_device->use_softpin)
+ anv_state_pool_finish(&device->binding_table_pool);
fail_surface_state_pool:
anv_state_pool_finish(&device->surface_state_pool);
fail_instruction_state_pool:
anv_scratch_pool_finish(device, &device->scratch_pool);
anv_gem_munmap(device->workaround_bo.map, device->workaround_bo.size);
+ anv_vma_free(device, &device->workaround_bo);
anv_gem_close(device, device->workaround_bo.gem_handle);
+ anv_vma_free(device, &device->trivial_batch_bo);
anv_gem_close(device, device->trivial_batch_bo.gem_handle);
+ if (device->info.gen >= 10)
+ anv_gem_close(device, device->hiz_clear_bo.gem_handle);
anv_state_pool_finish(&device->surface_state_pool);
anv_state_pool_finish(&device->instruction_state_pool);
*pQueue = anv_queue_to_handle(&device->queue);
}
+void anv_GetDeviceQueue2(
+ VkDevice _device,
+ const VkDeviceQueueInfo2* pQueueInfo,
+ VkQueue* pQueue)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+
+ assert(pQueueInfo->queueIndex == 0);
+
+ if (pQueueInfo->flags == device->queue.flags)
+ *pQueue = anv_queue_to_handle(&device->queue);
+ else
+ *pQueue = NULL;
+}
+
VkResult
anv_device_query_status(struct anv_device *device)
{
return anv_device_submit_simple_batch(device, &batch);
}
+bool
+anv_vma_alloc(struct anv_device *device, struct anv_bo *bo)
+{
+ if (!(bo->flags & EXEC_OBJECT_PINNED))
+ return true;
+
+ pthread_mutex_lock(&device->vma_mutex);
+
+ bo->offset = 0;
+
+ if (bo->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS &&
+ device->vma_hi_available >= bo->size) {
+ uint64_t addr = util_vma_heap_alloc(&device->vma_hi, bo->size, 4096);
+ if (addr) {
+ bo->offset = gen_canonical_address(addr);
+ assert(addr == gen_48b_address(bo->offset));
+ device->vma_hi_available -= bo->size;
+ }
+ }
+
+ if (bo->offset == 0 && device->vma_lo_available >= bo->size) {
+ uint64_t addr = util_vma_heap_alloc(&device->vma_lo, bo->size, 4096);
+ if (addr) {
+ bo->offset = gen_canonical_address(addr);
+ assert(addr == gen_48b_address(bo->offset));
+ device->vma_lo_available -= bo->size;
+ }
+ }
+
+ pthread_mutex_unlock(&device->vma_mutex);
+
+ return bo->offset != 0;
+}
+
+void
+anv_vma_free(struct anv_device *device, struct anv_bo *bo)
+{
+ if (!(bo->flags & EXEC_OBJECT_PINNED))
+ return;
+
+ const uint64_t addr_48b = gen_48b_address(bo->offset);
+
+ pthread_mutex_lock(&device->vma_mutex);
+
+ if (addr_48b >= LOW_HEAP_MIN_ADDRESS &&
+ addr_48b <= LOW_HEAP_MAX_ADDRESS) {
+ util_vma_heap_free(&device->vma_lo, addr_48b, bo->size);
+ device->vma_lo_available += bo->size;
+ } else {
+ assert(addr_48b >= HIGH_HEAP_MIN_ADDRESS &&
+ addr_48b <= HIGH_HEAP_MAX_ADDRESS);
+ util_vma_heap_free(&device->vma_hi, addr_48b, bo->size);
+ device->vma_hi_available += bo->size;
+ }
+
+ pthread_mutex_unlock(&device->vma_mutex);
+
+ bo->offset = 0;
+}
+
VkResult
anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size)
{
/* The Vulkan 1.0.33 spec says "allocationSize must be greater than 0". */
assert(pAllocateInfo->allocationSize > 0);
- /* The kernel relocation API has a limitation of a 32-bit delta value
- * applied to the address before it is written which, in spite of it being
- * unsigned, is treated as signed . Because of the way that this maps to
- * the Vulkan API, we cannot handle an offset into a buffer that does not
- * fit into a signed 32 bits. The only mechanism we have for dealing with
- * this at the moment is to limit all VkDeviceMemory objects to a maximum
- * of 2GB each. The Vulkan spec allows us to do this:
- *
- * "Some platforms may have a limit on the maximum size of a single
- * allocation. For example, certain systems may fail to create
- * allocations with a size greater than or equal to 4GB. Such a limit is
- * implementation-dependent, and if such a failure occurs then the error
- * VK_ERROR_OUT_OF_DEVICE_MEMORY should be returned."
- *
- * We don't use vk_error here because it's not an error so much as an
- * indication to the application that the allocation is too large.
- */
- if (pAllocateInfo->allocationSize > (1ull << 31))
+ if (pAllocateInfo->allocationSize > MAX_MEMORY_ALLOCATION_SIZE)
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
/* FINISHME: Fail if allocation request exceeds heap size. */
mem->map = NULL;
mem->map_size = 0;
+ uint64_t bo_flags = 0;
+
+ assert(mem->type->heapIndex < pdevice->memory.heap_count);
+ if (pdevice->memory.heaps[mem->type->heapIndex].supports_48bit_addresses)
+ bo_flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
+
+ const struct wsi_memory_allocate_info *wsi_info =
+ vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA);
+ if (wsi_info && wsi_info->implicit_sync) {
+ /* We need to set the WRITE flag on window system buffers so that GEM
+ * will know we're writing to them and synchronize uses on other rings
+ * (eg if the display server uses the blitter ring).
+ */
+ bo_flags |= EXEC_OBJECT_WRITE;
+ } else if (pdevice->has_exec_async) {
+ bo_flags |= EXEC_OBJECT_ASYNC;
+ }
+
+ if (pdevice->use_softpin)
+ bo_flags |= EXEC_OBJECT_PINNED;
+
const VkImportMemoryFdInfoKHR *fd_info =
vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
if (fd_info && fd_info->handleType) {
/* At the moment, we support only the below handle types. */
assert(fd_info->handleType ==
- VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR ||
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
fd_info->handleType ==
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
result = anv_bo_cache_import(device, &device->bo_cache,
- fd_info->fd, &mem->bo);
+ fd_info->fd, bo_flags, &mem->bo);
if (result != VK_SUCCESS)
goto fail;
close(fd_info->fd);
} else {
result = anv_bo_cache_alloc(device, &device->bo_cache,
- pAllocateInfo->allocationSize,
+ pAllocateInfo->allocationSize, bo_flags,
&mem->bo);
if (result != VK_SUCCESS)
goto fail;
}
}
- assert(mem->type->heapIndex < pdevice->memory.heap_count);
- if (pdevice->memory.heaps[mem->type->heapIndex].supports_48bit_addresses)
- mem->bo->flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
-
- const struct wsi_memory_allocate_info *wsi_info =
- vk_find_struct_const(pAllocateInfo->pNext, WSI_MEMORY_ALLOCATE_INFO_MESA);
- if (wsi_info && wsi_info->implicit_sync) {
- /* We need to set the WRITE flag on window system buffers so that GEM
- * will know we're writing to them and synchronize uses on other rings
- * (eg if the display server uses the blitter ring).
- */
- mem->bo->flags |= EXEC_OBJECT_WRITE;
- } else if (pdevice->has_exec_async) {
- mem->bo->flags |= EXEC_OBJECT_ASYNC;
- }
-
*pMem = anv_device_memory_to_handle(mem);
return VK_SUCCESS;
assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
- assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR ||
+ assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
return anv_bo_cache_export(dev, &dev->bo_cache, mem->bo, pFd);
*
* So opaque handle types fall into the default "unsupported" case.
*/
- return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR);
+ return vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE);
}
}
pMemoryRequirements->size = buffer->size;
pMemoryRequirements->alignment = alignment;
+
+ /* Storage and Uniform buffers should have their size aligned to
+ * 32-bits to avoid boundary checks when last DWord is not complete.
+ * This would ensure that not internal padding would be needed for
+ * 16-bit types.
+ */
+ if (device->robust_buffer_access &&
+ (buffer->usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ||
+ buffer->usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT))
+ pMemoryRequirements->size = align_u64(buffer->size, 4);
+
pMemoryRequirements->memoryTypeBits = memory_types;
}
-void anv_GetBufferMemoryRequirements2KHR(
+void anv_GetBufferMemoryRequirements2(
VkDevice _device,
- const VkBufferMemoryRequirementsInfo2KHR* pInfo,
- VkMemoryRequirements2KHR* pMemoryRequirements)
+ const VkBufferMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements)
{
anv_GetBufferMemoryRequirements(_device, pInfo->buffer,
&pMemoryRequirements->memoryRequirements);
vk_foreach_struct(ext, pMemoryRequirements->pNext) {
switch (ext->sType) {
- case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR: {
- VkMemoryDedicatedRequirementsKHR *requirements = (void *)ext;
+ case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
+ VkMemoryDedicatedRequirements *requirements = (void *)ext;
requirements->prefersDedicatedAllocation = VK_FALSE;
requirements->requiresDedicatedAllocation = VK_FALSE;
break;
pMemoryRequirements->memoryTypeBits = memory_types;
}
-void anv_GetImageMemoryRequirements2KHR(
+void anv_GetImageMemoryRequirements2(
VkDevice _device,
- const VkImageMemoryRequirementsInfo2KHR* pInfo,
- VkMemoryRequirements2KHR* pMemoryRequirements)
+ const VkImageMemoryRequirementsInfo2* pInfo,
+ VkMemoryRequirements2* pMemoryRequirements)
{
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_image, image, pInfo->image);
vk_foreach_struct_const(ext, pInfo->pNext) {
switch (ext->sType) {
- case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO_KHR: {
+ case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO: {
struct anv_physical_device *pdevice = &device->instance->physicalDevice;
const VkImagePlaneMemoryRequirementsInfoKHR *plane_reqs =
(const VkImagePlaneMemoryRequirementsInfoKHR *) ext;
vk_foreach_struct(ext, pMemoryRequirements->pNext) {
switch (ext->sType) {
- case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR: {
- VkMemoryDedicatedRequirementsKHR *requirements = (void *)ext;
+ case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
+ VkMemoryDedicatedRequirements *requirements = (void *)ext;
if (image->needs_set_tiling) {
/* If we need to set the tiling for external consumers, we need a
* dedicated allocation.
*pSparseMemoryRequirementCount = 0;
}
-void anv_GetImageSparseMemoryRequirements2KHR(
+void anv_GetImageSparseMemoryRequirements2(
VkDevice device,
- const VkImageSparseMemoryRequirementsInfo2KHR* pInfo,
+ const VkImageSparseMemoryRequirementsInfo2* pInfo,
uint32_t* pSparseMemoryRequirementCount,
- VkSparseImageMemoryRequirements2KHR* pSparseMemoryRequirements)
+ VkSparseImageMemoryRequirements2* pSparseMemoryRequirements)
{
*pSparseMemoryRequirementCount = 0;
}
}
static void
-anv_bind_buffer_memory(const VkBindBufferMemoryInfoKHR *pBindInfo)
+anv_bind_buffer_memory(const VkBindBufferMemoryInfo *pBindInfo)
{
ANV_FROM_HANDLE(anv_device_memory, mem, pBindInfo->memory);
ANV_FROM_HANDLE(anv_buffer, buffer, pBindInfo->buffer);
- assert(pBindInfo->sType == VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR);
+ assert(pBindInfo->sType == VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO);
if (mem) {
assert((buffer->usage & mem->type->valid_buffer_usage) == buffer->usage);
- buffer->bo = mem->bo;
- buffer->offset = pBindInfo->memoryOffset;
+ buffer->address = (struct anv_address) {
+ .bo = mem->bo,
+ .offset = pBindInfo->memoryOffset,
+ };
} else {
- buffer->bo = NULL;
- buffer->offset = 0;
+ buffer->address = ANV_NULL_ADDRESS;
}
}
VkDeviceSize memoryOffset)
{
anv_bind_buffer_memory(
- &(VkBindBufferMemoryInfoKHR) {
- .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO_KHR,
+ &(VkBindBufferMemoryInfo) {
+ .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
.buffer = buffer,
.memory = memory,
.memoryOffset = memoryOffset,
return VK_SUCCESS;
}
-VkResult anv_BindBufferMemory2KHR(
+VkResult anv_BindBufferMemory2(
VkDevice device,
uint32_t bindInfoCount,
- const VkBindBufferMemoryInfoKHR* pBindInfos)
+ const VkBindBufferMemoryInfo* pBindInfos)
{
for (uint32_t i = 0; i < bindInfoCount; i++)
anv_bind_buffer_memory(&pBindInfos[i]);
buffer->size = pCreateInfo->size;
buffer->usage = pCreateInfo->usage;
- buffer->bo = NULL;
- buffer->offset = 0;
+ buffer->address = ANV_NULL_ADDRESS;
*pBuffer = anv_buffer_to_handle(buffer);
void
anv_fill_buffer_surface_state(struct anv_device *device, struct anv_state state,
enum isl_format format,
- uint32_t offset, uint32_t range, uint32_t stride)
+ struct anv_address address,
+ uint32_t range, uint32_t stride)
{
isl_buffer_fill_state(&device->isl_dev, state.map,
- .address = offset,
+ .address = anv_address_physical(address),
.mocs = device->default_mocs,
.size = range,
.format = format,