* 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;
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");
anv_bo_init(bo, gem_handle, size);
+ if (device->instance->physicalDevice.supports_48bit_addresses)
+ bo->flags |= EXEC_OBJECT_SUPPORTS_48B_ADDRESS;
+
return VK_SUCCESS;
}
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)
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,
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;
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);