2
* Copyright © 2022 Imagination Technologies Ltd.
4
* Permission is hereby granted, free of charge, to any person obtaining a copy
5
* of this software and associated documentation files (the "Software"), to deal
6
* in the Software without restriction, including without limitation the rights
7
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
* copies of the Software, and to permit persons to whom the Software is
9
* furnished to do so, subject to the following conditions:
11
* The above copyright notice and this permission notice (including the next
12
* paragraph) shall be included in all copies or substantial portions of the
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
#include <vulkan/vulkan.h>
30
#include "pvr_private.h"
31
#include "pvr_winsys.h"
35
static uint32_t pvr_bo_alloc_to_winsys_flags(uint64_t flags)
37
uint32_t ws_flags = 0;
39
if (flags & PVR_BO_ALLOC_FLAG_CPU_ACCESS)
40
ws_flags |= PVR_WINSYS_BO_FLAG_CPU_ACCESS;
42
if (flags & PVR_BO_ALLOC_FLAG_GPU_UNCACHED)
43
ws_flags |= PVR_WINSYS_BO_FLAG_GPU_UNCACHED;
45
if (flags & PVR_BO_ALLOC_FLAG_PM_FW_PROTECT)
46
ws_flags |= PVR_WINSYS_BO_FLAG_PM_FW_PROTECT;
48
if (flags & PVR_BO_ALLOC_FLAG_ZERO_ON_ALLOC)
49
ws_flags |= PVR_WINSYS_BO_FLAG_ZERO_ON_ALLOC;
55
* \brief Helper interface to allocate a GPU buffer and map it to both host and
56
* device virtual memory. Host mapping is conditional and is controlled by
59
* \param[in] device Logical device pointer.
60
* \param[in] heap Heap to allocate device virtual address from.
61
* \param[in] size Size of buffer to allocate.
62
* \param[in] alignment Required alignment of the allocation. Must be a power
64
* \param[in] flags Controls allocation, CPU and GPU mapping behavior
65
* using PVR_BO_ALLOC_FLAG_*.
66
* \param[out] pvr_bo_out On success output buffer is returned in this pointer.
67
* \return VK_SUCCESS on success, or error code otherwise.
71
VkResult pvr_bo_alloc(struct pvr_device *device,
72
struct pvr_winsys_heap *heap,
76
struct pvr_bo **const pvr_bo_out)
78
const uint32_t ws_flags = pvr_bo_alloc_to_winsys_flags(flags);
79
struct pvr_bo *pvr_bo;
83
pvr_bo = vk_alloc(&device->vk.alloc,
86
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
88
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
90
result = device->ws->ops->buffer_create(device->ws,
93
PVR_WINSYS_BO_TYPE_GPU,
96
if (result != VK_SUCCESS)
99
if (flags & PVR_BO_ALLOC_FLAG_CPU_MAPPED) {
100
void *map = device->ws->ops->buffer_map(pvr_bo->bo);
102
result = VK_ERROR_MEMORY_MAP_FAILED;
103
goto err_buffer_destroy;
107
pvr_bo->vma = device->ws->ops->heap_alloc(heap, size, alignment);
109
result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
110
goto err_buffer_unmap;
113
addr = device->ws->ops->vma_map(pvr_bo->vma, pvr_bo->bo, 0, size);
115
result = VK_ERROR_MEMORY_MAP_FAILED;
119
*pvr_bo_out = pvr_bo;
124
device->ws->ops->heap_free(pvr_bo->vma);
127
if (flags & PVR_BO_ALLOC_FLAG_CPU_MAPPED)
128
device->ws->ops->buffer_unmap(pvr_bo->bo);
131
device->ws->ops->buffer_destroy(pvr_bo->bo);
134
vk_free(&device->vk.alloc, pvr_bo);
140
* \brief Interface to map the buffer into host virtual address space.
142
* Buffer should have been created with the #PVR_BO_ALLOC_FLAG_CPU_ACCESS
143
* flag. It should also not already be mapped or it should have been unmapped
144
* using #pvr_bo_cpu_unmap() before mapping again.
146
* \param[in] device Logical device pointer.
147
* \param[in] pvr_bo Buffer to map.
148
* \return Valid host virtual address on success, or NULL otherwise.
150
* \sa #pvr_bo_alloc(), #PVR_BO_ALLOC_FLAG_CPU_MAPPED
152
void *pvr_bo_cpu_map(struct pvr_device *device, struct pvr_bo *pvr_bo)
154
assert(!pvr_bo->bo->map);
156
return device->ws->ops->buffer_map(pvr_bo->bo);
160
* \brief Interface to unmap the buffer from host virtual address space.
162
* Buffer should have a valid mapping, created either using #pvr_bo_cpu_map() or
163
* by passing #PVR_BO_ALLOC_FLAG_CPU_MAPPED flag to #pvr_bo_alloc() at
166
* Buffer can be remapped using #pvr_bo_cpu_map().
168
* \param[in] device Logical device pointer.
169
* \param[in] pvr_bo Buffer to unmap.
171
void pvr_bo_cpu_unmap(struct pvr_device *device, struct pvr_bo *pvr_bo)
173
assert(pvr_bo->bo->map);
174
device->ws->ops->buffer_unmap(pvr_bo->bo);
178
* \brief Interface to free the buffer object.
180
* \param[in] device Logical device pointer.
181
* \param[in] pvr_bo Buffer to free.
183
* \sa #pvr_bo_alloc()
185
void pvr_bo_free(struct pvr_device *device, struct pvr_bo *pvr_bo)
190
device->ws->ops->vma_unmap(pvr_bo->vma);
191
device->ws->ops->heap_free(pvr_bo->vma);
194
device->ws->ops->buffer_unmap(pvr_bo->bo);
196
device->ws->ops->buffer_destroy(pvr_bo->bo);
198
vk_free(&device->vk.alloc, pvr_bo);