1/* 2 * Copyright © 2022 Imagination Technologies Ltd. 3 * 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: 10 * 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 13 * Software. 14 * 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 21 * SOFTWARE. 22 */ 23 24#include <stdbool.h> 25#include <stdint.h> 26#include <stddef.h> 27#include <vulkan/vulkan.h> 28 29#include "pvr_job_common.h" 30#include "pvr_job_context.h" 31#include "pvr_job_transfer.h" 32#include "pvr_private.h" 33#include "pvr_winsys.h" 34#include "util/list.h" 35#include "util/macros.h" 36#include "vk_sync.h" 37 38/* FIXME: Implement gpu based transfer support. */ 39VkResult pvr_transfer_job_submit(struct pvr_device *device, 40 struct pvr_transfer_ctx *ctx, 41 struct pvr_sub_cmd_transfer *sub_cmd, 42 struct vk_sync **waits, 43 uint32_t wait_count, 44 uint32_t *stage_flags, 45 struct vk_sync *signal_sync) 46{ 47 /* Wait for transfer semaphores here before doing any transfers. */ 48 for (uint32_t i = 0U; i < wait_count; i++) { 49 if (stage_flags[i] & PVR_PIPELINE_STAGE_TRANSFER_BIT) { 50 VkResult result = vk_sync_wait(&device->vk, 51 waits[i], 52 0U, 53 VK_SYNC_WAIT_COMPLETE, 54 UINT64_MAX); 55 if (result != VK_SUCCESS) 56 return result; 57 58 stage_flags[i] &= ~PVR_PIPELINE_STAGE_TRANSFER_BIT; 59 } 60 } 61 62 list_for_each_entry_safe (struct pvr_transfer_cmd, 63 transfer_cmd, 64 &sub_cmd->transfer_cmds, 65 link) { 66 bool src_mapped = false; 67 bool dst_mapped = false; 68 void *src_addr; 69 void *dst_addr; 70 void *ret_ptr; 71 72 /* Map if bo is not mapped. */ 73 if (!transfer_cmd->src->vma->bo->map) { 74 src_mapped = true; 75 ret_ptr = device->ws->ops->buffer_map(transfer_cmd->src->vma->bo); 76 if (!ret_ptr) 77 return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED); 78 } 79 80 if (!transfer_cmd->dst->vma->bo->map) { 81 dst_mapped = true; 82 ret_ptr = device->ws->ops->buffer_map(transfer_cmd->dst->vma->bo); 83 if (!ret_ptr) 84 return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED); 85 } 86 87 src_addr = 88 transfer_cmd->src->vma->bo->map + transfer_cmd->src->vma->bo_offset; 89 dst_addr = 90 transfer_cmd->dst->vma->bo->map + transfer_cmd->dst->vma->bo_offset; 91 92 for (uint32_t i = 0; i < transfer_cmd->region_count; i++) { 93 VkBufferCopy2 *region = &transfer_cmd->regions[i]; 94 95 memcpy(dst_addr + region->dstOffset, 96 src_addr + region->srcOffset, 97 region->size); 98 } 99 100 if (src_mapped) 101 device->ws->ops->buffer_unmap(transfer_cmd->src->vma->bo); 102 103 if (dst_mapped) 104 device->ws->ops->buffer_unmap(transfer_cmd->dst->vma->bo); 105 } 106 107 /* Given we are doing CPU based copy, completion fence should always be 108 * signaled. This should be fixed when GPU based copy is implemented. 109 */ 110 return vk_sync_signal(&device->vk, signal_sync, 0); 111} 112