1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * based in part on anv driver which is: 5bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * based in part on v3dv_cl.h which is: 8bf215546Sopenharmony_ci * Copyright © 2019 Raspberry Pi 9bf215546Sopenharmony_ci * 10bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 11bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 12bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights 13bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 15bf215546Sopenharmony_ci * furnished to do so, subject to the following conditions: 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 18bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 19bf215546Sopenharmony_ci * Software. 20bf215546Sopenharmony_ci * 21bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24bf215546Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27bf215546Sopenharmony_ci * SOFTWARE. 28bf215546Sopenharmony_ci */ 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#ifndef PVR_CSB_H 31bf215546Sopenharmony_ci#define PVR_CSB_H 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include <assert.h> 34bf215546Sopenharmony_ci#include <stdbool.h> 35bf215546Sopenharmony_ci#include <stdint.h> 36bf215546Sopenharmony_ci#include <vulkan/vulkan.h> 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#include "pvr_bo.h" 39bf215546Sopenharmony_ci#include "pvr_types.h" 40bf215546Sopenharmony_ci#include "pvr_winsys.h" 41bf215546Sopenharmony_ci#include "util/list.h" 42bf215546Sopenharmony_ci#include "util/macros.h" 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci#define __pvr_address_type pvr_dev_addr_t 45bf215546Sopenharmony_ci#define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr 46bf215546Sopenharmony_ci/* clang-format off */ 47bf215546Sopenharmony_ci#define __pvr_make_address(addr_u64) PVR_DEV_ADDR(addr_u64) 48bf215546Sopenharmony_ci/* clang-format on */ 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci#include "csbgen/rogue_hwdefs.h" 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_cistruct pvr_device; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_cienum pvr_cmd_stream_type { 55bf215546Sopenharmony_ci PVR_CMD_STREAM_TYPE_INVALID = 0, /* explicitly treat 0 as invalid */ 56bf215546Sopenharmony_ci PVR_CMD_STREAM_TYPE_GRAPHICS, 57bf215546Sopenharmony_ci PVR_CMD_STREAM_TYPE_COMPUTE, 58bf215546Sopenharmony_ci}; 59bf215546Sopenharmony_ci 60bf215546Sopenharmony_cistruct pvr_csb { 61bf215546Sopenharmony_ci struct pvr_device *device; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci /* Pointer to current csb buffer object */ 64bf215546Sopenharmony_ci struct pvr_bo *pvr_bo; 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci /* pointers to current bo memory */ 67bf215546Sopenharmony_ci void *start; 68bf215546Sopenharmony_ci void *end; 69bf215546Sopenharmony_ci void *next; 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci /* List of csb buffer objects */ 72bf215546Sopenharmony_ci struct list_head pvr_bo_list; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci enum pvr_cmd_stream_type stream_type; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci /* Current error status of the command buffer. Used to track inconsistent 77bf215546Sopenharmony_ci * or incomplete command buffer states that are the consequence of run-time 78bf215546Sopenharmony_ci * errors such as out of memory scenarios. We want to track this in the 79bf215546Sopenharmony_ci * csb because the command buffer object is not visible to some parts 80bf215546Sopenharmony_ci * of the driver. 81bf215546Sopenharmony_ci */ 82bf215546Sopenharmony_ci VkResult status; 83bf215546Sopenharmony_ci}; 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci/** 86bf215546Sopenharmony_ci * \brief Gets the status of the csb. 87bf215546Sopenharmony_ci * 88bf215546Sopenharmony_ci * \param[in] csb Control Stream Builder object. 89bf215546Sopenharmony_ci * \return VK_SUCCESS if the csb hasn't encountered any error or error code 90bf215546Sopenharmony_ci * otherwise. 91bf215546Sopenharmony_ci */ 92bf215546Sopenharmony_cistatic inline VkResult pvr_csb_get_status(const struct pvr_csb *csb) 93bf215546Sopenharmony_ci{ 94bf215546Sopenharmony_ci return csb->status; 95bf215546Sopenharmony_ci} 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci/** 98bf215546Sopenharmony_ci * \brief Checks if the control stream is empty or not. 99bf215546Sopenharmony_ci * 100bf215546Sopenharmony_ci * \param[in] csb Control Stream Builder object. 101bf215546Sopenharmony_ci * \return true if csb is empty false otherwise. 102bf215546Sopenharmony_ci */ 103bf215546Sopenharmony_cistatic inline bool pvr_csb_is_empty(const struct pvr_csb *csb) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci return list_is_empty(&csb->pvr_bo_list); 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_cistatic inline pvr_dev_addr_t 109bf215546Sopenharmony_cipvr_csb_get_start_address(const struct pvr_csb *csb) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci if (!pvr_csb_is_empty(csb)) { 112bf215546Sopenharmony_ci struct pvr_bo *pvr_bo = 113bf215546Sopenharmony_ci list_first_entry(&csb->pvr_bo_list, struct pvr_bo, link); 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci return pvr_bo->vma->dev_addr; 116bf215546Sopenharmony_ci } 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci return PVR_DEV_ADDR_INVALID; 119bf215546Sopenharmony_ci} 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_civoid pvr_csb_init(struct pvr_device *device, 122bf215546Sopenharmony_ci enum pvr_cmd_stream_type stream_type, 123bf215546Sopenharmony_ci struct pvr_csb *csb); 124bf215546Sopenharmony_civoid pvr_csb_finish(struct pvr_csb *csb); 125bf215546Sopenharmony_civoid *pvr_csb_alloc_dwords(struct pvr_csb *csb, uint32_t num_dwords); 126bf215546Sopenharmony_ciVkResult pvr_csb_emit_return(struct pvr_csb *csb); 127bf215546Sopenharmony_ciVkResult pvr_csb_emit_terminate(struct pvr_csb *csb); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci#define PVRX(x) ROGUE_##x 130bf215546Sopenharmony_ci#define pvr_cmd_length(x) PVRX(x##_length) 131bf215546Sopenharmony_ci#define pvr_cmd_header(x) PVRX(x##_header) 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci/* This helper is internal to this header. It should only be used as part of 134bf215546Sopenharmony_ci * the pvr_csb_*() macros below. 135bf215546Sopenharmony_ci */ 136bf215546Sopenharmony_ci#define __pvr_cmd_pack(x) PVRX(x##_pack) 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci/** 139bf215546Sopenharmony_ci * \brief Packs a command/state into one or more dwords and stores them in the 140bf215546Sopenharmony_ci * memory pointed to by _dst. 141bf215546Sopenharmony_ci * 142bf215546Sopenharmony_ci * \param[out] _dst Pointer to store the packed command/state. 143bf215546Sopenharmony_ci * \param[in] cmd Command/state type. 144bf215546Sopenharmony_ci * \param[in,out] name Name to give to the command/state structure variable, 145bf215546Sopenharmony_ci * which contains the information to be packed and emitted. 146bf215546Sopenharmony_ci * This can be used by the caller to modify the command or 147bf215546Sopenharmony_ci * state information before it's packed. 148bf215546Sopenharmony_ci */ 149bf215546Sopenharmony_ci#define pvr_csb_pack(_dst, cmd, name) \ 150bf215546Sopenharmony_ci for (struct PVRX(cmd) name = { pvr_cmd_header(cmd) }, \ 151bf215546Sopenharmony_ci *_loop_terminate = &name; \ 152bf215546Sopenharmony_ci __builtin_expect(_loop_terminate != NULL, 1); \ 153bf215546Sopenharmony_ci ({ \ 154bf215546Sopenharmony_ci STATIC_ASSERT(sizeof(*(_dst)) == pvr_cmd_length(cmd) * 4); \ 155bf215546Sopenharmony_ci __pvr_cmd_pack(cmd)((_dst), &name); \ 156bf215546Sopenharmony_ci _loop_terminate = NULL; \ 157bf215546Sopenharmony_ci })) 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci/** 160bf215546Sopenharmony_ci * \brief Merges dwords0 and dwords1 arrays and stores the result into the 161bf215546Sopenharmony_ci * control stream pointed by the csb object. 162bf215546Sopenharmony_ci * 163bf215546Sopenharmony_ci * \param[in] csb Control Stream Builder object. 164bf215546Sopenharmony_ci * \param[in] dwords0 Dwords0 array. 165bf215546Sopenharmony_ci * \param[in] dwords1 Dwords1 array. 166bf215546Sopenharmony_ci */ 167bf215546Sopenharmony_ci#define pvr_csb_emit_merge(csb, dwords0, dwords1) \ 168bf215546Sopenharmony_ci do { \ 169bf215546Sopenharmony_ci uint32_t *dw; \ 170bf215546Sopenharmony_ci STATIC_ASSERT(ARRAY_SIZE(dwords0) == ARRAY_SIZE(dwords1)); \ 171bf215546Sopenharmony_ci dw = pvr_csb_alloc_dwords(csb, ARRAY_SIZE(dwords0)); \ 172bf215546Sopenharmony_ci if (!dw) \ 173bf215546Sopenharmony_ci break; \ 174bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(dwords0); i++) \ 175bf215546Sopenharmony_ci dw[i] = (dwords0)[i] | (dwords1)[i]; \ 176bf215546Sopenharmony_ci } while (0) 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci/** 179bf215546Sopenharmony_ci * \brief Packs a command/state into one or more dwords and stores them into 180bf215546Sopenharmony_ci * the control stream pointed by the csb object. 181bf215546Sopenharmony_ci * 182bf215546Sopenharmony_ci * \param[in] csb Control Stream Builder object. 183bf215546Sopenharmony_ci * \param[in] cmd Command/state type. 184bf215546Sopenharmony_ci * \param[in,out] name Name to give to the command/state structure variable, 185bf215546Sopenharmony_ci * which contains the information to be packed. This can be 186bf215546Sopenharmony_ci * used by the caller to modify the command or state 187bf215546Sopenharmony_ci * information before it's packed. 188bf215546Sopenharmony_ci */ 189bf215546Sopenharmony_ci#define pvr_csb_emit(csb, cmd, name) \ 190bf215546Sopenharmony_ci for (struct PVRX(cmd) \ 191bf215546Sopenharmony_ci name = { pvr_cmd_header(cmd) }, \ 192bf215546Sopenharmony_ci *_dst = pvr_csb_alloc_dwords(csb, pvr_cmd_length(cmd)); \ 193bf215546Sopenharmony_ci __builtin_expect(_dst != NULL, 1); \ 194bf215546Sopenharmony_ci ({ \ 195bf215546Sopenharmony_ci __pvr_cmd_pack(cmd)(_dst, &name); \ 196bf215546Sopenharmony_ci _dst = NULL; \ 197bf215546Sopenharmony_ci })) 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci/** 200bf215546Sopenharmony_ci * \brief Stores dword into the control stream pointed by the csb object. 201bf215546Sopenharmony_ci * 202bf215546Sopenharmony_ci * \param[in] csb Control Stream Builder object. 203bf215546Sopenharmony_ci * \param[in] dword Dword to store into control stream. 204bf215546Sopenharmony_ci */ 205bf215546Sopenharmony_ci#define pvr_csb_emit_dword(csb, dword) \ 206bf215546Sopenharmony_ci do { \ 207bf215546Sopenharmony_ci uint32_t *dw; \ 208bf215546Sopenharmony_ci STATIC_ASSERT(sizeof(dword) == sizeof(uint32_t)); \ 209bf215546Sopenharmony_ci dw = pvr_csb_alloc_dwords(csb, 1U); \ 210bf215546Sopenharmony_ci if (!dw) \ 211bf215546Sopenharmony_ci break; \ 212bf215546Sopenharmony_ci *dw = dword; \ 213bf215546Sopenharmony_ci } while (0) 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci#endif /* PVR_CSB_H */ 216