static uint64_t
get_available_system_memory()
{
- char *meminfo = os_read_file("/proc/meminfo");
+ char *meminfo = os_read_file("/proc/meminfo", NULL);
if (!meminfo)
return 0;
*/
device->has_bindless_samplers = device->info.gen >= 8;
+ device->has_implicit_ccs = device->info.has_aux_map;
+
device->has_mem_available = get_available_system_memory() != 0;
device->always_flush_cache =
driQueryOptionb(&instance->dri_options, "always_flush_cache");
- /* 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.
- */
- if (device->info.gen >= 10) {
- int timestamp_frequency =
- anv_gem_get_param(fd, I915_PARAM_CS_TIMESTAMP_FREQUENCY);
-
- if (timestamp_frequency < 0)
- intel_logw("Kernel 4.16-rc1+ required to properly query CS timestamp frequency");
- else
- device->info.timestamp_frequency = timestamp_frequency;
- }
+ device->has_mmap_offset =
+ anv_gem_get_param(fd, I915_PARAM_MMAP_GTT_VERSION) >= 4;
/* GENs prior to 8 do not support EU/Subslice info */
if (device->info.gen >= 8) {
.shaderClipDistance = true,
.shaderCullDistance = true,
.shaderFloat64 = pdevice->info.gen >= 8 &&
- pdevice->info.has_64bit_types,
+ pdevice->info.has_64bit_float,
.shaderInt64 = pdevice->info.gen >= 8 &&
- pdevice->info.has_64bit_types,
+ pdevice->info.has_64bit_int,
.shaderInt16 = pdevice->info.gen >= 8,
.shaderResourceMinLod = pdevice->info.gen >= 9,
.variableMultisampleRate = true,
LOOKUP_ANV_ENTRYPOINT(EnumerateInstanceVersion);
LOOKUP_ANV_ENTRYPOINT(CreateInstance);
+ /* GetInstanceProcAddr() can also be called with a NULL instance.
+ * See https://gitlab.khronos.org/vulkan/vulkan/issues/2057
+ */
+ LOOKUP_ANV_ENTRYPOINT(GetInstanceProcAddr);
+
#undef LOOKUP_ANV_ENTRYPOINT
if (instance == NULL)
.free = gen_aux_map_buffer_free,
};
+static VkResult
+check_physical_device_features(VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceFeatures *features)
+{
+ VkPhysicalDeviceFeatures supported_features;
+ anv_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
+ VkBool32 *supported_feature = (VkBool32 *)&supported_features;
+ VkBool32 *enabled_feature = (VkBool32 *)features;
+ unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
+ for (uint32_t i = 0; i < num_features; i++) {
+ if (enabled_feature[i] && !supported_feature[i])
+ return vk_error(VK_ERROR_FEATURE_NOT_PRESENT);
+ }
+
+ return VK_SUCCESS;
+}
+
VkResult anv_CreateDevice(
VkPhysicalDevice physicalDevice,
const VkDeviceCreateInfo* pCreateInfo,
}
/* Check enabled features */
+ bool robust_buffer_access = false;
if (pCreateInfo->pEnabledFeatures) {
- VkPhysicalDeviceFeatures supported_features;
- anv_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
- VkBool32 *supported_feature = (VkBool32 *)&supported_features;
- VkBool32 *enabled_feature = (VkBool32 *)pCreateInfo->pEnabledFeatures;
- unsigned num_features = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
- for (uint32_t i = 0; i < num_features; i++) {
- if (enabled_feature[i] && !supported_feature[i])
- return vk_error(VK_ERROR_FEATURE_NOT_PRESENT);
+ result = check_physical_device_features(physicalDevice,
+ pCreateInfo->pEnabledFeatures);
+ if (result != VK_SUCCESS)
+ return result;
+
+ if (pCreateInfo->pEnabledFeatures->robustBufferAccess)
+ robust_buffer_access = true;
+ }
+
+ vk_foreach_struct_const(ext, pCreateInfo->pNext) {
+ switch (ext->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: {
+ const VkPhysicalDeviceFeatures2 *features = (const void *)ext;
+ result = check_physical_device_features(physicalDevice,
+ &features->features);
+ if (result != VK_SUCCESS)
+ return result;
+
+ if (features->features.robustBufferAccess)
+ robust_buffer_access = true;
+ break;
+ }
+
+ default:
+ /* Don't warn */
+ break;
}
}
*/
device->can_chain_batches = device->info.gen >= 8;
- device->robust_buffer_access = pCreateInfo->pEnabledFeatures &&
- pCreateInfo->pEnabledFeatures->robustBufferAccess;
+ device->robust_buffer_access = robust_buffer_access;
device->enabled_extensions = enabled_extensions;
anv_device_init_dispatch(device);
return anv_queue_submit_simple_batch(&device->queue, NULL);
}
-bool
-anv_vma_alloc(struct anv_device *device, struct anv_bo *bo,
+uint64_t
+anv_vma_alloc(struct anv_device *device,
+ uint64_t size, uint64_t align,
+ enum anv_bo_alloc_flags alloc_flags,
uint64_t client_address)
{
- const struct gen_device_info *devinfo = &device->info;
- /* Gen12 CCS surface addresses need to be 64K aligned. We have no way of
- * telling what this allocation is for so pick the largest alignment.
- */
- const uint32_t vma_alignment =
- devinfo->gen >= 12 ? (64 * 1024) : (4 * 1024);
-
- if (!(bo->flags & EXEC_OBJECT_PINNED)) {
- assert(!(bo->has_client_visible_address));
- return true;
- }
-
pthread_mutex_lock(&device->vma_mutex);
- bo->offset = 0;
+ uint64_t addr = 0;
- if (bo->has_client_visible_address) {
- assert(bo->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS);
+ if (alloc_flags & ANV_BO_ALLOC_CLIENT_VISIBLE_ADDRESS) {
if (client_address) {
if (util_vma_heap_alloc_addr(&device->vma_cva,
- client_address, bo->size)) {
- bo->offset = gen_canonical_address(client_address);
+ client_address, size)) {
+ addr = client_address;
}
} else {
- uint64_t addr =
- util_vma_heap_alloc(&device->vma_cva, bo->size, vma_alignment);
- if (addr) {
- bo->offset = gen_canonical_address(addr);
- assert(addr == gen_48b_address(bo->offset));
- }
+ addr = util_vma_heap_alloc(&device->vma_cva, size, align);
}
/* We don't want to fall back to other heaps */
goto done;
assert(client_address == 0);
- if (bo->flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS) {
- uint64_t addr =
- util_vma_heap_alloc(&device->vma_hi, bo->size, vma_alignment);
- if (addr) {
- bo->offset = gen_canonical_address(addr);
- assert(addr == gen_48b_address(bo->offset));
- }
- }
+ if (!(alloc_flags & ANV_BO_ALLOC_32BIT_ADDRESS))
+ addr = util_vma_heap_alloc(&device->vma_hi, size, align);
- if (bo->offset == 0) {
- uint64_t addr =
- util_vma_heap_alloc(&device->vma_lo, bo->size, vma_alignment);
- if (addr) {
- bo->offset = gen_canonical_address(addr);
- assert(addr == gen_48b_address(bo->offset));
- }
- }
+ if (addr == 0)
+ addr = util_vma_heap_alloc(&device->vma_lo, size, align);
done:
pthread_mutex_unlock(&device->vma_mutex);
- return bo->offset != 0;
+ assert(addr == gen_48b_address(addr));
+ return gen_canonical_address(addr);
}
void
-anv_vma_free(struct anv_device *device, struct anv_bo *bo)
+anv_vma_free(struct anv_device *device,
+ uint64_t address, uint64_t size)
{
- if (!(bo->flags & EXEC_OBJECT_PINNED))
- return;
-
- const uint64_t addr_48b = gen_48b_address(bo->offset);
+ const uint64_t addr_48b = gen_48b_address(address);
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);
+ util_vma_heap_free(&device->vma_lo, addr_48b, size);
} else if (addr_48b >= CLIENT_VISIBLE_HEAP_MIN_ADDRESS &&
addr_48b <= CLIENT_VISIBLE_HEAP_MAX_ADDRESS) {
- util_vma_heap_free(&device->vma_cva, addr_48b, bo->size);
+ util_vma_heap_free(&device->vma_cva, addr_48b, size);
} else {
assert(addr_48b >= HIGH_HEAP_MIN_ADDRESS);
- util_vma_heap_free(&device->vma_hi, addr_48b, bo->size);
+ util_vma_heap_free(&device->vma_hi, addr_48b, size);
}
pthread_mutex_unlock(&device->vma_mutex);
-
- bo->offset = 0;
}
VkResult anv_AllocateMemory(
}
}
+ /* By default, we want all VkDeviceMemory objects to support CCS */
+ if (device->physical->has_implicit_ccs)
+ alloc_flags |= ANV_BO_ALLOC_IMPLICIT_CCS;
+
if (vk_flags & VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR)
alloc_flags |= ANV_BO_ALLOC_CLIENT_VISIBLE_ADDRESS;
+ if ((export_info && export_info->handleTypes) ||
+ (fd_info && fd_info->handleType) ||
+ (host_ptr_info && host_ptr_info->handleType)) {
+ /* Anything imported or exported is EXTERNAL */
+ alloc_flags |= ANV_BO_ALLOC_EXTERNAL;
+
+ /* We can't have implicit CCS on external memory with an AUX-table.
+ * Doing so would require us to sync the aux tables across processes
+ * which is impractical.
+ */
+ if (device->info.has_aux_map)
+ alloc_flags &= ~ANV_BO_ALLOC_IMPLICIT_CCS;
+ }
+
/* Check if we need to support Android HW buffer export. If so,
* create AHardwareBuffer and import memory from it.
*/
if (result != VK_SUCCESS)
goto fail;
- VkDeviceSize aligned_alloc_size =
- align_u64(pAllocateInfo->allocationSize, 4096);
-
/* For security purposes, we reject importing the bo if it's smaller
* than the requested allocation size. This prevents a malicious client
* from passing a buffer to a trusted client, lying about the size, and
/* Regular allocate (not importing memory). */
- if (export_info && export_info->handleTypes)
- alloc_flags |= ANV_BO_ALLOC_EXTERNAL;
-
result = anv_device_alloc_bo(device, pAllocateInfo->allocationSize,
alloc_flags, client_address, &mem->bo);
if (result != VK_SUCCESS)
gem_flags |= I915_MMAP_WC;
/* GEM will fail to map if the offset isn't 4k-aligned. Round down. */
- uint64_t map_offset = offset & ~4095ull;
+ uint64_t map_offset;
+ if (!device->physical->has_mmap_offset)
+ map_offset = offset & ~4095ull;
+ else
+ map_offset = 0;
assert(offset >= map_offset);
uint64_t map_size = (offset + size) - map_offset;
VkDevice _device,
VkDeviceMemory _memory)
{
+ ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_device_memory, mem, _memory);
if (mem == NULL || mem->host_ptr)
return;
- anv_gem_munmap(mem->map, mem->map_size);
+ anv_gem_munmap(device, mem->map, mem->map_size);
mem->map = NULL;
mem->map_size = 0;
}
framebuffer->attachment_count = pCreateInfo->attachmentCount;
} else {
- assert(device->enabled_extensions.KHR_imageless_framebuffer);
framebuffer = vk_alloc2(&device->alloc, pAllocator, size, 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (framebuffer == NULL)