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