#include <stdbool.h>
#include <string.h>
#include <sys/mman.h>
-#include <sys/sysinfo.h>
#include <unistd.h>
#include <fcntl.h>
-#include <xf86drm.h>
#include "drm-uapi/drm_fourcc.h"
+#include "drm-uapi/drm.h"
+#include <xf86drm.h>
#include "anv_private.h"
#include "util/debug.h"
#include "util/disk_cache.h"
#include "util/mesa-sha1.h"
#include "util/os_file.h"
+#include "util/os_misc.h"
#include "util/u_atomic.h"
#include "util/u_string.h"
-#include "util/xmlpool.h"
+#include "util/driconf.h"
#include "git_sha1.h"
#include "vk_util.h"
#include "common/gen_aux_map.h"
*/
#define MAX_DEBUG_MESSAGE_LENGTH 4096
+/* Render engine timestamp register */
+#define TIMESTAMP 0x2358
+
static void
compiler_debug_log(void *data, const char *fmt, ...)
{
anv_compute_heap_size(int fd, uint64_t gtt_size)
{
/* Query the total ram from the system */
- struct sysinfo info;
- sysinfo(&info);
-
- uint64_t total_ram = (uint64_t)info.totalram * (uint64_t)info.mem_unit;
+ uint64_t total_ram;
+ if (!os_get_total_physical_memory(&total_ram))
+ return 0;
/* We don't want to burn too much ram with the GPU. If the user has 4GiB
* or less, we use at most half. If they have more than 4GiB, we use 3/4.
#endif
}
-static uint64_t
-get_available_system_memory()
-{
- char *meminfo = os_read_file("/proc/meminfo", NULL);
- if (!meminfo)
- return 0;
-
- char *str = strstr(meminfo, "MemAvailable:");
- if (!str) {
- free(meminfo);
- return 0;
- }
-
- uint64_t kb_mem_available;
- if (sscanf(str, "MemAvailable: %" PRIx64, &kb_mem_available) == 1) {
- free(meminfo);
- return kb_mem_available << 10;
- }
-
- free(meminfo);
- return 0;
-}
-
static VkResult
anv_physical_device_try_create(struct anv_instance *instance,
drmDevicePtr drm_device,
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_syncobj_wait_available =
+ anv_gem_get_drm_cap(fd, DRM_CAP_SYNCOBJ_TIMELINE) != 0;
+
device->has_context_priority = anv_gem_has_context_priority(fd);
result = anv_physical_device_init_heaps(device, fd);
device->has_context_isolation =
anv_gem_get_param(fd, I915_PARAM_HAS_CONTEXT_ISOLATION);
+ device->has_exec_timeline =
+ anv_gem_get_param(fd, I915_PARAM_HAS_EXEC_TIMELINE_FENCES);
+ if (env_var_as_boolean("ANV_QUEUE_THREAD_DISABLE", false))
+ device->has_exec_timeline = false;
+
+ device->has_thread_submit =
+ device->has_syncobj_wait_available && device->has_exec_timeline;
+
device->always_use_bindless =
env_var_as_boolean("ANV_ALWAYS_BINDLESS", false);
+ device->use_call_secondary =
+ device->use_softpin &&
+ !env_var_as_boolean("ANV_DISABLE_SECONDARY_CMD_BUFFER_CALLS", false);
+
/* We first got the A64 messages on broadwell and we can only use them if
* we can pass addresses directly into the shader which requires softpin.
*/
device->has_implicit_ccs = device->info.has_aux_map;
- device->has_mem_available = get_available_system_memory() != 0;
+ /* Check if we can read the GPU timestamp register from the CPU */
+ uint64_t u64_ignore;
+ device->has_reg_timestamp = anv_gem_reg_read(fd, TIMESTAMP | I915_REG_READ_8B_WA,
+ &u64_ignore) == 0;
+
+ uint64_t avail_mem;
+ device->has_mem_available = os_get_available_system_memory(&avail_mem);
device->always_flush_cache =
driQueryOptionb(&instance->dri_options, "always_flush_cache");
driParseOptionInfo(&instance->available_dri_options, anv_dri_options_xml);
driParseConfigFiles(&instance->dri_options, &instance->available_dri_options,
0, "anv", NULL,
+ instance->app_info.app_name,
+ instance->app_info.app_version,
instance->app_info.engine_name,
instance->app_info.engine_version);
vk_foreach_struct(ext, pFeatures->pNext) {
switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
+ VkPhysicalDevice4444FormatsFeaturesEXT *features =
+ (VkPhysicalDevice4444FormatsFeaturesEXT *)ext;
+ features->formatA4R4G4B4 = true;
+ features->formatA4B4G4R4 = false;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: {
VkPhysicalDevice8BitStorageFeaturesKHR *features =
(VkPhysicalDevice8BitStorageFeaturesKHR *)ext;
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT: {
+ VkPhysicalDeviceImageRobustnessFeaturesEXT *features =
+ (VkPhysicalDeviceImageRobustnessFeaturesEXT *)ext;
+ features->robustImageAccess = true;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =
(VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_CREATION_CACHE_CONTROL_FEATURES_EXT: {
+ VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT *features =
+ (VkPhysicalDevicePipelineCreationCacheControlFeaturesEXT *)ext;
+ features->pipelineCreationCacheControl = true;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: {
VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *features =
(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *)ext;
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT: {
+ VkPhysicalDeviceShaderAtomicFloatFeaturesEXT *features = (void *)ext;
+ features->shaderBufferFloat32Atomics = true;
+ features->shaderBufferFloat32AtomicAdd = false;
+ features->shaderBufferFloat64Atomics = false;
+ features->shaderBufferFloat64AtomicAdd = false;
+ features->shaderSharedFloat32Atomics = true;
+ features->shaderSharedFloat32AtomicAdd = false;
+ features->shaderSharedFloat64Atomics = false;
+ features->shaderSharedFloat64AtomicAdd = false;
+ features->shaderImageFloat32Atomics = true;
+ features->shaderImageFloat32AtomicAdd = false;
+ features->sparseImageFloat32Atomics = false;
+ features->sparseImageFloat32AtomicAdd = false;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR: {
VkPhysicalDeviceShaderAtomicInt64FeaturesKHR *features = (void *)ext;
CORE_FEATURE(1, 2, shaderBufferInt64Atomics);
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: {
+ VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL *features =
+ (VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL *)ext;
+ features->shaderIntegerFunctions2 = true;
+ break;
+ }
+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_SUBGROUP_EXTENDED_TYPES_FEATURES_KHR: {
VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR *features =
(VkPhysicalDeviceShaderSubgroupExtendedTypesFeaturesKHR *)ext;
break;
}
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: {
+ VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *features =
+ (VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *)ext;
+ features->extendedDynamicState = true;
+ break;
+ }
+
default:
anv_debug_ignored_stype(ext->sType);
break;
VkPhysicalDeviceMemoryBudgetPropertiesEXT *memoryBudget)
{
ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
- uint64_t sys_available = get_available_system_memory();
- assert(sys_available > 0);
+ uint64_t sys_available;
+ ASSERTED bool has_available_memory =
+ os_get_available_system_memory(&sys_available);
+ assert(has_available_memory);
VkDeviceSize total_heaps_size = 0;
for (size_t i = 0; i < device->memory.heap_count; i++)
return vk_outarray_status(&out);
}
-static void
-anv_device_init_dispatch(struct anv_device *device)
-{
- const struct anv_instance *instance = device->physical->instance;
-
- const struct anv_device_dispatch_table *genX_table;
- switch (device->info.gen) {
- case 12:
- genX_table = &gen12_device_dispatch_table;
- break;
- case 11:
- genX_table = &gen11_device_dispatch_table;
- break;
- case 10:
- genX_table = &gen10_device_dispatch_table;
- break;
- case 9:
- genX_table = &gen9_device_dispatch_table;
- break;
- case 8:
- genX_table = &gen8_device_dispatch_table;
- break;
- case 7:
- if (device->info.is_haswell)
- genX_table = &gen75_device_dispatch_table;
- else
- genX_table = &gen7_device_dispatch_table;
- break;
- default:
- unreachable("unsupported gen\n");
- }
-
- for (unsigned i = 0; i < ARRAY_SIZE(device->dispatch.entrypoints); i++) {
- /* Vulkan requires that entrypoints for extensions which have not been
- * enabled must not be advertised.
- */
- if (!anv_device_entrypoint_is_enabled(i, instance->app_info.api_version,
- &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_device_dispatch_table.entrypoints[i];
- }
- }
-}
-
static int
vk_priority_to_gen(int priority)
{
goto fail_fd;
}
+ device->has_thread_submit = physical_device->has_thread_submit;
+
result = anv_queue_init(device, &device->queue);
if (result != VK_SUCCESS)
goto fail_context_id;
device->robust_buffer_access = robust_buffer_access;
device->enabled_extensions = enabled_extensions;
- anv_device_init_dispatch(device);
+ const struct anv_instance *instance = physical_device->instance;
+ for (unsigned i = 0; i < ARRAY_SIZE(device->dispatch.entrypoints); i++) {
+ /* Vulkan requires that entrypoints for extensions which have not been
+ * enabled must not be advertised.
+ */
+ if (!anv_device_entrypoint_is_enabled(i, instance->app_info.api_version,
+ &instance->enabled_extensions,
+ &device->enabled_extensions)) {
+ device->dispatch.entrypoints[i] = NULL;
+ } else {
+ device->dispatch.entrypoints[i] =
+ anv_resolve_device_entrypoint(&device->info, i);
+ }
+ }
if (pthread_mutex_init(&device->mutex, NULL) != 0) {
result = vk_error(VK_ERROR_INITIALIZATION_FAILED);
*/
anv_state_reserved_pool_init(&device->custom_border_colors,
&device->dynamic_state_pool,
- sizeof(struct gen8_border_color),
- MAX_CUSTOM_BORDER_COLORS, 64);
+ MAX_CUSTOM_BORDER_COLORS,
+ sizeof(struct gen8_border_color), 64);
}
result = anv_state_pool_init(&device->instruction_state_pool, device,
goto fail_surface_state_pool;
}
- if (device->info.gen >= 12) {
+ if (device->info.has_aux_map) {
device->aux_map_ctx = gen_aux_map_init(device, &aux_map_allocator,
&physical_device->info);
if (!device->aux_map_ctx)
"Anv") + 8, 8),
};
- if (!device->info.has_llc) {
- gen_clflush_range(device->workaround_bo->map,
- device->workaround_address.offset);
- }
+ device->debug_frame_desc =
+ intel_debug_get_identifier_block(device->workaround_bo->map,
+ device->workaround_bo->size,
+ GEN_DEBUG_BLOCK_TYPE_FRAME);
result = anv_device_init_trivial_batch(device);
if (result != VK_SUCCESS)
if (result != VK_SUCCESS)
goto fail_clear_value_bo;
- anv_pipeline_cache_init(&device->default_pipeline_cache, device, true);
+ anv_pipeline_cache_init(&device->default_pipeline_cache, device,
+ true /* cache_enabled */, false /* external_sync */);
anv_device_init_blorp(device);
fail_workaround_bo:
anv_device_release_bo(device, device->workaround_bo);
fail_surface_aux_map_pool:
- if (device->info.gen >= 12) {
+ if (device->info.has_aux_map) {
gen_aux_map_finish(device->aux_map_ctx);
device->aux_map_ctx = NULL;
}
if (!device)
return;
+ anv_queue_finish(&device->queue);
+
anv_device_finish_blorp(device);
anv_pipeline_cache_finish(&device->default_pipeline_cache);
- anv_queue_finish(&device->queue);
-
#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.
if (device->info.gen >= 10)
anv_device_release_bo(device, device->hiz_clear_bo);
- if (device->info.gen >= 12) {
+ if (device->info.has_aux_map) {
gen_aux_map_finish(device->aux_map_ctx);
device->aux_map_ctx = NULL;
}
*pQueue = NULL;
}
+void
+_anv_device_report_lost(struct anv_device *device)
+{
+ assert(p_atomic_read(&device->_lost) > 0);
+
+ device->lost_reported = true;
+
+ struct anv_queue *queue = &device->queue;
+
+ __vk_errorf(device->physical->instance, device,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
+ VK_ERROR_DEVICE_LOST,
+ queue->error_file, queue->error_line,
+ "%s", queue->error_msg);
+}
+
VkResult
_anv_device_set_lost(struct anv_device *device,
const char *file, int line,
VkResult err;
va_list ap;
+ if (p_atomic_read(&device->_lost) > 0)
+ return VK_ERROR_DEVICE_LOST;
+
p_atomic_inc(&device->_lost);
+ device->lost_reported = true;
va_start(ap, msg);
err = __vk_errorv(device->physical->instance, device,
VkResult
_anv_queue_set_lost(struct anv_queue *queue,
- const char *file, int line,
- const char *msg, ...)
+ const char *file, int line,
+ const char *msg, ...)
{
- VkResult err;
va_list ap;
- p_atomic_inc(&queue->device->_lost);
+ if (queue->lost)
+ return VK_ERROR_DEVICE_LOST;
+ queue->lost = true;
+
+ queue->error_file = file;
+ queue->error_line = line;
va_start(ap, msg);
- err = __vk_errorv(queue->device->physical->instance, queue->device,
- VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
- VK_ERROR_DEVICE_LOST, file, line, msg, ap);
+ vsnprintf(queue->error_msg, sizeof(queue->error_msg),
+ msg, ap);
va_end(ap);
+ p_atomic_inc(&queue->device->_lost);
+
if (env_var_as_boolean("ANV_ABORT_ON_DEVICE_LOSS", false))
abort();
- return err;
+ return VK_ERROR_DEVICE_LOST;
}
VkResult
static const VkTimeDomainEXT anv_time_domains[] = {
VK_TIME_DOMAIN_DEVICE_EXT,
VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT,
+#ifdef CLOCK_MONOTONIC_RAW
VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT,
+#endif
};
VkResult anv_GetPhysicalDeviceCalibrateableTimeDomainsEXT(
int ret;
ret = clock_gettime(clock_id, ¤t);
+#ifdef CLOCK_MONOTONIC_RAW
if (ret < 0 && clock_id == CLOCK_MONOTONIC_RAW)
ret = clock_gettime(CLOCK_MONOTONIC, ¤t);
+#endif
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,
uint64_t begin, end;
uint64_t max_clock_period = 0;
+#ifdef CLOCK_MONOTONIC_RAW
begin = anv_clock_gettime(CLOCK_MONOTONIC_RAW);
+#else
+ begin = anv_clock_gettime(CLOCK_MONOTONIC);
+#endif
for (d = 0; d < timestampCount; d++) {
switch (pTimestampInfos[d].timeDomain) {
case VK_TIME_DOMAIN_DEVICE_EXT:
- ret = anv_gem_reg_read(device, TIMESTAMP | 1,
+ ret = anv_gem_reg_read(device->fd, TIMESTAMP | I915_REG_READ_8B_WA,
&pTimestamps[d]);
if (ret != 0) {
max_clock_period = MAX2(max_clock_period, 1);
break;
+#ifdef CLOCK_MONOTONIC_RAW
case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT:
pTimestamps[d] = begin;
break;
+#endif
default:
pTimestamps[d] = 0;
break;
}
}
+#ifdef CLOCK_MONOTONIC_RAW
end = anv_clock_gettime(CLOCK_MONOTONIC_RAW);
+#else
+ end = anv_clock_gettime(CLOCK_MONOTONIC);
+#endif
/*
* The maximum deviation is the sum of the interval over which we