hk: bind for sparse emulation

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34486>
This commit is contained in:
Alyssa Rosenzweig 2025-04-11 11:58:28 -04:00 committed by Marge Bot
parent fb71b8a4ee
commit f3272ebab8
3 changed files with 47 additions and 3 deletions

View file

@ -81,9 +81,22 @@ VkResult
hk_bind_scratch(struct hk_device *dev, struct agx_va *va, unsigned offset_B,
size_t size_B)
{
return agx_bo_bind(
&dev->dev, dev->sparse.write, va->addr + offset_B, size_B, 0,
DRM_ASAHI_BIND_READ | DRM_ASAHI_BIND_WRITE | DRM_ASAHI_BIND_SINGLE_PAGE);
uint64_t addr = va->addr + offset_B;
uint32_t flags = DRM_ASAHI_BIND_READ | DRM_ASAHI_BIND_SINGLE_PAGE;
/* Map read-write scratch to the primary (bottom half) VA range */
int ret = agx_bo_bind(&dev->dev, dev->sparse.write, addr, size_B, 0,
flags | DRM_ASAHI_BIND_WRITE);
if (ret)
return VK_ERROR_UNKNOWN;
/* Map read-only scratch to the secondary (top half) VA range */
ret = agx_bo_bind(&dev->dev, dev->dev.zero_bo,
addr + dev->dev.sparse_ro_offset, size_B, 0, flags);
if (ret)
return VK_ERROR_UNKNOWN;
return VK_SUCCESS;
}
VKAPI_ATTR VkResult VKAPI_CALL
@ -132,6 +145,9 @@ hk_CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo,
"Sparse VMA allocation failed");
}
buffer->vk.device_address = buffer->va->addr;
/* Bind scratch pages to make read/write across the VA valid */
hk_bind_scratch(dev, buffer->va, 0, vma_size_B);
}
*pBuffer = hk_buffer_to_handle(buffer);
@ -245,11 +261,21 @@ hk_BindBufferMemory2(VkDevice device, uint32_t bindInfoCount,
if (buffer->va) {
VK_FROM_HANDLE(hk_device, dev, device);
size_t size = MIN2(mem->bo->size, buffer->va->size_B);
/* Lower mapping: read-write */
int ret = agx_bo_bind(&dev->dev, mem->bo, buffer->vk.device_address,
size, pBindInfos[i].memoryOffset,
DRM_ASAHI_BIND_READ | DRM_ASAHI_BIND_WRITE);
if (ret)
return VK_ERROR_UNKNOWN;
/* Upper mapping: read-only */
ret =
agx_bo_bind(&dev->dev, mem->bo,
buffer->vk.device_address + dev->dev.sparse_ro_offset,
size, pBindInfos[i].memoryOffset, DRM_ASAHI_BIND_READ);
if (ret)
return VK_ERROR_UNKNOWN;
} else {
assert(buffer->vk.device_address == 0);
buffer->vk.device_address =

View file

@ -219,6 +219,13 @@ hk_AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
}
}
/* Shadow map in case this is used for a sparse resident buffer */
int ret = agx_bo_bind(&dev->dev, mem->bo,
agx_rw_addr_to_ro(&dev->dev, mem->bo->va->addr),
mem->bo->size, 0, DRM_ASAHI_BIND_READ);
if (ret)
return VK_ERROR_UNKNOWN;
if (mem->bo->flags & (AGX_BO_SHAREABLE | AGX_BO_SHARED))
hk_add_ext_bo(dev, mem->bo);

View file

@ -480,6 +480,17 @@ hk_flush_bind(struct hk_bind_builder *b)
}
util_dynarray_append(&b->binds, struct drm_asahi_gem_bind_op, op);
/* Shadow a read-only mapping to the upper half */
op.flags &= ~DRM_ASAHI_BIND_WRITE;
op.addr = agx_rw_addr_to_ro(&b->dev->dev, op.addr);
if (!b->mem) {
op.handle = b->dev->dev.zero_bo->uapi_handle;
}
util_dynarray_append(&b->binds, struct drm_asahi_gem_bind_op, op);
return VK_SUCCESS;
}