#include <unistd.h>
#include <fcntl.h>
#include <xf86drm.h>
-#include <drm_fourcc.h>
+#include "drm-uapi/drm_fourcc.h"
#include "anv_private.h"
#include "util/strtod.h"
#include "util/debug.h"
#include "util/build_id.h"
+#include "util/disk_cache.h"
#include "util/mesa-sha1.h"
+#include "util/u_string.h"
+#include "git_sha1.h"
#include "vk_util.h"
#include "common/gen_defines.h"
va_end(args);
}
-static VkResult
-anv_compute_heap_size(int fd, uint64_t *heap_size)
+static uint64_t
+anv_compute_heap_size(int fd, uint64_t gtt_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);
*/
uint64_t available_gtt = gtt_size * 3 / 4;
- *heap_size = MIN2(available_ram, available_gtt);
-
- return VK_SUCCESS;
+ return MIN2(available_ram, available_gtt);
}
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 (result != VK_SUCCESS)
- return result;
+ 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 = anv_compute_heap_size(fd, gtt_size);
if (heap_size > (2ull << 30) && !device->supports_48bit_addresses) {
/* When running with an overridden PCI ID, we may get a GTT size from
"build-id too short. It needs to be a SHA");
}
+ memcpy(device->driver_build_sha1, build_id_data(note), 20);
+
struct mesa_sha1 sha1_ctx;
uint8_t sha1[20];
STATIC_ASSERT(VK_UUID_SIZE <= sizeof(sha1));
return VK_SUCCESS;
}
+static void
+anv_physical_device_init_disk_cache(struct anv_physical_device *device)
+{
+#ifdef ENABLE_SHADER_CACHE
+ char renderer[10];
+ MAYBE_UNUSED int len = snprintf(renderer, sizeof(renderer), "anv_%04x",
+ device->chipset_id);
+ assert(len == sizeof(renderer) - 2);
+
+ char timestamp[41];
+ _mesa_sha1_format(timestamp, device->driver_build_sha1);
+
+ const uint64_t driver_flags =
+ brw_get_compiler_config_value(device->compiler);
+ device->disk_cache = disk_cache_create(renderer, timestamp, driver_flags);
+#else
+ device->disk_cache = NULL;
+#endif
+}
+
+static void
+anv_physical_device_free_disk_cache(struct anv_physical_device *device)
+{
+#ifdef ENABLE_SHADER_CACHE
+ if (device->disk_cache)
+ disk_cache_destroy(device->disk_cache);
+#else
+ assert(device->disk_cache == NULL);
+#endif
+}
+
static VkResult
anv_physical_device_init(struct anv_physical_device *device,
struct anv_instance *instance,
- const char *path)
+ drmDevicePtr drm_device)
{
+ const char *primary_path = drm_device->nodes[DRM_NODE_PRIMARY];
+ const char *path = drm_device->nodes[DRM_NODE_RENDER];
VkResult result;
int fd;
+ int master_fd = -1;
brw_process_intel_debug_variable();
device->instance = instance;
assert(strlen(path) < ARRAY_SIZE(device->path));
- strncpy(device->path, path, ARRAY_SIZE(device->path));
+ snprintf(device->path, ARRAY_SIZE(device->path), "%s", path);
device->no_hw = getenv("INTEL_NO_HW") != NULL;
device->no_hw = true;
}
+ device->pci_info.domain = drm_device->businfo.pci->domain;
+ device->pci_info.bus = drm_device->businfo.pci->bus;
+ device->pci_info.device = drm_device->businfo.pci->dev;
+ device->pci_info.function = drm_device->businfo.pci->func;
+
device->name = gen_get_device_name(device->chipset_id);
if (!gen_get_device_info(device->chipset_id, &device->info)) {
result = vk_error(VK_ERROR_INCOMPATIBLE_DRIVER);
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,
anv_gem_supports_syncobj_wait(fd);
device->has_context_priority = anv_gem_has_context_priority(fd);
- bool swizzled = anv_gem_get_bit6_swizzle(fd, I915_TILING_X);
+ 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);
/* Starting with Gen10, the timestamp frequency of the command streamer may
* vary from one part to another. We can query the value from the kernel.
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;
+ device->compiler->supports_shader_constants = true;
+
+ /* Broadwell PRM says:
+ *
+ * "Before Gen8, there was a historical configuration control field to
+ * swizzle address bit[6] for in X/Y tiling modes. This was set in three
+ * different places: TILECTL[1:0], ARB_MODE[5:4], and
+ * DISP_ARB_CTL[14:13].
+ *
+ * For Gen8 and subsequent generations, the swizzle fields are all
+ * reserved, and the CPU's memory controller performs all address
+ * swizzling modifications."
+ */
+ bool swizzled =
+ device->info.gen < 8 && anv_gem_get_bit6_swizzle(fd, I915_TILING_X);
isl_device_init(&device->isl_dev, &device->info, swizzled);
if (result != VK_SUCCESS)
goto fail;
+ anv_physical_device_init_disk_cache(device);
+
+ 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_free_disk_cache(device);
goto fail;
}
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_physical_device_finish(struct anv_physical_device *device)
{
anv_finish_wsi(device);
+ anv_physical_device_free_disk_cache(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;
+ instance->app_info = (struct anv_app_info) { .api_version = 0 };
+ if (pCreateInfo->pApplicationInfo) {
+ const VkApplicationInfo *app = pCreateInfo->pApplicationInfo;
+
+ instance->app_info.app_name =
+ vk_strdup(&instance->alloc, app->pApplicationName,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ instance->app_info.app_version = app->applicationVersion;
+
+ instance->app_info.engine_name =
+ vk_strdup(&instance->alloc, app->pEngineName,
+ VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
+ instance->app_info.engine_version = app->engineVersion;
+
+ instance->app_info.api_version = app->apiVersion;
+ }
+
+ if (instance->app_info.api_version == 0)
+ instance->app_info.api_version = VK_API_VERSION_1_0;
+
instance->enabled_extensions = enabled_extensions;
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 (!anv_entrypoint_is_enabled(i, instance->apiVersion,
- &instance->enabled_extensions, NULL)) {
+ if (!anv_instance_entrypoint_is_enabled(i, instance->app_info.api_version,
+ &instance->enabled_extensions)) {
instance->dispatch.entrypoints[i] = NULL;
- } else if (anv_dispatch_table.entrypoints[i] != NULL) {
- instance->dispatch.entrypoints[i] = anv_dispatch_table.entrypoints[i];
} else {
instance->dispatch.entrypoints[i] =
- anv_tramp_dispatch_table.entrypoints[i];
+ anv_instance_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 (!anv_device_entrypoint_is_enabled(i, instance->app_info.api_version,
+ &instance->enabled_extensions, NULL)) {
+ instance->device_dispatch.entrypoints[i] = NULL;
+ } else {
+ instance->device_dispatch.entrypoints[i] =
+ anv_device_dispatch_table.entrypoints[i];
}
}
return vk_error(result);
}
+ instance->pipeline_cache_enabled =
+ env_var_as_boolean("ANV_ENABLE_PIPELINE_CACHE", true);
+
_mesa_locale_init();
VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
anv_physical_device_finish(&instance->physicalDevice);
}
+ vk_free(&instance->alloc, (char *)instance->app_info.app_name);
+ vk_free(&instance->alloc, (char *)instance->app_info.engine_name);
+
VG(VALGRIND_DESTROY_MEMPOOL(instance));
vk_debug_report_instance_destroy(&instance->debug_report_callbacks);
devices[i]->deviceinfo.pci->vendor_id == 0x8086) {
result = anv_physical_device_init(&instance->physicalDevice,
- instance,
- devices[i]->nodes[DRM_NODE_RENDER]);
+ instance, devices[i]);
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,
- .shaderResourceMinLod = false,
- .variableMultisampleRate = 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 = pdevice->info.gen >= 9,
+ .variableMultisampleRate = true,
.inheritedQueries = true,
};
pFeatures->vertexPipelineStoresAndAtomics =
pdevice->compiler->scalar_stage[MESA_SHADER_VERTEX] &&
pdevice->compiler->scalar_stage[MESA_SHADER_GEOMETRY];
+
+ struct anv_app_info *app_info = &pdevice->instance->app_info;
+
+ /* The new DOOM and Wolfenstein games require depthBounds without
+ * checking for it. They seem to run fine without it so just claim it's
+ * there and accept the consequences.
+ */
+ if (app_info->engine_name && strcmp(app_info->engine_name, "idTech") == 0)
+ pFeatures->depthBounds = true;
}
void anv_GetPhysicalDeviceFeatures2(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceFeatures2* pFeatures)
{
+ ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
anv_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
vk_foreach_struct(ext, pFeatures->pNext) {
switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: {
+ VkPhysicalDevice8BitStorageFeaturesKHR *features =
+ (VkPhysicalDevice8BitStorageFeaturesKHR *)ext;
+ ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
+
+ features->storageBuffer8BitAccess = pdevice->info.gen >= 8;
+ features->uniformAndStorageBuffer8BitAccess = pdevice->info.gen >= 8;
+ features->storagePushConstant8 = pdevice->info.gen >= 8;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
+ VkPhysicalDevice16BitStorageFeatures *features =
+ (VkPhysicalDevice16BitStorageFeatures *)ext;
+ features->storageBuffer16BitAccess = pdevice->info.gen >= 8;
+ features->uniformAndStorageBuffer16BitAccess = pdevice->info.gen >= 8;
+ features->storagePushConstant16 = pdevice->info.gen >= 8;
+ features->storageInputOutput16 = false;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT: {
+ VkPhysicalDeviceBufferAddressFeaturesEXT *features = (void *)ext;
+ features->bufferDeviceAddress = pdevice->use_softpin &&
+ pdevice->info.gen >= 8;
+ features->bufferDeviceAddressCaptureReplay = false;
+ features->bufferDeviceAddressMultiDevice = false;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
+ VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
+ (VkPhysicalDeviceConditionalRenderingFeaturesEXT*)ext;
+ ANV_FROM_HANDLE(anv_physical_device, pdevice, physicalDevice);
+
+ features->conditionalRendering = pdevice->info.gen >= 8 ||
+ pdevice->info.is_haswell;
+ features->inheritedConditionalRendering = pdevice->info.gen >= 8 ||
+ pdevice->info.is_haswell;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
+ VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =
+ (VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;
+ features->depthClipEnable = VK_TRUE;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT: {
+ VkPhysicalDeviceInlineUniformBlockFeaturesEXT *features =
+ (VkPhysicalDeviceInlineUniformBlockFeaturesEXT *)ext;
+ features->inlineUniformBlock = true;
+ features->descriptorBindingInlineUniformBlockUpdateAfterBind = false;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
VkPhysicalDeviceMultiviewFeatures *features =
(VkPhysicalDeviceMultiviewFeatures *)ext;
break;
}
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES: {
- VkPhysicalDeviceVariablePointerFeatures *features = (void *)ext;
- features->variablePointersStorageBuffer = true;
- features->variablePointers = true;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
+ VkPhysicalDeviceProtectedMemoryFeatures *features = (void *)ext;
+ features->protectedMemory = VK_FALSE;
break;
}
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {
+ VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *features =
+ (VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *)ext;
+ features->scalarBlockLayout = 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);
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES: {
+ VkPhysicalDeviceVariablePointerFeatures *features = (void *)ext;
+ features->variablePointersStorageBuffer = true;
+ features->variablePointers = true;
+ break;
+ }
- features->storageBuffer16BitAccess = pdevice->info.gen >= 8;
- features->uniformAndStorageBuffer16BitAccess = pdevice->info.gen >= 8;
- features->storagePushConstant16 = pdevice->info.gen >= 8;
- features->storageInputOutput16 = false;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
+ VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =
+ (VkPhysicalDeviceTransformFeedbackFeaturesEXT *)ext;
+ features->transformFeedback = VK_TRUE;
+ features->geometryStreams = VK_TRUE;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
+ VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
+ (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;
+ features->vertexAttributeInstanceRateDivisor = VK_TRUE;
+ features->vertexAttributeInstanceRateZeroDivisor = VK_TRUE;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT: {
+ VkPhysicalDeviceYcbcrImageArraysFeaturesEXT *features =
+ (VkPhysicalDeviceYcbcrImageArraysFeaturesEXT *)ext;
+ features->ycbcrImageArrays = VK_TRUE;
break;
}
const uint32_t max_samplers = (devinfo->gen >= 8 || devinfo->is_haswell) ?
128 : 16;
+ const uint32_t max_images = devinfo->gen < 9 ? MAX_GEN8_IMAGES : MAX_IMAGES;
+
VkSampleCountFlags sample_counts =
isl_device_get_sample_counts(&pdevice->isl_dev);
+
VkPhysicalDeviceLimits limits = {
.maxImageDimension1D = (1 << 14),
.maxImageDimension2D = (1 << 14),
.maxPerStageDescriptorUniformBuffers = 64,
.maxPerStageDescriptorStorageBuffers = 64,
.maxPerStageDescriptorSampledImages = max_samplers,
- .maxPerStageDescriptorStorageImages = 64,
+ .maxPerStageDescriptorStorageImages = max_images,
.maxPerStageDescriptorInputAttachments = 64,
.maxPerStageResources = 250,
.maxDescriptorSetSamplers = 6 * max_samplers, /* number of stages * maxPerStageDescriptorSamplers */
.maxDescriptorSetStorageBuffers = 6 * 64, /* number of stages * maxPerStageDescriptorStorageBuffers */
.maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_BUFFERS / 2,
.maxDescriptorSetSampledImages = 6 * max_samplers, /* number of stages * maxPerStageDescriptorSampledImages */
- .maxDescriptorSetStorageImages = 6 * 64, /* number of stages * maxPerStageDescriptorStorageImages */
+ .maxDescriptorSetStorageImages = 6 * max_images, /* number of stages * maxPerStageDescriptorStorageImages */
.maxDescriptorSetInputAttachments = 256,
.maxVertexInputAttributes = MAX_VBS,
.maxVertexInputBindings = MAX_VBS,
.maxGeometryOutputComponents = 128,
.maxGeometryOutputVertices = 256,
.maxGeometryTotalOutputComponents = 1024,
- .maxFragmentInputComponents = 128,
+ .maxFragmentInputComponents = 112, /* 128 components - (POS, PSIZ, CLIP_DIST0, CLIP_DIST1) */
.maxFragmentOutputAttachments = 8,
.maxFragmentDualSrcAttachments = 1,
.maxFragmentCombinedOutputResources = 8,
16 * devinfo->max_cs_threads,
16 * devinfo->max_cs_threads,
},
- .subPixelPrecisionBits = 4 /* FIXME */,
+ .subPixelPrecisionBits = 8,
.subTexelPrecisionBits = 4 /* FIXME */,
.mipmapPrecisionBits = 4 /* FIXME */,
.maxDrawIndexedIndexValue = UINT32_MAX,
.maxClipDistances = 8,
.maxCullDistances = 8,
.maxCombinedClipAndCullDistances = 8,
- .discreteQueuePriorities = 1,
+ .discreteQueuePriorities = 2,
.pointSizeRange = { 0.125, 255.875 },
.lineWidthRange = { 0.0, 7.9921875 },
.pointSizeGranularity = (1.0 / 8.0),
vk_foreach_struct(ext, pProperties->pNext) {
switch (ext->sType) {
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
- VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
- (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR: {
+ VkPhysicalDeviceDepthStencilResolvePropertiesKHR *props =
+ (VkPhysicalDeviceDepthStencilResolvePropertiesKHR *)ext;
+
+ /* We support all of the depth resolve modes */
+ props->supportedDepthResolveModes =
+ VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR |
+ VK_RESOLVE_MODE_AVERAGE_BIT_KHR |
+ VK_RESOLVE_MODE_MIN_BIT_KHR |
+ VK_RESOLVE_MODE_MAX_BIT_KHR;
+
+ /* Average doesn't make sense for stencil so we don't support that */
+ props->supportedStencilResolveModes =
+ VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR;
+ if (pdevice->info.gen >= 8) {
+ /* The advanced stencil resolve modes currently require stencil
+ * sampling be supported by the hardware.
+ */
+ props->supportedStencilResolveModes |=
+ VK_RESOLVE_MODE_MIN_BIT_KHR |
+ VK_RESOLVE_MODE_MAX_BIT_KHR;
+ }
- properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
+ props->independentResolveNone = VK_TRUE;
+ props->independentResolve = VK_TRUE;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR: {
+ VkPhysicalDeviceDriverPropertiesKHR *driver_props =
+ (VkPhysicalDeviceDriverPropertiesKHR *) ext;
+
+ driver_props->driverID = VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR;
+ util_snprintf(driver_props->driverName, VK_MAX_DRIVER_NAME_SIZE_KHR,
+ "Intel open-source Mesa driver");
+
+ util_snprintf(driver_props->driverInfo, VK_MAX_DRIVER_INFO_SIZE_KHR,
+ "Mesa " PACKAGE_VERSION MESA_GIT_SHA1);
+
+ driver_props->conformanceVersion = (VkConformanceVersionKHR) {
+ .major = 1,
+ .minor = 1,
+ .subminor = 2,
+ .patch = 0,
+ };
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: {
+ VkPhysicalDeviceExternalMemoryHostPropertiesEXT *props =
+ (VkPhysicalDeviceExternalMemoryHostPropertiesEXT *) ext;
+ /* Userptr needs page aligned memory. */
+ props->minImportedHostPointerAlignment = 4096;
break;
}
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES_EXT: {
+ VkPhysicalDeviceInlineUniformBlockPropertiesEXT *props =
+ (VkPhysicalDeviceInlineUniformBlockPropertiesEXT *)ext;
+ props->maxInlineUniformBlockSize = MAX_INLINE_UNIFORM_BLOCK_SIZE;
+ props->maxPerStageDescriptorInlineUniformBlocks =
+ MAX_INLINE_UNIFORM_BLOCK_DESCRIPTORS;
+ props->maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks =
+ MAX_INLINE_UNIFORM_BLOCK_DESCRIPTORS;
+ props->maxDescriptorSetInlineUniformBlocks =
+ MAX_INLINE_UNIFORM_BLOCK_DESCRIPTORS;
+ props->maxDescriptorSetUpdateAfterBindInlineUniformBlocks =
+ MAX_INLINE_UNIFORM_BLOCK_DESCRIPTORS;
+ break;
+ }
+
+ 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;
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT: {
+ VkPhysicalDevicePCIBusInfoPropertiesEXT *properties =
+ (VkPhysicalDevicePCIBusInfoPropertiesEXT *)ext;
+ properties->pciDomain = pdevice->pci_info.domain;
+ properties->pciBus = pdevice->pci_info.bus;
+ properties->pciDevice = pdevice->pci_info.device;
+ properties->pciFunction = pdevice->pci_info.function;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
VkPhysicalDevicePointClippingProperties *properties =
(VkPhysicalDevicePointClippingProperties *) ext;
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES: {
+ VkPhysicalDeviceProtectedMemoryProperties *props =
+ (VkPhysicalDeviceProtectedMemoryProperties *)ext;
+ props->protectedNoFault = false;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
+ VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
+ (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
+
+ properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES_EXT: {
+ VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT *properties =
+ (VkPhysicalDeviceSamplerFilterMinmaxPropertiesEXT *)ext;
+ properties->filterMinmaxImageComponentMapping = pdevice->info.gen >= 9;
+ properties->filterMinmaxSingleComponentFormats = true;
+ 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;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: {
+ VkPhysicalDeviceTransformFeedbackPropertiesEXT *props =
+ (VkPhysicalDeviceTransformFeedbackPropertiesEXT *)ext;
+
+ props->maxTransformFeedbackStreams = MAX_XFB_STREAMS;
+ props->maxTransformFeedbackBuffers = MAX_XFB_BUFFERS;
+ props->maxTransformFeedbackBufferSize = (1ull << 32);
+ props->maxTransformFeedbackStreamDataSize = 128 * 4;
+ props->maxTransformFeedbackBufferDataSize = 128 * 4;
+ props->maxTransformFeedbackBufferDataStride = 2048;
+ props->transformFeedbackQueries = VK_TRUE;
+ props->transformFeedbackStreamsLinesTriangles = VK_FALSE;
+ props->transformFeedbackRasterizationStreamSelect = VK_FALSE;
+ props->transformFeedbackDraw = VK_TRUE;
+ break;
+ }
+
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
+ VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props =
+ (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
+ /* We have to restrict this a bit for multiview */
+ props->maxVertexAttribDivisor = UINT32_MAX / 16;
+ break;
+ }
+
default:
anv_debug_ignored_stype(ext->sType);
break;
}
}
+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
if (instance == NULL)
return NULL;
- int idx = anv_get_entrypoint_index(pName);
- if (idx < 0)
- return NULL;
+ int idx = anv_get_instance_entrypoint_index(pName);
+ if (idx >= 0)
+ return instance->dispatch.entrypoints[idx];
+
+ idx = anv_get_device_entrypoint_index(pName);
+ if (idx >= 0)
+ return instance->device_dispatch.entrypoints[idx];
- return instance->dispatch.entrypoints[idx];
+ return NULL;
}
/* With version 1+ of the loader interface the ICD should expose
if (!device || !pName)
return NULL;
- int idx = anv_get_entrypoint_index(pName);
+ int idx = anv_get_device_entrypoint_index(pName);
if (idx < 0)
return NULL;
{
queue->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
queue->device = device;
- queue->pool = &device->surface_state_pool;
+ queue->flags = 0;
}
static void
state = anv_state_pool_alloc(pool, size, align);
memcpy(state.map, p, size);
- anv_state_flush(pool->block_pool.device, state);
-
return state;
}
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);
{
ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
- (void)device;
for (int i = 0; i < ANV_DEVICE_EXTENSION_COUNT; i++) {
if (device->supported_extensions.extensions[i]) {
static void
anv_device_init_dispatch(struct anv_device *device)
{
- const struct anv_dispatch_table *genX_table;
+ const struct anv_device_dispatch_table *genX_table;
switch (device->info.gen) {
+ case 11:
+ genX_table = &gen11_device_dispatch_table;
+ break;
case 10:
- genX_table = &gen10_dispatch_table;
+ genX_table = &gen10_device_dispatch_table;
break;
case 9:
- genX_table = &gen9_dispatch_table;
+ genX_table = &gen9_device_dispatch_table;
break;
case 8:
- genX_table = &gen8_dispatch_table;
+ genX_table = &gen8_device_dispatch_table;
break;
case 7:
if (device->info.is_haswell)
- genX_table = &gen75_dispatch_table;
+ genX_table = &gen75_device_dispatch_table;
else
- genX_table = &gen7_dispatch_table;
+ genX_table = &gen7_device_dispatch_table;
break;
default:
unreachable("unsupported gen\n");
/* Vulkan requires that entrypoints for extensions which have not been
* enabled must not be advertised.
*/
- if (!anv_entrypoint_is_enabled(i, device->instance->apiVersion,
- &device->instance->enabled_extensions,
- &device->enabled_extensions)) {
+ if (!anv_device_entrypoint_is_enabled(i, device->instance->app_info.api_version,
+ &device->instance->enabled_extensions,
+ &device->enabled_extensions)) {
device->dispatch.entrypoints[i] = NULL;
} else if (genX_table->entrypoints[i]) {
device->dispatch.entrypoints[i] = genX_table->entrypoints[i];
} else {
- device->dispatch.entrypoints[i] = anv_dispatch_table.entrypoints[i];
+ device->dispatch.entrypoints[i] =
+ anv_device_dispatch_table.entrypoints[i];
}
}
}
}
}
+static void
+anv_device_init_hiz_clear_value_bo(struct anv_device *device)
+{
+ anv_bo_init_new(&device->hiz_clear_bo, device, 4096);
+
+ if (device->instance->physicalDevice.has_exec_async)
+ device->hiz_clear_bo.flags |= EXEC_OBJECT_ASYNC;
+
+ if (device->instance->physicalDevice.use_softpin)
+ device->hiz_clear_bo.flags |= EXEC_OBJECT_PINNED;
+
+ anv_vma_alloc(device, &device->hiz_clear_bo);
+
+ 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);
+}
+
+static bool
+get_bo_from_pool(struct gen_batch_decode_bo *ret,
+ struct anv_block_pool *pool,
+ uint64_t address)
+{
+ for (uint32_t i = 0; i < pool->nbos; i++) {
+ uint64_t bo_address = pool->bos[i].offset & (~0ull >> 16);
+ uint32_t bo_size = pool->bos[i].size;
+ if (address >= bo_address && address < (bo_address + bo_size)) {
+ *ret = (struct gen_batch_decode_bo) {
+ .addr = bo_address,
+ .size = bo_size,
+ .map = pool->bos[i].map,
+ };
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Finding a buffer for batch decoding */
+static struct gen_batch_decode_bo
+decode_get_bo(void *v_batch, bool ppgtt, uint64_t address)
+{
+ struct anv_device *device = v_batch;
+ struct gen_batch_decode_bo ret_bo = {};
+
+ assert(ppgtt);
+
+ if (get_bo_from_pool(&ret_bo, &device->dynamic_state_pool.block_pool, address))
+ return ret_bo;
+ if (get_bo_from_pool(&ret_bo, &device->instruction_state_pool.block_pool, address))
+ return ret_bo;
+ if (get_bo_from_pool(&ret_bo, &device->binding_table_pool.block_pool, address))
+ return ret_bo;
+ if (get_bo_from_pool(&ret_bo, &device->surface_state_pool.block_pool, address))
+ return ret_bo;
+
+ if (!device->cmd_buffer_being_decoded)
+ return (struct gen_batch_decode_bo) { };
+
+ struct anv_batch_bo **bo;
+
+ u_vector_foreach(bo, &device->cmd_buffer_being_decoded->seen_bbos) {
+ /* The decoder zeroes out the top 16 bits, so we need to as well */
+ uint64_t bo_address = (*bo)->bo.offset & (~0ull >> 16);
+
+ if (address >= bo_address && address < bo_address + (*bo)->bo.size) {
+ return (struct gen_batch_decode_bo) {
+ .addr = bo_address,
+ .size = (*bo)->bo.size,
+ .map = (*bo)->bo.map,
+ };
+ }
+ }
+
+ return (struct gen_batch_decode_bo) { };
+}
+
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,
if (!device)
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ const unsigned decode_flags =
+ GEN_BATCH_DECODE_FULL |
+ ((INTEL_DEBUG & DEBUG_COLOR) ? GEN_BATCH_DECODE_IN_COLOR : 0) |
+ GEN_BATCH_DECODE_OFFSETS |
+ GEN_BATCH_DECODE_FLOATS;
+
+ gen_batch_decode_ctx_init(&device->decoder_ctx,
+ &physical_device->info,
+ stderr, decode_flags, NULL,
+ decode_get_bo, NULL, 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;
+ device->_lost = false;
if (pAllocator)
device->alloc = *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
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_value_bo(device);
+
+ if (physical_device->use_softpin)
+ device->pinned_buffers = _mesa_pointer_set_create(NULL);
+
anv_scratch_pool_init(device, &device->scratch_pool);
anv_queue_init(device, &device->queue);
if (result != VK_SUCCESS)
goto fail_workaround_bo;
+ anv_pipeline_cache_init(&device->default_pipeline_cache, device, true);
+
anv_device_init_blorp(device);
anv_device_init_border_colors(device);
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:
const VkAllocationCallbacks* pAllocator)
{
ANV_FROM_HANDLE(anv_device, device, _device);
+ struct anv_physical_device *physical_device;
if (!device)
return;
+ physical_device = &device->instance->physicalDevice;
+
anv_device_finish_blorp(device);
+ anv_pipeline_cache_finish(&device->default_pipeline_cache);
+
anv_queue_finish(&device->queue);
+ if (physical_device->use_softpin)
+ _mesa_set_destroy(device->pinned_buffers, NULL);
+
#ifdef HAVE_VALGRIND
/* We only need to free these to prevent valgrind errors. The backing
* BO will go away in a couple of lines so we don't actually leak.
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);
+ if (physical_device->use_softpin)
+ anv_state_pool_finish(&device->binding_table_pool);
anv_state_pool_finish(&device->surface_state_pool);
anv_state_pool_finish(&device->instruction_state_pool);
anv_state_pool_finish(&device->dynamic_state_pool);
anv_gem_destroy_context(device, device->context_id);
+ gen_batch_decode_ctx_finish(&device->decoder_ctx);
+
close(device->fd);
vk_free(&device->alloc, device);
*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_set_lost(struct anv_device *device,
+ const char *file, int line,
+ const char *msg, ...)
+{
+ VkResult err;
+ va_list ap;
+
+ device->_lost = true;
+
+ va_start(ap, msg);
+ err = __vk_errorv(device->instance, device,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
+ VK_ERROR_DEVICE_LOST, file, line, msg, ap);
+ va_end(ap);
+
+ if (env_var_as_boolean("ANV_ABORT_ON_DEVICE_LOSS", false))
+ abort();
+
+ return err;
+}
+
VkResult
anv_device_query_status(struct anv_device *device)
{
* for it. However, it doesn't hurt to check and it potentially lets us
* avoid an ioctl.
*/
- if (unlikely(device->lost))
+ if (anv_device_is_lost(device))
return VK_ERROR_DEVICE_LOST;
uint32_t active, pending;
int ret = anv_gem_gpu_get_reset_stats(device, &active, &pending);
if (ret == -1) {
/* We don't know the real error. */
- device->lost = true;
- return vk_errorf(device->instance, device, VK_ERROR_DEVICE_LOST,
- "get_reset_stats failed: %m");
+ return anv_device_set_lost(device, "get_reset_stats failed: %m");
}
if (active) {
- device->lost = true;
- return vk_errorf(device->instance, device, VK_ERROR_DEVICE_LOST,
- "GPU hung on one of our command buffers");
+ return anv_device_set_lost(device, "GPU hung on one of our command buffers");
} else if (pending) {
- device->lost = true;
- return vk_errorf(device->instance, device, VK_ERROR_DEVICE_LOST,
- "GPU hung with commands in-flight");
+ return anv_device_set_lost(device, "GPU hung with commands in-flight");
}
return VK_SUCCESS;
return VK_NOT_READY;
} else if (ret == -1) {
/* We don't know the real error. */
- device->lost = true;
- return vk_errorf(device->instance, device, VK_ERROR_DEVICE_LOST,
- "gem wait failed: %m");
+ return anv_device_set_lost(device, "gem wait failed: %m");
}
/* Query for device status after the busy call. If the BO we're checking
return VK_TIMEOUT;
} else if (ret == -1) {
/* We don't know the real error. */
- device->lost = true;
- return vk_errorf(device->instance, device, VK_ERROR_DEVICE_LOST,
- "gem wait failed: %m");
+ return anv_device_set_lost(device, "gem wait failed: %m");
}
/* Query for device status after the wait. If the BO we're waiting on got
VkDevice _device)
{
ANV_FROM_HANDLE(anv_device, device, _device);
- if (unlikely(device->lost))
+ if (anv_device_is_lost(device))
return VK_ERROR_DEVICE_LOST;
struct anv_batch batch;
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->type = &pdevice->memory.types[pAllocateInfo->memoryTypeIndex];
mem->map = NULL;
mem->map_size = 0;
+ mem->ahw = NULL;
+ mem->host_ptr = NULL;
+
+ 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 VkExportMemoryAllocateInfo *export_info =
+ vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
+
+ /* Check if we need to support Android HW buffer export. If so,
+ * create AHardwareBuffer and import memory from it.
+ */
+ bool android_export = false;
+ if (export_info && export_info->handleTypes &
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID)
+ android_export = true;
+
+ /* Android memory import. */
+ const struct VkImportAndroidHardwareBufferInfoANDROID *ahw_import_info =
+ vk_find_struct_const(pAllocateInfo->pNext,
+ IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID);
+
+ if (ahw_import_info) {
+ result = anv_import_ahw_memory(_device, mem, ahw_import_info);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ goto success;
+ } else if (android_export) {
+ result = anv_create_ahw_memory(_device, mem, pAllocateInfo);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ const struct VkImportAndroidHardwareBufferInfoANDROID import_info = {
+ .buffer = mem->ahw,
+ };
+ result = anv_import_ahw_memory(_device, mem, &import_info);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ goto success;
+ }
const VkImportMemoryFdInfoKHR *fd_info =
vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
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);
+ result = anv_bo_cache_import(device, &device->bo_cache, fd_info->fd,
+ bo_flags | ANV_BO_EXTERNAL, &mem->bo);
if (result != VK_SUCCESS)
goto fail;
*/
if (mem->bo->size < aligned_alloc_size) {
result = vk_errorf(device->instance, device,
- VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR,
+ VK_ERROR_INVALID_EXTERNAL_HANDLE,
"aligned allocationSize too large for "
- "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR: "
+ "VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT: "
"%"PRIu64"B > %"PRIu64"B",
aligned_alloc_size, mem->bo->size);
anv_bo_cache_release(device, &device->bo_cache, mem->bo);
* If the import fails, we leave the file descriptor open.
*/
close(fd_info->fd);
- } else {
- result = anv_bo_cache_alloc(device, &device->bo_cache,
- pAllocateInfo->allocationSize,
- &mem->bo);
- if (result != VK_SUCCESS)
+ goto success;
+ }
+
+ const VkImportMemoryHostPointerInfoEXT *host_ptr_info =
+ vk_find_struct_const(pAllocateInfo->pNext,
+ IMPORT_MEMORY_HOST_POINTER_INFO_EXT);
+ if (host_ptr_info && host_ptr_info->handleType) {
+ if (host_ptr_info->handleType ==
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT) {
+ result = vk_error(VK_ERROR_INVALID_EXTERNAL_HANDLE);
goto fail;
+ }
- const VkMemoryDedicatedAllocateInfoKHR *dedicated_info =
- vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO_KHR);
- if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
- ANV_FROM_HANDLE(anv_image, image, dedicated_info->image);
+ assert(host_ptr_info->handleType ==
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT);
- /* Some legacy (non-modifiers) consumers need the tiling to be set on
- * the BO. In this case, we have a dedicated allocation.
- */
- if (image->needs_set_tiling) {
- const uint32_t i915_tiling =
- isl_tiling_to_i915_tiling(image->planes[0].surface.isl.tiling);
- int ret = anv_gem_set_tiling(device, mem->bo->gem_handle,
- image->planes[0].surface.isl.row_pitch,
- i915_tiling);
- if (ret) {
- anv_bo_cache_release(device, &device->bo_cache, mem->bo);
- return vk_errorf(device->instance, NULL,
- VK_ERROR_OUT_OF_DEVICE_MEMORY,
- "failed to set BO tiling: %m");
- }
- }
- }
+ result = anv_bo_cache_import_host_ptr(
+ device, &device->bo_cache, host_ptr_info->pHostPointer,
+ pAllocateInfo->allocationSize, bo_flags, &mem->bo);
+
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ mem->host_ptr = host_ptr_info->pHostPointer;
+ goto success;
}
- 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;
+ /* Regular allocate (not importing memory). */
- 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).
+ if (export_info && export_info->handleTypes)
+ bo_flags |= ANV_BO_EXTERNAL;
+
+ result = anv_bo_cache_alloc(device, &device->bo_cache,
+ pAllocateInfo->allocationSize, bo_flags,
+ &mem->bo);
+ if (result != VK_SUCCESS)
+ goto fail;
+
+ const VkMemoryDedicatedAllocateInfo *dedicated_info =
+ vk_find_struct_const(pAllocateInfo->pNext, MEMORY_DEDICATED_ALLOCATE_INFO);
+ if (dedicated_info && dedicated_info->image != VK_NULL_HANDLE) {
+ ANV_FROM_HANDLE(anv_image, image, dedicated_info->image);
+
+ /* Some legacy (non-modifiers) consumers need the tiling to be set on
+ * the BO. In this case, we have a dedicated allocation.
*/
- mem->bo->flags |= EXEC_OBJECT_WRITE;
- } else if (pdevice->has_exec_async) {
- mem->bo->flags |= EXEC_OBJECT_ASYNC;
+ if (image->needs_set_tiling) {
+ const uint32_t i915_tiling =
+ isl_tiling_to_i915_tiling(image->planes[0].surface.isl.tiling);
+ int ret = anv_gem_set_tiling(device, mem->bo->gem_handle,
+ image->planes[0].surface.isl.row_pitch_B,
+ i915_tiling);
+ if (ret) {
+ anv_bo_cache_release(device, &device->bo_cache, mem->bo);
+ return vk_errorf(device->instance, NULL,
+ VK_ERROR_OUT_OF_DEVICE_MEMORY,
+ "failed to set BO tiling: %m");
+ }
+ }
}
+ success:
*pMem = anv_device_memory_to_handle(mem);
return VK_SUCCESS;
VkResult anv_GetMemoryFdPropertiesKHR(
VkDevice _device,
- VkExternalMemoryHandleTypeFlagBitsKHR handleType,
+ VkExternalMemoryHandleTypeFlagBits handleType,
int fd,
VkMemoryFdPropertiesKHR* pMemoryFdProperties)
{
}
}
+VkResult anv_GetMemoryHostPointerPropertiesEXT(
+ VkDevice _device,
+ VkExternalMemoryHandleTypeFlagBits handleType,
+ const void* pHostPointer,
+ VkMemoryHostPointerPropertiesEXT* pMemoryHostPointerProperties)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+
+ assert(pMemoryHostPointerProperties->sType ==
+ VK_STRUCTURE_TYPE_MEMORY_HOST_POINTER_PROPERTIES_EXT);
+
+ switch (handleType) {
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: {
+ struct anv_physical_device *pdevice = &device->instance->physicalDevice;
+
+ /* Host memory can be imported as any memory type. */
+ pMemoryHostPointerProperties->memoryTypeBits =
+ (1ull << pdevice->memory.type_count) - 1;
+
+ return VK_SUCCESS;
+ }
+ default:
+ return VK_ERROR_INVALID_EXTERNAL_HANDLE;
+ }
+}
+
void anv_FreeMemory(
VkDevice _device,
VkDeviceMemory _mem,
anv_bo_cache_release(device, &device->bo_cache, mem->bo);
+#ifdef ANDROID
+ if (mem->ahw)
+ AHardwareBuffer_release(mem->ahw);
+#endif
+
vk_free2(&device->alloc, pAllocator, mem);
}
return VK_SUCCESS;
}
+ if (mem->host_ptr) {
+ *ppData = mem->host_ptr + offset;
+ return VK_SUCCESS;
+ }
+
if (size == VK_WHOLE_SIZE)
size = mem->bo->size - offset;
{
ANV_FROM_HANDLE(anv_device_memory, mem, _memory);
- if (mem == NULL)
+ if (mem == NULL || mem->host_ptr)
return;
anv_gem_munmap(mem->map, mem->map_size);
*/
uint32_t memory_types = (1ull << pdevice->memory.type_count) - 1;
+ /* We must have image allocated or imported at this point. According to the
+ * specification, external images must have been bound to memory before
+ * calling GetImageMemoryRequirements.
+ */
+ assert(image->size > 0);
+
pMemoryRequirements->size = image->size;
pMemoryRequirements->alignment = image->alignment;
pMemoryRequirements->memoryTypeBits = memory_types;
switch (ext->sType) {
case VK_STRUCTURE_TYPE_IMAGE_PLANE_MEMORY_REQUIREMENTS_INFO: {
struct anv_physical_device *pdevice = &device->instance->physicalDevice;
- const VkImagePlaneMemoryRequirementsInfoKHR *plane_reqs =
- (const VkImagePlaneMemoryRequirementsInfoKHR *) ext;
+ const VkImagePlaneMemoryRequirementsInfo *plane_reqs =
+ (const VkImagePlaneMemoryRequirementsInfo *) ext;
uint32_t plane = anv_image_aspect_to_plane(image->aspects,
plane_reqs->planeAspect);
pMemoryRequirements->memoryRequirements.memoryTypeBits =
(1ull << pdevice->memory.type_count) - 1;
+ /* We must have image allocated or imported at this point. According to the
+ * specification, external images must have been bound to memory before
+ * calling GetImageMemoryRequirements.
+ */
+ assert(image->planes[plane].size > 0);
+
pMemoryRequirements->memoryRequirements.size = image->planes[plane].size;
pMemoryRequirements->memoryRequirements.alignment =
image->planes[plane].alignment;
switch (ext->sType) {
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
VkMemoryDedicatedRequirements *requirements = (void *)ext;
- if (image->needs_set_tiling) {
+ if (image->needs_set_tiling || image->external_format) {
/* If we need to set the tiling for external consumers, we need a
* dedicated allocation.
*
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;
}
}
VkFence fence)
{
ANV_FROM_HANDLE(anv_queue, queue, _queue);
- if (unlikely(queue->device->lost))
+ if (anv_device_is_lost(queue->device))
return VK_ERROR_DEVICE_LOST;
return vk_error(VK_ERROR_FEATURE_NOT_PRESENT);
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_event, event, _event);
- if (unlikely(device->lost))
+ if (anv_device_is_lost(device))
return VK_ERROR_DEVICE_LOST;
if (!device->info.has_llc) {
buffer->size = pCreateInfo->size;
buffer->usage = pCreateInfo->usage;
- buffer->bo = NULL;
- buffer->offset = 0;
+ buffer->address = ANV_NULL_ADDRESS;
+
+ if (buffer->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT) {
+ pthread_mutex_lock(&device->mutex);
+ _mesa_set_add(device->pinned_buffers, buffer);
+ pthread_mutex_unlock(&device->mutex);
+ }
*pBuffer = anv_buffer_to_handle(buffer);
if (!buffer)
return;
+ if (buffer->usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT_EXT) {
+ pthread_mutex_lock(&device->mutex);
+ _mesa_set_remove_key(device->pinned_buffers, buffer);
+ pthread_mutex_unlock(&device->mutex);
+ }
+
vk_free2(&device->alloc, pAllocator, buffer);
}
+VkDeviceAddress anv_GetBufferDeviceAddressEXT(
+ VkDevice device,
+ const VkBufferDeviceAddressInfoEXT* pInfo)
+{
+ ANV_FROM_HANDLE(anv_buffer, buffer, pInfo->buffer);
+
+ assert(buffer->address.bo->flags & EXEC_OBJECT_PINNED);
+
+ return anv_address_physical(buffer->address);
+}
+
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,
+ .size_B = range,
.format = format,
- .stride = stride);
-
- anv_state_flush(device, state);
+ .stride_B = stride);
}
void anv_DestroySampler(
vk_free2(&device->alloc, pAllocator, fb);
}
+static const VkTimeDomainEXT anv_time_domains[] = {
+ VK_TIME_DOMAIN_DEVICE_EXT,
+ VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT,
+ VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT,
+};
+
+VkResult anv_GetPhysicalDeviceCalibrateableTimeDomainsEXT(
+ VkPhysicalDevice physicalDevice,
+ uint32_t *pTimeDomainCount,
+ VkTimeDomainEXT *pTimeDomains)
+{
+ int d;
+ VK_OUTARRAY_MAKE(out, pTimeDomains, pTimeDomainCount);
+
+ for (d = 0; d < ARRAY_SIZE(anv_time_domains); d++) {
+ vk_outarray_append(&out, i) {
+ *i = anv_time_domains[d];
+ }
+ }
+
+ return vk_outarray_status(&out);
+}
+
+static uint64_t
+anv_clock_gettime(clockid_t clock_id)
+{
+ struct timespec current;
+ int ret;
+
+ ret = clock_gettime(clock_id, ¤t);
+ if (ret < 0 && clock_id == CLOCK_MONOTONIC_RAW)
+ ret = clock_gettime(CLOCK_MONOTONIC, ¤t);
+ if (ret < 0)
+ return 0;
+
+ return (uint64_t) current.tv_sec * 1000000000ULL + current.tv_nsec;
+}
+
+#define TIMESTAMP 0x2358
+
+VkResult anv_GetCalibratedTimestampsEXT(
+ VkDevice _device,
+ uint32_t timestampCount,
+ const VkCalibratedTimestampInfoEXT *pTimestampInfos,
+ uint64_t *pTimestamps,
+ uint64_t *pMaxDeviation)
+{
+ ANV_FROM_HANDLE(anv_device, device, _device);
+ uint64_t timestamp_frequency = device->info.timestamp_frequency;
+ int ret;
+ int d;
+ uint64_t begin, end;
+ uint64_t max_clock_period = 0;
+
+ begin = anv_clock_gettime(CLOCK_MONOTONIC_RAW);
+
+ for (d = 0; d < timestampCount; d++) {
+ switch (pTimestampInfos[d].timeDomain) {
+ case VK_TIME_DOMAIN_DEVICE_EXT:
+ ret = anv_gem_reg_read(device, TIMESTAMP | 1,
+ &pTimestamps[d]);
+
+ if (ret != 0) {
+ return anv_device_set_lost(device, "Failed to read the TIMESTAMP "
+ "register: %m");
+ }
+ uint64_t device_period = DIV_ROUND_UP(1000000000, timestamp_frequency);
+ max_clock_period = MAX2(max_clock_period, device_period);
+ break;
+ case VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT:
+ pTimestamps[d] = anv_clock_gettime(CLOCK_MONOTONIC);
+ max_clock_period = MAX2(max_clock_period, 1);
+ break;
+
+ case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT:
+ pTimestamps[d] = begin;
+ break;
+ default:
+ pTimestamps[d] = 0;
+ break;
+ }
+ }
+
+ end = anv_clock_gettime(CLOCK_MONOTONIC_RAW);
+
+ /*
+ * The maximum deviation is the sum of the interval over which we
+ * perform the sampling and the maximum period of any sampled
+ * clock. That's because the maximum skew between any two sampled
+ * clock edges is when the sampled clock with the largest period is
+ * sampled at the end of that period but right at the beginning of the
+ * sampling interval and some other clock is sampled right at the
+ * begining of its sampling period and right at the end of the
+ * sampling interval. Let's assume the GPU has the longest clock
+ * period and that the application is sampling GPU and monotonic:
+ *
+ * s e
+ * w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ * Raw -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
+ *
+ * g
+ * 0 1 2 3
+ * GPU -----_____-----_____-----_____-----_____
+ *
+ * m
+ * x y z 0 1 2 3 4 5 6 7 8 9 a b c
+ * Monotonic -_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-
+ *
+ * Interval <----------------->
+ * Deviation <-------------------------->
+ *
+ * s = read(raw) 2
+ * g = read(GPU) 1
+ * m = read(monotonic) 2
+ * e = read(raw) b
+ *
+ * We round the sample interval up by one tick to cover sampling error
+ * in the interval clock
+ */
+
+ uint64_t sample_interval = end - begin + 1;
+
+ *pMaxDeviation = sample_interval + max_clock_period;
+
+ return VK_SUCCESS;
+}
+
/* vk_icd.h does not declare this function, so we declare it here to
* suppress Wmissing-prototypes.
*/