mirror of https://gitlab.freedesktop.org/mesa/mesa
641 lines
22 KiB
C
641 lines
22 KiB
C
/*
|
|
* Copyright 2019 Google LLC
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* based in part on anv and radv which are:
|
|
* Copyright © 2015 Intel Corporation
|
|
* Copyright © 2016 Red Hat.
|
|
* Copyright © 2016 Bas Nieuwenhuizen
|
|
*/
|
|
|
|
#include "vn_device_memory.h"
|
|
|
|
#include "venus-protocol/vn_protocol_driver_device_memory.h"
|
|
#include "venus-protocol/vn_protocol_driver_transport.h"
|
|
|
|
#include "vn_android.h"
|
|
#include "vn_buffer.h"
|
|
#include "vn_device.h"
|
|
#include "vn_image.h"
|
|
#include "vn_physical_device.h"
|
|
#include "vn_renderer.h"
|
|
#include "vn_renderer_util.h"
|
|
|
|
/* device memory commands */
|
|
|
|
static inline VkResult
|
|
vn_device_memory_alloc_simple(struct vn_device *dev,
|
|
struct vn_device_memory *mem,
|
|
const VkMemoryAllocateInfo *alloc_info)
|
|
{
|
|
VkDevice dev_handle = vn_device_to_handle(dev);
|
|
VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
|
|
if (VN_PERF(NO_ASYNC_MEM_ALLOC)) {
|
|
return vn_call_vkAllocateMemory(dev->primary_ring, dev_handle,
|
|
alloc_info, NULL, &mem_handle);
|
|
}
|
|
|
|
struct vn_ring_submit_command ring_submit;
|
|
vn_submit_vkAllocateMemory(dev->primary_ring, 0, dev_handle, alloc_info,
|
|
NULL, &mem_handle, &ring_submit);
|
|
if (!ring_submit.ring_seqno_valid)
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
|
|
mem->bo_ring_seqno_valid = true;
|
|
mem->bo_ring_seqno = ring_submit.ring_seqno;
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
static inline void
|
|
vn_device_memory_free_simple(struct vn_device *dev,
|
|
struct vn_device_memory *mem)
|
|
{
|
|
VkDevice dev_handle = vn_device_to_handle(dev);
|
|
VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
|
|
vn_async_vkFreeMemory(dev->primary_ring, dev_handle, mem_handle, NULL);
|
|
}
|
|
|
|
static VkResult
|
|
vn_device_memory_wait_alloc(struct vn_device *dev,
|
|
struct vn_device_memory *mem)
|
|
{
|
|
if (!mem->bo_ring_seqno_valid)
|
|
return VK_SUCCESS;
|
|
|
|
/* no need to wait for ring if
|
|
* - mem alloc is done upon bo map or export
|
|
* - mem import is done upon bo destroy
|
|
*/
|
|
if (vn_ring_get_seqno_status(dev->primary_ring, mem->bo_ring_seqno))
|
|
return VK_SUCCESS;
|
|
|
|
/* fine to false it here since renderer submission failure is fatal */
|
|
mem->bo_ring_seqno_valid = false;
|
|
|
|
const uint64_t ring_id = vn_ring_get_id(dev->primary_ring);
|
|
uint32_t local_data[8];
|
|
struct vn_cs_encoder local_enc =
|
|
VN_CS_ENCODER_INITIALIZER_LOCAL(local_data, sizeof(local_data));
|
|
vn_encode_vkWaitRingSeqnoMESA(&local_enc, 0, ring_id, mem->bo_ring_seqno);
|
|
return vn_renderer_submit_simple(dev->renderer, local_data,
|
|
vn_cs_encoder_get_len(&local_enc));
|
|
}
|
|
|
|
static inline VkResult
|
|
vn_device_memory_bo_init(struct vn_device *dev, struct vn_device_memory *mem)
|
|
{
|
|
VkResult result = vn_device_memory_wait_alloc(dev, mem);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
const struct vk_device_memory *mem_vk = &mem->base.base;
|
|
const VkMemoryType *mem_type = &dev->physical_device->memory_properties
|
|
.memoryTypes[mem_vk->memory_type_index];
|
|
return vn_renderer_bo_create_from_device_memory(
|
|
dev->renderer, mem_vk->size, mem->base.id, mem_type->propertyFlags,
|
|
mem_vk->export_handle_types, &mem->base_bo);
|
|
}
|
|
|
|
static inline void
|
|
vn_device_memory_bo_fini(struct vn_device *dev, struct vn_device_memory *mem)
|
|
{
|
|
if (mem->base_bo) {
|
|
vn_device_memory_wait_alloc(dev, mem);
|
|
vn_renderer_bo_unref(dev->renderer, mem->base_bo);
|
|
}
|
|
}
|
|
|
|
VkResult
|
|
vn_device_memory_import_dma_buf(struct vn_device *dev,
|
|
struct vn_device_memory *mem,
|
|
const VkMemoryAllocateInfo *alloc_info,
|
|
bool force_unmappable,
|
|
int fd)
|
|
{
|
|
const VkMemoryType *mem_type =
|
|
&dev->physical_device->memory_properties
|
|
.memoryTypes[alloc_info->memoryTypeIndex];
|
|
|
|
struct vn_renderer_bo *bo;
|
|
VkResult result = vn_renderer_bo_create_from_dma_buf(
|
|
dev->renderer, alloc_info->allocationSize, fd,
|
|
force_unmappable ? 0 : mem_type->propertyFlags, &bo);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
vn_ring_roundtrip(dev->primary_ring);
|
|
|
|
const VkImportMemoryResourceInfoMESA import_memory_resource_info = {
|
|
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_RESOURCE_INFO_MESA,
|
|
.pNext = alloc_info->pNext,
|
|
.resourceId = bo->res_id,
|
|
};
|
|
const VkMemoryAllocateInfo memory_allocate_info = {
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
.pNext = &import_memory_resource_info,
|
|
.allocationSize = alloc_info->allocationSize,
|
|
.memoryTypeIndex = alloc_info->memoryTypeIndex,
|
|
};
|
|
result = vn_device_memory_alloc_simple(dev, mem, &memory_allocate_info);
|
|
if (result != VK_SUCCESS) {
|
|
vn_renderer_bo_unref(dev->renderer, bo);
|
|
return result;
|
|
}
|
|
|
|
/* need to close import fd on success to avoid fd leak */
|
|
close(fd);
|
|
mem->base_bo = bo;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
static VkResult
|
|
vn_device_memory_alloc_guest_vram(struct vn_device *dev,
|
|
struct vn_device_memory *mem,
|
|
const VkMemoryAllocateInfo *alloc_info)
|
|
{
|
|
const struct vk_device_memory *mem_vk = &mem->base.base;
|
|
const VkMemoryType *mem_type = &dev->physical_device->memory_properties
|
|
.memoryTypes[mem_vk->memory_type_index];
|
|
VkMemoryPropertyFlags flags = mem_type->propertyFlags;
|
|
|
|
/* For external allocation handles, it's possible scenario when requested
|
|
* non-mappable memory. To make sure that virtio-gpu driver will send to
|
|
* the host the address of allocated blob using RESOURCE_MAP_BLOB command
|
|
* a flag VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT must be set.
|
|
*/
|
|
if (mem_vk->export_handle_types)
|
|
flags |= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
|
|
|
VkResult result = vn_renderer_bo_create_from_device_memory(
|
|
dev->renderer, mem_vk->size, mem->base.id, flags,
|
|
mem_vk->export_handle_types, &mem->base_bo);
|
|
if (result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
|
|
const VkImportMemoryResourceInfoMESA import_memory_resource_info = {
|
|
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_RESOURCE_INFO_MESA,
|
|
.pNext = alloc_info->pNext,
|
|
.resourceId = mem->base_bo->res_id,
|
|
};
|
|
|
|
const VkMemoryAllocateInfo memory_allocate_info = {
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
|
.pNext = &import_memory_resource_info,
|
|
.allocationSize = alloc_info->allocationSize,
|
|
.memoryTypeIndex = alloc_info->memoryTypeIndex,
|
|
};
|
|
|
|
vn_ring_roundtrip(dev->primary_ring);
|
|
|
|
result = vn_device_memory_alloc_simple(dev, mem, &memory_allocate_info);
|
|
if (result != VK_SUCCESS) {
|
|
vn_renderer_bo_unref(dev->renderer, mem->base_bo);
|
|
return result;
|
|
}
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
static VkResult
|
|
vn_device_memory_alloc_export(struct vn_device *dev,
|
|
struct vn_device_memory *mem,
|
|
const VkMemoryAllocateInfo *alloc_info)
|
|
{
|
|
VkResult result = vn_device_memory_alloc_simple(dev, mem, alloc_info);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
result = vn_device_memory_bo_init(dev, mem);
|
|
if (result != VK_SUCCESS) {
|
|
vn_device_memory_free_simple(dev, mem);
|
|
return result;
|
|
}
|
|
|
|
result =
|
|
vn_ring_submit_roundtrip(dev->primary_ring, &mem->bo_roundtrip_seqno);
|
|
if (result != VK_SUCCESS) {
|
|
vn_renderer_bo_unref(dev->renderer, mem->base_bo);
|
|
vn_device_memory_free_simple(dev, mem);
|
|
return result;
|
|
}
|
|
|
|
mem->bo_roundtrip_seqno_valid = true;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
struct vn_device_memory_alloc_info {
|
|
VkMemoryAllocateInfo alloc;
|
|
VkExportMemoryAllocateInfo export;
|
|
VkMemoryAllocateFlagsInfo flags;
|
|
VkMemoryDedicatedAllocateInfo dedicated;
|
|
VkMemoryOpaqueCaptureAddressAllocateInfo capture;
|
|
};
|
|
|
|
static const VkMemoryAllocateInfo *
|
|
vn_device_memory_fix_alloc_info(
|
|
const VkMemoryAllocateInfo *alloc_info,
|
|
const VkExternalMemoryHandleTypeFlagBits renderer_handle_type,
|
|
bool has_guest_vram,
|
|
struct vn_device_memory_alloc_info *local_info)
|
|
{
|
|
local_info->alloc = *alloc_info;
|
|
VkBaseOutStructure *cur = (void *)&local_info->alloc;
|
|
|
|
vk_foreach_struct_const(src, alloc_info->pNext) {
|
|
void *next = NULL;
|
|
switch (src->sType) {
|
|
case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
|
|
/* guest vram turns export alloc into import, so drop export info */
|
|
if (has_guest_vram)
|
|
break;
|
|
memcpy(&local_info->export, src, sizeof(local_info->export));
|
|
local_info->export.handleTypes = renderer_handle_type;
|
|
next = &local_info->export;
|
|
break;
|
|
case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO:
|
|
memcpy(&local_info->flags, src, sizeof(local_info->flags));
|
|
next = &local_info->flags;
|
|
break;
|
|
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
|
|
memcpy(&local_info->dedicated, src, sizeof(local_info->dedicated));
|
|
next = &local_info->dedicated;
|
|
break;
|
|
case VK_STRUCTURE_TYPE_MEMORY_OPAQUE_CAPTURE_ADDRESS_ALLOCATE_INFO:
|
|
memcpy(&local_info->capture, src, sizeof(local_info->capture));
|
|
next = &local_info->capture;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (next) {
|
|
cur->pNext = next;
|
|
cur = next;
|
|
}
|
|
}
|
|
|
|
cur->pNext = NULL;
|
|
|
|
return &local_info->alloc;
|
|
}
|
|
|
|
static VkResult
|
|
vn_device_memory_alloc(struct vn_device *dev,
|
|
struct vn_device_memory *mem,
|
|
const VkMemoryAllocateInfo *alloc_info)
|
|
{
|
|
struct vk_device_memory *mem_vk = &mem->base.base;
|
|
const VkMemoryType *mem_type = &dev->physical_device->memory_properties
|
|
.memoryTypes[mem_vk->memory_type_index];
|
|
|
|
const bool has_guest_vram = dev->renderer->info.has_guest_vram;
|
|
const bool host_visible =
|
|
mem_type->propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
|
|
const bool export_alloc = mem_vk->export_handle_types;
|
|
|
|
const VkExternalMemoryHandleTypeFlagBits renderer_handle_type =
|
|
dev->physical_device->external_memory.renderer_handle_type;
|
|
struct vn_device_memory_alloc_info local_info;
|
|
if (mem_vk->export_handle_types &&
|
|
mem_vk->export_handle_types != renderer_handle_type) {
|
|
alloc_info = vn_device_memory_fix_alloc_info(
|
|
alloc_info, renderer_handle_type, has_guest_vram, &local_info);
|
|
|
|
/* ensure correct blob flags */
|
|
mem_vk->export_handle_types = renderer_handle_type;
|
|
}
|
|
|
|
if (has_guest_vram && (host_visible || export_alloc)) {
|
|
return vn_device_memory_alloc_guest_vram(dev, mem, alloc_info);
|
|
} else if (export_alloc) {
|
|
return vn_device_memory_alloc_export(dev, mem, alloc_info);
|
|
} else {
|
|
return vn_device_memory_alloc_simple(dev, mem, alloc_info);
|
|
}
|
|
}
|
|
|
|
static void
|
|
vn_device_memory_emit_report(struct vn_device *dev,
|
|
struct vn_device_memory *mem,
|
|
bool is_alloc,
|
|
VkResult result)
|
|
{
|
|
if (likely(!dev->memory_reports))
|
|
return;
|
|
|
|
const struct vk_device_memory *mem_vk = &mem->base.base;
|
|
VkDeviceMemoryReportEventTypeEXT type;
|
|
if (result != VK_SUCCESS) {
|
|
type = VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATION_FAILED_EXT;
|
|
} else if (is_alloc) {
|
|
type = mem_vk->import_handle_type
|
|
? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_IMPORT_EXT
|
|
: VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_ALLOCATE_EXT;
|
|
} else {
|
|
type = mem_vk->import_handle_type
|
|
? VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_UNIMPORT_EXT
|
|
: VK_DEVICE_MEMORY_REPORT_EVENT_TYPE_FREE_EXT;
|
|
}
|
|
const uint64_t mem_obj_id =
|
|
(mem_vk->import_handle_type | mem_vk->export_handle_types)
|
|
? mem->base_bo->res_id
|
|
: mem->base.id;
|
|
const VkMemoryType *mem_type = &dev->physical_device->memory_properties
|
|
.memoryTypes[mem_vk->memory_type_index];
|
|
vn_device_emit_device_memory_report(dev, type, mem_obj_id, mem_vk->size,
|
|
VK_OBJECT_TYPE_DEVICE_MEMORY,
|
|
(uintptr_t)mem, mem_type->heapIndex);
|
|
}
|
|
|
|
VkResult
|
|
vn_AllocateMemory(VkDevice device,
|
|
const VkMemoryAllocateInfo *pAllocateInfo,
|
|
const VkAllocationCallbacks *pAllocator,
|
|
VkDeviceMemory *pMemory)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
/* see vn_physical_device_init_memory_properties */
|
|
VkMemoryAllocateInfo local_info;
|
|
if (pAllocateInfo->memoryTypeIndex ==
|
|
dev->physical_device->incoherent_cached) {
|
|
local_info = *pAllocateInfo;
|
|
local_info.memoryTypeIndex = dev->physical_device->coherent_uncached;
|
|
pAllocateInfo = &local_info;
|
|
}
|
|
|
|
const VkImportMemoryFdInfoKHR *import_fd_info = NULL;
|
|
const VkMemoryDedicatedAllocateInfo *dedicated_info = NULL;
|
|
vk_foreach_struct_const(pnext, pAllocateInfo->pNext) {
|
|
switch (pnext->sType) {
|
|
case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR:
|
|
import_fd_info = (const void *)pnext;
|
|
break;
|
|
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
|
|
dedicated_info = (const void *)pnext;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
struct vn_device_memory *mem = vk_device_memory_create(
|
|
&dev->base.base, pAllocateInfo, pAllocator, sizeof(*mem));
|
|
if (!mem)
|
|
return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
vn_object_set_id(mem, vn_get_next_obj_id(), VK_OBJECT_TYPE_DEVICE_MEMORY);
|
|
|
|
VkResult result;
|
|
if (mem->base.base.ahardware_buffer) {
|
|
result = vn_android_device_import_ahb(dev, mem, dedicated_info);
|
|
} else if (import_fd_info) {
|
|
result = vn_device_memory_import_dma_buf(dev, mem, pAllocateInfo, false,
|
|
import_fd_info->fd);
|
|
} else {
|
|
result = vn_device_memory_alloc(dev, mem, pAllocateInfo);
|
|
}
|
|
|
|
vn_device_memory_emit_report(dev, mem, /* is_alloc */ true, result);
|
|
|
|
if (result != VK_SUCCESS) {
|
|
vk_device_memory_destroy(&dev->base.base, pAllocator, &mem->base.base);
|
|
return vn_error(dev->instance, result);
|
|
}
|
|
|
|
*pMemory = vn_device_memory_to_handle(mem);
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
void
|
|
vn_FreeMemory(VkDevice device,
|
|
VkDeviceMemory memory,
|
|
const VkAllocationCallbacks *pAllocator)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
|
|
if (!mem)
|
|
return;
|
|
|
|
vn_device_memory_emit_report(dev, mem, /* is_alloc */ false, VK_SUCCESS);
|
|
|
|
/* ensure renderer side import still sees the resource */
|
|
vn_device_memory_bo_fini(dev, mem);
|
|
|
|
if (mem->bo_roundtrip_seqno_valid)
|
|
vn_ring_wait_roundtrip(dev->primary_ring, mem->bo_roundtrip_seqno);
|
|
|
|
vn_device_memory_free_simple(dev, mem);
|
|
vk_device_memory_destroy(&dev->base.base, pAllocator, &mem->base.base);
|
|
}
|
|
|
|
uint64_t
|
|
vn_GetDeviceMemoryOpaqueCaptureAddress(
|
|
VkDevice device, const VkDeviceMemoryOpaqueCaptureAddressInfo *pInfo)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
return vn_call_vkGetDeviceMemoryOpaqueCaptureAddress(dev->primary_ring,
|
|
device, pInfo);
|
|
}
|
|
|
|
VkResult
|
|
vn_MapMemory(VkDevice device,
|
|
VkDeviceMemory memory,
|
|
VkDeviceSize offset,
|
|
VkDeviceSize size,
|
|
VkMemoryMapFlags flags,
|
|
void **ppData)
|
|
{
|
|
VN_TRACE_FUNC();
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
struct vn_device_memory *mem = vn_device_memory_from_handle(memory);
|
|
const struct vk_device_memory *mem_vk = &mem->base.base;
|
|
const bool need_bo = !mem->base_bo;
|
|
void *ptr = NULL;
|
|
VkResult result;
|
|
|
|
/* We don't want to blindly create a bo for each HOST_VISIBLE memory as
|
|
* that has a cost. By deferring bo creation until now, we can avoid the
|
|
* cost unless a bo is really needed. However, that means
|
|
* vn_renderer_bo_map will block until the renderer creates the resource
|
|
* and injects the pages into the guest.
|
|
*
|
|
* XXX We also assume that a vn_renderer_bo can be created as long as the
|
|
* renderer VkDeviceMemory has a mappable memory type. That is plain
|
|
* wrong. It is impossible to fix though until some new extension is
|
|
* created and supported by the driver, and that the renderer switches to
|
|
* the extension.
|
|
*/
|
|
if (need_bo) {
|
|
result = vn_device_memory_bo_init(dev, mem);
|
|
if (result != VK_SUCCESS)
|
|
return vn_error(dev->instance, result);
|
|
}
|
|
|
|
ptr = vn_renderer_bo_map(dev->renderer, mem->base_bo);
|
|
if (!ptr) {
|
|
/* vn_renderer_bo_map implies a roundtrip on success, but not here. */
|
|
if (need_bo) {
|
|
result = vn_ring_submit_roundtrip(dev->primary_ring,
|
|
&mem->bo_roundtrip_seqno);
|
|
if (result != VK_SUCCESS)
|
|
return vn_error(dev->instance, result);
|
|
|
|
mem->bo_roundtrip_seqno_valid = true;
|
|
}
|
|
|
|
return vn_error(dev->instance, VK_ERROR_MEMORY_MAP_FAILED);
|
|
}
|
|
|
|
mem->map_end = size == VK_WHOLE_SIZE ? mem_vk->size : offset + size;
|
|
|
|
*ppData = ptr + offset;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
void
|
|
vn_UnmapMemory(VkDevice device, VkDeviceMemory memory)
|
|
{
|
|
}
|
|
|
|
VkResult
|
|
vn_FlushMappedMemoryRanges(VkDevice device,
|
|
uint32_t memoryRangeCount,
|
|
const VkMappedMemoryRange *pMemoryRanges)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
for (uint32_t i = 0; i < memoryRangeCount; i++) {
|
|
const VkMappedMemoryRange *range = &pMemoryRanges[i];
|
|
struct vn_device_memory *mem =
|
|
vn_device_memory_from_handle(range->memory);
|
|
|
|
const VkDeviceSize size = range->size == VK_WHOLE_SIZE
|
|
? mem->map_end - range->offset
|
|
: range->size;
|
|
vn_renderer_bo_flush(dev->renderer, mem->base_bo, range->offset, size);
|
|
}
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult
|
|
vn_InvalidateMappedMemoryRanges(VkDevice device,
|
|
uint32_t memoryRangeCount,
|
|
const VkMappedMemoryRange *pMemoryRanges)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
|
|
for (uint32_t i = 0; i < memoryRangeCount; i++) {
|
|
const VkMappedMemoryRange *range = &pMemoryRanges[i];
|
|
struct vn_device_memory *mem =
|
|
vn_device_memory_from_handle(range->memory);
|
|
|
|
const VkDeviceSize size = range->size == VK_WHOLE_SIZE
|
|
? mem->map_end - range->offset
|
|
: range->size;
|
|
vn_renderer_bo_invalidate(dev->renderer, mem->base_bo, range->offset,
|
|
size);
|
|
}
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
void
|
|
vn_GetDeviceMemoryCommitment(VkDevice device,
|
|
VkDeviceMemory memory,
|
|
VkDeviceSize *pCommittedMemoryInBytes)
|
|
{
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
vn_call_vkGetDeviceMemoryCommitment(dev->primary_ring, device, memory,
|
|
pCommittedMemoryInBytes);
|
|
}
|
|
|
|
VkResult
|
|
vn_GetMemoryFdKHR(VkDevice device,
|
|
const VkMemoryGetFdInfoKHR *pGetFdInfo,
|
|
int *pFd)
|
|
{
|
|
VN_TRACE_FUNC();
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
struct vn_device_memory *mem =
|
|
vn_device_memory_from_handle(pGetFdInfo->memory);
|
|
|
|
/* At the moment, we support only the below handle types. */
|
|
assert(pGetFdInfo->handleType &
|
|
(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT |
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT));
|
|
assert(mem->base_bo);
|
|
*pFd = vn_renderer_bo_export_dma_buf(dev->renderer, mem->base_bo);
|
|
if (*pFd < 0)
|
|
return vn_error(dev->instance, VK_ERROR_TOO_MANY_OBJECTS);
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult
|
|
vn_get_memory_dma_buf_properties(struct vn_device *dev,
|
|
int fd,
|
|
uint64_t *out_alloc_size,
|
|
uint32_t *out_mem_type_bits)
|
|
{
|
|
VkDevice device = vn_device_to_handle(dev);
|
|
|
|
struct vn_renderer_bo *bo;
|
|
VkResult result = vn_renderer_bo_create_from_dma_buf(
|
|
dev->renderer, 0 /* size */, fd, 0 /* flags */, &bo);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
vn_ring_roundtrip(dev->primary_ring);
|
|
|
|
VkMemoryResourceAllocationSizePropertiesMESA alloc_size_props = {
|
|
.sType =
|
|
VK_STRUCTURE_TYPE_MEMORY_RESOURCE_ALLOCATION_SIZE_PROPERTIES_MESA,
|
|
};
|
|
VkMemoryResourcePropertiesMESA props = {
|
|
.sType = VK_STRUCTURE_TYPE_MEMORY_RESOURCE_PROPERTIES_MESA,
|
|
.pNext = &alloc_size_props,
|
|
};
|
|
result = vn_call_vkGetMemoryResourcePropertiesMESA(
|
|
dev->primary_ring, device, bo->res_id, &props);
|
|
vn_renderer_bo_unref(dev->renderer, bo);
|
|
if (result != VK_SUCCESS)
|
|
return result;
|
|
|
|
*out_alloc_size = alloc_size_props.allocationSize;
|
|
*out_mem_type_bits = props.memoryTypeBits;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VkResult
|
|
vn_GetMemoryFdPropertiesKHR(VkDevice device,
|
|
VkExternalMemoryHandleTypeFlagBits handleType,
|
|
int fd,
|
|
VkMemoryFdPropertiesKHR *pMemoryFdProperties)
|
|
{
|
|
VN_TRACE_FUNC();
|
|
struct vn_device *dev = vn_device_from_handle(device);
|
|
uint64_t alloc_size = 0;
|
|
uint32_t mem_type_bits = 0;
|
|
VkResult result = VK_SUCCESS;
|
|
|
|
if (handleType != VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT)
|
|
return vn_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
|
|
|
|
result =
|
|
vn_get_memory_dma_buf_properties(dev, fd, &alloc_size, &mem_type_bits);
|
|
if (result != VK_SUCCESS)
|
|
return vn_error(dev->instance, result);
|
|
|
|
pMemoryFdProperties->memoryTypeBits = mem_type_bits;
|
|
|
|
return VK_SUCCESS;
|
|
}
|