tu: Implement VK_EXT_device_address_binding_report

This extension should be helpful for debugging.

Passes dEQP-VK.memory.address_binding_report.*

Signed-off-by: Valentine Burley <valentine.burley@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30021>
This commit is contained in:
Valentine Burley 2024-06-23 15:49:36 +00:00 committed by Marge Bot
parent dd10d2ef2f
commit 47de27cde1
17 changed files with 107 additions and 33 deletions

View file

@ -573,7 +573,7 @@ Khronos extensions that are not part of any Vulkan version:
VK_EXT_depth_clip_enable DONE (anv, hasvk, lvp, nvk, radv, tu, v3dv/vc7+, vn)
VK_EXT_depth_range_unrestricted DONE (anv/gen20+, nvk, radv, lvp)
VK_EXT_descriptor_buffer DONE (anv, lvp, radv, tu)
VK_EXT_device_address_binding_report DONE (radv)
VK_EXT_device_address_binding_report DONE (radv, tu)
VK_EXT_device_fault DONE (radv)
VK_EXT_device_memory_report DONE (vn)
VK_EXT_direct_mode_display DONE (anv, lvp, nvk, radv, tu, v3dv)

View file

@ -9,6 +9,8 @@
#include "tu_buffer.h"
#include "vk_debug_utils.h"
#include "tu_device.h"
#include "tu_rmv.h"
@ -44,6 +46,7 @@ tu_DestroyBuffer(VkDevice _device,
{
VK_FROM_HANDLE(tu_device, device, _device);
VK_FROM_HANDLE(tu_buffer, buffer, _buffer);
struct tu_instance *instance = device->physical_device->instance;
if (!buffer)
return;
@ -54,6 +57,12 @@ tu_DestroyBuffer(VkDevice _device,
tu_perfetto_log_destroy_buffer(device, buffer);
#endif
if (buffer->iova)
vk_address_binding_report(&instance->vk, &buffer->vk.base,
buffer->iova, buffer->bo_size,
VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT);
vk_buffer_destroy(&device->vk, pAllocator, &buffer->vk);
}
@ -126,6 +135,7 @@ tu_BindBufferMemory2(VkDevice device,
const VkBindBufferMemoryInfo *pBindInfos)
{
VK_FROM_HANDLE(tu_device, dev, device);
struct tu_instance *instance = dev->physical_device->instance;
for (uint32_t i = 0; i < bindInfoCount; ++i) {
VK_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
@ -146,11 +156,16 @@ tu_BindBufferMemory2(VkDevice device,
#ifdef HAVE_PERFETTO
tu_perfetto_log_bind_buffer(dev, buffer);
#endif
buffer->bo_size = mem->bo->size;
} else {
buffer->bo = NULL;
}
TU_RMV(buffer_bind, dev, buffer);
vk_address_binding_report(&instance->vk, &buffer->vk.base,
buffer->bo->iova, buffer->bo->size,
VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
}
return VK_SUCCESS;
}

View file

@ -20,6 +20,7 @@ struct tu_buffer
struct tu_bo *bo;
uint64_t iova;
uint64_t bo_size;
};
VK_DEFINE_NONDISP_HANDLE_CASTS(tu_buffer, vk.base, VkBuffer,

View file

@ -156,7 +156,7 @@ tu_cs_add_bo(struct tu_cs *cs, uint32_t size)
struct tu_bo *new_bo;
VkResult result =
tu_bo_init_new(cs->device, &new_bo, size * sizeof(uint32_t),
tu_bo_init_new(cs->device, NULL, &new_bo, size * sizeof(uint32_t),
(enum tu_bo_alloc_flags)(COND(!cs->writeable,
TU_BO_ALLOC_GPU_READ_ONLY) |
TU_BO_ALLOC_ALLOW_DUMP),

View file

@ -281,8 +281,8 @@ tu_CreateDescriptorSetLayout(
if (pCreateInfo->flags &
VK_DESCRIPTOR_SET_LAYOUT_CREATE_EMBEDDED_IMMUTABLE_SAMPLERS_BIT_EXT) {
result = tu_bo_init_new(device, &set_layout->embedded_samplers,
set_layout->size,
result = tu_bo_init_new(device, &set_layout->vk.base,
&set_layout->embedded_samplers, set_layout->size,
(enum tu_bo_alloc_flags) (TU_BO_ALLOC_ALLOW_DUMP |
TU_BO_ALLOC_INTERNAL_RESOURCE),
"embedded samplers");
@ -805,7 +805,8 @@ tu_CreateDescriptorPool(VkDevice _device,
if (bo_size) {
if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_HOST_ONLY_BIT_EXT)) {
ret = tu_bo_init_new(device, &pool->bo, bo_size, TU_BO_ALLOC_ALLOW_DUMP, "descriptor pool");
ret = tu_bo_init_new(device, &pool->base, &pool->bo, bo_size,
TU_BO_ALLOC_ALLOW_DUMP, "descriptor pool");
if (ret)
goto fail_alloc;

View file

@ -235,6 +235,7 @@ get_device_extensions(const struct tu_physical_device *device,
.EXT_depth_clip_enable = true,
.EXT_descriptor_buffer = true,
.EXT_descriptor_indexing = true,
.EXT_device_address_binding_report = true,
#ifdef VK_USE_PLATFORM_DISPLAY_KHR
.EXT_display_control = true,
#endif
@ -530,6 +531,9 @@ tu_get_features(struct tu_physical_device *pdevice,
features->descriptorBufferImageLayoutIgnored = true;
features->descriptorBufferPushDescriptors = true;
/* VK_EXT_device_address_binding_report */
features->reportAddressBinding = true;
/* VK_EXT_extended_dynamic_state */
features->extendedDynamicState = true;
@ -1707,7 +1711,7 @@ tu_trace_create_ts_buffer(struct u_trace_context *utctx, uint32_t size)
container_of(utctx, struct tu_device, trace_context);
struct tu_bo *bo;
tu_bo_init_new(device, &bo, size, TU_BO_ALLOC_INTERNAL_RESOURCE, "trace");
tu_bo_init_new(device, NULL, &bo, size, TU_BO_ALLOC_INTERNAL_RESOURCE, "trace");
return bo;
}
@ -2366,7 +2370,7 @@ tu_CreateDevice(VkPhysicalDevice physicalDevice,
}
result = tu_bo_init_new(
device, &device->global_bo, global_size,
device, NULL, &device->global_bo, global_size,
(enum tu_bo_alloc_flags) (TU_BO_ALLOC_ALLOW_DUMP |
TU_BO_ALLOC_INTERNAL_RESOURCE),
"global");
@ -2717,7 +2721,7 @@ tu_get_scratch_bo(struct tu_device *dev, uint64_t size, struct tu_bo **bo)
}
unsigned bo_size = 1ull << size_log2;
VkResult result = tu_bo_init_new(dev, &dev->scratch_bos[index].bo, bo_size,
VkResult result = tu_bo_init_new(dev, NULL, &dev->scratch_bos[index].bo, bo_size,
TU_BO_ALLOC_INTERNAL_RESOURCE, "scratch");
if (result != VK_SUCCESS) {
mtx_unlock(&dev->scratch_bos[index].construct_mtx);
@ -2864,8 +2868,8 @@ tu_AllocateMemory(VkDevice _device,
VkMemoryPropertyFlags mem_property =
device->physical_device->memory.types[pAllocateInfo->memoryTypeIndex];
result = tu_bo_init_new_explicit_iova(
device, &mem->bo, pAllocateInfo->allocationSize, client_address,
mem_property, alloc_flags, name);
device, &mem->vk.base, &mem->bo, pAllocateInfo->allocationSize,
client_address, mem_property, alloc_flags, name);
}
if (result == VK_SUCCESS) {

View file

@ -26,7 +26,7 @@ tu_CreateEvent(VkDevice _device,
if (!event)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
VkResult result = tu_bo_init_new(device, &event->bo, 0x1000,
VkResult result = tu_bo_init_new(device, &event->base, &event->bo, 0x1000,
TU_BO_ALLOC_NO_FLAGS, "event");
if (result != VK_SUCCESS)
goto fail_alloc;

View file

@ -15,6 +15,7 @@
#include "util/format/u_format.h"
#include "vulkan/vulkan_android.h"
#include "vk_android.h"
#include "vk_debug_utils.h"
#include "vk_util.h"
#include "drm-uapi/drm_fourcc.h"
#include "vulkan/vulkan_core.h"
@ -821,6 +822,7 @@ tu_DestroyImage(VkDevice _device,
{
VK_FROM_HANDLE(tu_device, device, _device);
VK_FROM_HANDLE(tu_image, image, _image);
struct tu_instance *instance = device->physical_device->instance;
if (!image)
return;
@ -831,6 +833,11 @@ tu_DestroyImage(VkDevice _device,
tu_perfetto_log_destroy_image(device, image);
#endif
if (image->iova)
vk_address_binding_report(&instance->vk, &image->vk.base,
image->iova, image->total_size,
VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT);
vk_image_destroy(&device->vk, pAllocator, &image->vk);
}
@ -840,6 +847,7 @@ tu_BindImageMemory2(VkDevice _device,
const VkBindImageMemoryInfo *pBindInfos)
{
VK_FROM_HANDLE(tu_device, device, _device);
struct tu_instance *instance = device->physical_device->instance;
for (uint32_t i = 0; i < bindInfoCount; ++i) {
VK_FROM_HANDLE(tu_image, image, pBindInfos[i].image);
@ -861,6 +869,10 @@ tu_BindImageMemory2(VkDevice _device,
TU_RMV(image_bind, device, image);
vk_address_binding_report(&instance->vk, &image->vk.base,
image->iova, image->total_size,
VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
continue;
}
#endif
@ -919,6 +931,10 @@ tu_BindImageMemory2(VkDevice _device,
}
TU_RMV(image_bind, device, image);
vk_address_binding_report(&instance->vk, &image->vk.base,
image->iova, image->total_size,
VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
}
return VK_SUCCESS;

View file

@ -18,6 +18,8 @@
#include <sys/mman.h>
#include "vk_debug_utils.h"
#include "util/libdrm.h"
#include "tu_device.h"
@ -27,13 +29,26 @@
VkResult
tu_bo_init_new_explicit_iova(struct tu_device *dev,
struct vk_object_base *base,
struct tu_bo **out_bo,
uint64_t size,
uint64_t client_iova,
VkMemoryPropertyFlags mem_property,
enum tu_bo_alloc_flags flags, const char *name)
{
return dev->instance->knl->bo_init(dev, out_bo, size, client_iova, mem_property, flags, name);
struct tu_instance *instance = dev->physical_device->instance;
VkResult result =
dev->instance->knl->bo_init(dev, base, out_bo, size, client_iova,
mem_property, flags, name);
if (result != VK_SUCCESS)
return result;
vk_address_binding_report(&instance->vk, base ? base : &dev->vk.base,
(*out_bo)->iova, (*out_bo)->size,
VK_DEVICE_ADDRESS_BINDING_TYPE_BIND_EXT);
return VK_SUCCESS;
}
VkResult
@ -54,6 +69,12 @@ tu_bo_export_dmabuf(struct tu_device *dev, struct tu_bo *bo)
void
tu_bo_finish(struct tu_device *dev, struct tu_bo *bo)
{
struct tu_instance *instance = dev->physical_device->instance;
vk_address_binding_report(&instance->vk, bo->base ? bo->base : &dev->vk.base,
bo->iova, bo->size,
VK_DEVICE_ADDRESS_BINDING_TYPE_UNBIND_EXT);
dev->instance->knl->bo_finish(dev, bo);
}

View file

@ -69,6 +69,11 @@ struct tu_bo {
bool implicit_sync : 1;
bool never_unmap : 1;
/* Pointer to the vk_object_base associated with the BO
* for the purposes of VK_EXT_device_address_binding_report
*/
struct vk_object_base *base;
};
struct tu_knl {
@ -81,8 +86,9 @@ struct tu_knl {
VkResult (*device_check_status)(struct tu_device *dev);
int (*submitqueue_new)(struct tu_device *dev, int priority, uint32_t *queue_id);
void (*submitqueue_close)(struct tu_device *dev, uint32_t queue_id);
VkResult (*bo_init)(struct tu_device *dev, struct tu_bo **out_bo, uint64_t size,
uint64_t client_iova, VkMemoryPropertyFlags mem_property,
VkResult (*bo_init)(struct tu_device *dev, struct vk_object_base *base,
struct tu_bo **out_bo, uint64_t size, uint64_t client_iova,
VkMemoryPropertyFlags mem_property,
enum tu_bo_alloc_flags flags, const char *name);
VkResult (*bo_init_dmabuf)(struct tu_device *dev, struct tu_bo **out_bo,
uint64_t size, int prime_fd);
@ -121,6 +127,7 @@ struct tu_timeline_sync {
VkResult
tu_bo_init_new_explicit_iova(struct tu_device *dev,
struct vk_object_base *base,
struct tu_bo **out_bo,
uint64_t size,
uint64_t client_iova,
@ -129,13 +136,14 @@ tu_bo_init_new_explicit_iova(struct tu_device *dev,
const char *name);
static inline VkResult
tu_bo_init_new(struct tu_device *dev, struct tu_bo **out_bo, uint64_t size,
tu_bo_init_new(struct tu_device *dev, struct vk_object_base *base,
struct tu_bo **out_bo, uint64_t size,
enum tu_bo_alloc_flags flags, const char *name)
{
// TODO don't mark everything with HOST_VISIBLE !!! Anything that
// never gets CPU access should not have this bit set
return tu_bo_init_new_explicit_iova(
dev, out_bo, size, 0,
dev, base, out_bo, size, 0,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,

View file

@ -431,6 +431,7 @@ tu_allocate_kernel_iova(struct tu_device *dev,
static VkResult
tu_bo_init(struct tu_device *dev,
struct vk_object_base *base,
struct tu_bo *bo,
uint32_t gem_handle,
uint64_t size,
@ -494,6 +495,7 @@ tu_bo_init(struct tu_device *dev,
.name = name,
.refcnt = 1,
.bo_list_idx = idx,
.base = base,
};
mtx_unlock(&dev->bo_mutex);
@ -550,6 +552,7 @@ msm_vma_unlock(struct tu_device *dev)
static VkResult
msm_bo_init(struct tu_device *dev,
struct vk_object_base *base,
struct tu_bo **out_bo,
uint64_t size,
uint64_t client_iova,
@ -588,7 +591,7 @@ msm_bo_init(struct tu_device *dev,
msm_vma_lock(dev);
VkResult result =
tu_bo_init(dev, bo, req.handle, size, client_iova, flags, name);
tu_bo_init(dev, base, bo, req.handle, size, client_iova, flags, name);
msm_vma_unlock(dev);
@ -666,7 +669,7 @@ msm_bo_init_dmabuf(struct tu_device *dev,
}
VkResult result =
tu_bo_init(dev, bo, gem_handle, size, 0, TU_BO_ALLOC_DMABUF, "dmabuf");
tu_bo_init(dev, NULL, bo, gem_handle, size, 0, TU_BO_ALLOC_DMABUF, "dmabuf");
if (result != VK_SUCCESS)
memset(bo, 0, sizeof(*bo));

View file

@ -491,6 +491,7 @@ virtio_allocate_userspace_iova_locked(struct tu_device *dev,
static VkResult
tu_bo_init(struct tu_device *dev,
struct vk_object_base *base,
struct tu_bo *bo,
uint32_t gem_handle,
uint64_t size,
@ -540,6 +541,7 @@ tu_bo_init(struct tu_device *dev,
.name = name,
.refcnt = 1,
.bo_list_idx = idx,
.base = base,
};
mtx_unlock(&dev->bo_mutex);
@ -582,12 +584,13 @@ tu_bo_set_kernel_name(struct tu_device *dev, struct tu_bo *bo, const char *name)
static VkResult
virtio_bo_init(struct tu_device *dev,
struct tu_bo **out_bo,
uint64_t size,
uint64_t client_iova,
VkMemoryPropertyFlags mem_property,
enum tu_bo_alloc_flags flags,
const char *name)
struct vk_object_base *base,
struct tu_bo **out_bo,
uint64_t size,
uint64_t client_iova,
VkMemoryPropertyFlags mem_property,
enum tu_bo_alloc_flags flags,
const char *name)
{
struct tu_virtio_device *vdev = dev->vdev;
struct msm_ccmd_gem_new_req req = {
@ -651,7 +654,7 @@ virtio_bo_init(struct tu_device *dev,
bo->res_id = res_id;
result = tu_bo_init(dev, bo, handle, size, req.iova, flags, name);
result = tu_bo_init(dev, base, bo, handle, size, req.iova, flags, name);
if (result != VK_SUCCESS) {
memset(bo, 0, sizeof(*bo));
goto fail;
@ -748,7 +751,7 @@ virtio_bo_init_dmabuf(struct tu_device *dev,
}
result =
tu_bo_init(dev, bo, handle, size, iova, TU_BO_ALLOC_NO_FLAGS, "dmabuf");
tu_bo_init(dev, NULL, bo, handle, size, iova, TU_BO_ALLOC_NO_FLAGS, "dmabuf");
if (result != VK_SUCCESS) {
util_vma_heap_free(&dev->vma, iova, size);
memset(bo, 0, sizeof(*bo));
@ -986,8 +989,8 @@ setup_fence_cmds(struct tu_device *dev)
struct tu_virtio_device *vdev = dev->vdev;
VkResult result;
result = tu_bo_init_new(dev, &vdev->fence_cmds_mem, sizeof(*vdev->fence_cmds),
(enum tu_bo_alloc_flags)
result = tu_bo_init_new(dev, NULL, &vdev->fence_cmds_mem,
sizeof(*vdev->fence_cmds), (enum tu_bo_alloc_flags)
(TU_BO_ALLOC_ALLOW_DUMP | TU_BO_ALLOC_GPU_READ_ONLY),
"fence_cmds");
if (result != VK_SUCCESS)

View file

@ -165,6 +165,7 @@ bo_init_new_ion_legacy(struct tu_device *dev, struct tu_bo **out_bo, uint64_t si
static VkResult
kgsl_bo_init(struct tu_device *dev,
struct vk_object_base *base,
struct tu_bo **out_bo,
uint64_t size,
uint64_t client_iova,
@ -231,6 +232,7 @@ kgsl_bo_init(struct tu_device *dev,
.name = tu_debug_bos_add(dev, req.mmapsize, name),
.refcnt = 1,
.shared_fd = -1,
.base = base,
};
if (flags & TU_BO_ALLOC_REPLAYABLE) {

View file

@ -1084,7 +1084,7 @@ tu_get_tess_iova(struct tu_device *dev,
if (!dev->tess_bo) {
mtx_lock(&dev->mutex);
if (!dev->tess_bo) {
tu_bo_init_new(dev, &dev->tess_bo, TU_TESS_BO_SIZE,
tu_bo_init_new(dev, NULL, &dev->tess_bo, TU_TESS_BO_SIZE,
TU_BO_ALLOC_INTERNAL_RESOURCE, "tess");
}
mtx_unlock(&dev->mutex);

View file

@ -314,7 +314,7 @@ tu_CreateQueryPool(VkDevice _device,
compare_perfcntr_pass);
}
VkResult result = tu_bo_init_new(device, &pool->bo,
VkResult result = tu_bo_init_new(device, &pool->vk.base, &pool->bo,
pCreateInfo->queryCount * slot_size, TU_BO_ALLOC_NO_FLAGS, "query pool");
if (result != VK_SUCCESS) {
vk_query_pool_destroy(&device->vk, pAllocator, &pool->vk);

View file

@ -2050,7 +2050,7 @@ tu_setup_pvtmem(struct tu_device *dev,
uint32_t total_size =
dev->physical_device->info->num_sp_cores * pvtmem_bo->per_sp_size;
VkResult result = tu_bo_init_new(dev, &pvtmem_bo->bo, total_size,
VkResult result = tu_bo_init_new(dev, NULL, &pvtmem_bo->bo, total_size,
TU_BO_ALLOC_INTERNAL_RESOURCE, "pvtmem");
if (result != VK_SUCCESS) {
mtx_unlock(&pvtmem_bo->mtx);

View file

@ -82,8 +82,8 @@ tu_suballoc_bo_alloc(struct tu_suballoc_bo *suballoc_bo,
/* Allocate the new BO if we didn't have one cached. */
if (!suballoc->bo) {
VkResult result = tu_bo_init_new(suballoc->dev, &suballoc->bo,
alloc_size,
VkResult result = tu_bo_init_new(suballoc->dev, NULL,
&suballoc->bo, alloc_size,
suballoc->flags, suballoc->name);
if (result != VK_SUCCESS)
return result;