diff options
-rw-r--r-- | src/intel/vulkan/anv_allocator.c | 26 | ||||
-rw-r--r-- | src/intel/vulkan/anv_device.c | 5 | ||||
-rw-r--r-- | src/intel/vulkan/anv_gem.c | 18 | ||||
-rw-r--r-- | src/intel/vulkan/anv_intel.c | 3 | ||||
-rw-r--r-- | src/intel/vulkan/anv_private.h | 2 |
5 files changed, 54 insertions, 0 deletions
diff --git a/src/intel/vulkan/anv_allocator.c b/src/intel/vulkan/anv_allocator.c index 45c663b6707..78327df3439 100644 --- a/src/intel/vulkan/anv_allocator.c +++ b/src/intel/vulkan/anv_allocator.c @@ -475,6 +475,32 @@ anv_block_pool_grow(struct anv_block_pool *pool, struct anv_block_state *state) * values back into pool. */ pool->map = map + center_bo_offset; pool->center_bo_offset = center_bo_offset; + + /* For block pool BOs we have to be a bit careful about where we place them + * in the GTT. There are two documented workarounds for state base address + * placement : Wa32bitGeneralStateOffset and Wa32bitInstructionBaseOffset + * which state that those two base addresses do not support 48-bit + * addresses and need to be placed in the bottom 32-bit range. + * Unfortunately, this is not quite accurate. + * + * The real problem is that we always set the size of our state pools in + * STATE_BASE_ADDRESS to 0xfffff (the maximum) even though the BO is most + * likely significantly smaller. We do this because we do not no at the + * time we emit STATE_BASE_ADDRESS whether or not we will need to expand + * the pool during command buffer building so we don't actually have a + * valid final size. If the address + size, as seen by STATE_BASE_ADDRESS + * overflows 48 bits, the GPU appears to treat all accesses to the buffer + * as being out of bounds and returns zero. For dynamic state, this + * usually just leads to rendering corruptions, but shaders that are all + * zero hang the GPU immediately. + * + * The easiest solution to do is exactly what the bogus workarounds say to + * do: restrict these buffers to 32-bit addresses. We could also pin the + * BO to some particular location of our choosing, but that's significantly + * more work than just not setting a flag. So, we explicitly DO NOT set + * the EXEC_OBJECT_SUPPORTS_48B_ADDRESS flag and the kernel does all of the + * hard work for us. + */ anv_bo_init(&pool->bo, gem_handle, size); pool->bo.map = map; diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 9e860d51896..22dd5d6bf3d 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -149,6 +149,8 @@ anv_physical_device_init(struct anv_physical_device *device, goto fail; } + device->supports_48bit_addresses = anv_gem_supports_48b_addresses(fd); + if (!anv_device_get_cache_uuid(device->uuid)) { result = vk_errorf(VK_ERROR_INITIALIZATION_FAILED, "cannot generate UUID"); @@ -1452,6 +1454,9 @@ anv_bo_init_new(struct anv_bo *bo, struct anv_device *device, uint64_t size) anv_bo_init(bo, gem_handle, size); + if (device->instance->physicalDevice.supports_48bit_addresses) + bo->flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; + return VK_SUCCESS; } diff --git a/src/intel/vulkan/anv_gem.c b/src/intel/vulkan/anv_gem.c index 7612f493aa0..6a996ea3db8 100644 --- a/src/intel/vulkan/anv_gem.c +++ b/src/intel/vulkan/anv_gem.c @@ -301,6 +301,24 @@ anv_gem_get_aperture(int fd, uint64_t *size) return 0; } +bool +anv_gem_supports_48b_addresses(int fd) +{ + struct drm_i915_gem_exec_object2 obj = { + .flags = EXEC_OBJECT_SUPPORTS_48B_ADDRESS, + }; + + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = (uintptr_t)&obj, + .buffer_count = 1, + .rsvd1 = 0xffffffu, + }; + + int ret = anv_ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + + return ret == -1 && errno == ENOENT; +} + int anv_gem_gpu_get_reset_stats(struct anv_device *device, uint32_t *active, uint32_t *pending) diff --git a/src/intel/vulkan/anv_intel.c b/src/intel/vulkan/anv_intel.c index c356e848fe0..eda474e62ec 100644 --- a/src/intel/vulkan/anv_intel.c +++ b/src/intel/vulkan/anv_intel.c @@ -59,6 +59,9 @@ VkResult anv_CreateDmaBufImageINTEL( anv_bo_init(&mem->bo, gem_handle, size); + if (device->instance->physicalDevice.supports_48bit_addresses) + mem->bo.flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS; + anv_image_create(_device, &(struct anv_image_create_info) { .isl_tiling_flags = ISL_TILING_X_BIT, diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index ee0f79b6ddd..03381999152 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -517,6 +517,7 @@ struct anv_physical_device { const char * name; struct gen_device_info info; uint64_t aperture_size; + bool supports_48bit_addresses; struct brw_compiler * compiler; struct isl_device isl_dev; int cmd_parser_version; @@ -654,6 +655,7 @@ int anv_gem_destroy_context(struct anv_device *device, int context); int anv_gem_get_param(int fd, uint32_t param); bool anv_gem_get_bit6_swizzle(int fd, uint32_t tiling); int anv_gem_get_aperture(int fd, uint64_t *size); +bool anv_gem_supports_48b_addresses(int fd); int anv_gem_gpu_get_reset_stats(struct anv_device *device, uint32_t *active, uint32_t *pending); int anv_gem_handle_to_fd(struct anv_device *device, uint32_t gem_handle); |