summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/intel/vulkan/anv_allocator.c26
-rw-r--r--src/intel/vulkan/anv_device.c5
-rw-r--r--src/intel/vulkan/anv_gem.c18
-rw-r--r--src/intel/vulkan/anv_intel.c3
-rw-r--r--src/intel/vulkan/anv_private.h2
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);