#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/driconf.h"
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->has_reg_timestamp = anv_gem_reg_read(fd, TIMESTAMP | I915_REG_READ_8B_WA,
&u64_ignore) == 0;
- device->has_mem_available = get_available_system_memory() != 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_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++)
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;
*/
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,
"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 (!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.
*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;
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) {
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