xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/pvr_hardcode.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 <stddef.h>
26 #include <stdint.h>
27 #include <string.h>
28 #include <vulkan/vulkan_core.h>
29 
30 #include "compiler/shader_enums.h"
31 #include "hwdef/rogue_hw_utils.h"
32 #include "pvr_device_info.h"
33 #include "pvr_hardcode.h"
34 #include "pvr_private.h"
35 #include "rogue/rogue.h"
36 #include "usc/hardcoded_apps/pvr_simple_compute.h"
37 #include "util/macros.h"
38 #include "util/u_dynarray.h"
39 #include "util/u_process.h"
40 
41 /**
42  * \file pvr_hardcode.c
43  *
44  * \brief Contains hard coding functions.
45  * This should eventually be deleted as the compiler becomes more capable.
46  */
47 
48 #define PVR_AXE_1_16M_BVNC PVR_BVNC_PACK(33, 15, 11, 3)
49 #define PVR_GX6250_BVNC PVR_BVNC_PACK(4, 40, 2, 51)
50 
51 #define util_dynarray_append_mem(buf, size, mem) \
52    memcpy(util_dynarray_grow_bytes((buf), 1, size), mem, size)
53 
54 enum pvr_hard_code_shader_type {
55    PVR_HARD_CODE_SHADER_TYPE_COMPUTE,
56    PVR_HARD_CODE_SHADER_TYPE_GRAPHICS,
57 };
58 
59 static const struct pvr_hard_coding_data {
60    const char *const name;
61    uint64_t bvnc;
62    enum pvr_hard_code_shader_type type;
63 
64    union {
65       struct {
66          const uint8_t *const shader;
67          size_t shader_size;
68 
69          /* Note that the bo field will be unused. */
70          const struct pvr_compute_shader_state shader_info;
71 
72          const struct pvr_hard_code_compute_build_info build_info;
73       } compute;
74 
75       struct {
76          /* Mask of MESA_SHADER_* (gl_shader_stage). */
77          uint32_t flags;
78 
79          uint8_t *const *const vert_shaders;
80          unsigned *vert_shader_sizes;
81          uint8_t *const *const frag_shaders;
82          unsigned *frag_shader_sizes;
83 
84          const struct pvr_vertex_shader_state *const *const vert_shader_states;
85          const struct pvr_fragment_shader_state *const *const frag_shader_states;
86 
87          const struct pvr_hard_code_graphics_build_info *const
88             *const build_infos;
89 
90          uint32_t shader_count;
91       } graphics;
92    };
93 
94 } hard_coding_table[] = {
95    {
96       .name = "simple-compute",
97       .bvnc = PVR_GX6250_BVNC,
98       .type = PVR_HARD_CODE_SHADER_TYPE_COMPUTE,
99 
100       .compute = {
101          .shader = pvr_simple_compute_shader,
102          .shader_size = sizeof(pvr_simple_compute_shader),
103 
104          .shader_info = {
105             .uses_atomic_ops = false,
106             .uses_barrier = false,
107             .uses_num_workgroups = false,
108 
109             .const_shared_reg_count = 4,
110             .input_register_count = 8,
111             .work_size = 1 * 1 * 1,
112             .coefficient_register_count = 4,
113          },
114 
115          .build_info = {
116             .ubo_data = { 0 },
117             .compile_time_consts_data = {
118                .static_consts = { 0 },
119             },
120 
121             .local_invocation_regs = { 0, 1 },
122             .work_group_regs = { 0, 1, 2 },
123             .barrier_reg = ROGUE_REG_UNUSED,
124             .usc_temps = 0,
125 
126             .explicit_conts_usage = {
127                .start_offset = 0,
128             },
129          },
130       }
131    },
132 };
133 
134 static inline uint64_t
pvr_device_get_bvnc(const struct pvr_device_info * const dev_info)135 pvr_device_get_bvnc(const struct pvr_device_info *const dev_info)
136 {
137    const struct pvr_device_ident *const ident = &dev_info->ident;
138 
139    return PVR_BVNC_PACK(ident->b, ident->v, ident->n, ident->c);
140 }
141 
pvr_has_hard_coded_shaders(const struct pvr_device_info * const dev_info)142 bool pvr_has_hard_coded_shaders(const struct pvr_device_info *const dev_info)
143 {
144    const char *const program = util_get_process_name();
145    const uint64_t bvnc = pvr_device_get_bvnc(dev_info);
146 
147    for (uint32_t i = 0; i < ARRAY_SIZE(hard_coding_table); i++) {
148       if (bvnc != hard_coding_table[i].bvnc)
149          continue;
150 
151       if (strcmp(program, hard_coding_table[i].name) == 0)
152          return true;
153    }
154 
155    return false;
156 }
157 
158 static const struct pvr_hard_coding_data *
pvr_get_hard_coding_data(const struct pvr_device_info * const dev_info)159 pvr_get_hard_coding_data(const struct pvr_device_info *const dev_info)
160 {
161    const char *const program = util_get_process_name();
162    const uint64_t bvnc = pvr_device_get_bvnc(dev_info);
163 
164    for (uint32_t i = 0; i < ARRAY_SIZE(hard_coding_table); i++) {
165       if (bvnc != hard_coding_table[i].bvnc)
166          continue;
167 
168       if (strcmp(program, hard_coding_table[i].name) == 0)
169          return &hard_coding_table[i];
170    }
171 
172    mesa_loge("Could not find hard coding data for %s", program);
173 
174    return NULL;
175 }
176 
pvr_hard_code_compute_pipeline(struct pvr_device * const device,struct pvr_compute_shader_state * const shader_state_out,struct pvr_hard_code_compute_build_info * const build_info_out)177 VkResult pvr_hard_code_compute_pipeline(
178    struct pvr_device *const device,
179    struct pvr_compute_shader_state *const shader_state_out,
180    struct pvr_hard_code_compute_build_info *const build_info_out)
181 {
182    const uint32_t cache_line_size =
183       rogue_get_slc_cache_line_size(&device->pdevice->dev_info);
184    const struct pvr_hard_coding_data *const data =
185       pvr_get_hard_coding_data(&device->pdevice->dev_info);
186 
187    assert(data->type == PVR_HARD_CODE_SHADER_TYPE_COMPUTE);
188 
189    mesa_logd("Hard coding compute pipeline for %s", data->name);
190 
191    *build_info_out = data->compute.build_info;
192    *shader_state_out = data->compute.shader_info;
193 
194    return pvr_gpu_upload_usc(device,
195                              data->compute.shader,
196                              data->compute.shader_size,
197                              cache_line_size,
198                              &shader_state_out->bo);
199 }
200 
201 uint32_t
pvr_hard_code_graphics_get_flags(const struct pvr_device_info * const dev_info)202 pvr_hard_code_graphics_get_flags(const struct pvr_device_info *const dev_info)
203 {
204    const struct pvr_hard_coding_data *const data =
205       pvr_get_hard_coding_data(dev_info);
206 
207    assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
208 
209    return data->graphics.flags;
210 }
211 
pvr_hard_code_graphics_shader(const struct pvr_device_info * const dev_info,uint32_t pipeline_n,gl_shader_stage stage,struct util_dynarray * shader_out)212 void pvr_hard_code_graphics_shader(const struct pvr_device_info *const dev_info,
213                                    uint32_t pipeline_n,
214                                    gl_shader_stage stage,
215                                    struct util_dynarray *shader_out)
216 {
217    const struct pvr_hard_coding_data *const data =
218       pvr_get_hard_coding_data(dev_info);
219 
220    assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
221    assert(pipeline_n < data->graphics.shader_count);
222    assert(data->graphics.flags & BITFIELD_BIT(stage));
223 
224    mesa_logd("Hard coding %s stage shader for \"%s\" demo.",
225              _mesa_shader_stage_to_string(stage),
226              data->name);
227 
228    switch (stage) {
229    case MESA_SHADER_VERTEX:
230       util_dynarray_append_mem(shader_out,
231                                data->graphics.vert_shader_sizes[pipeline_n],
232                                data->graphics.vert_shaders[pipeline_n]);
233       break;
234 
235    case MESA_SHADER_FRAGMENT:
236       util_dynarray_append_mem(shader_out,
237                                data->graphics.frag_shader_sizes[pipeline_n],
238                                data->graphics.frag_shaders[pipeline_n]);
239       break;
240 
241    default:
242       unreachable("Unsupported stage.");
243    }
244 }
245 
pvr_hard_code_graphics_vertex_state(const struct pvr_device_info * const dev_info,uint32_t pipeline_n,struct pvr_vertex_shader_state * const vert_state_out)246 void pvr_hard_code_graphics_vertex_state(
247    const struct pvr_device_info *const dev_info,
248    uint32_t pipeline_n,
249    struct pvr_vertex_shader_state *const vert_state_out)
250 {
251    const struct pvr_hard_coding_data *const data =
252       pvr_get_hard_coding_data(dev_info);
253 
254    assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
255    assert(pipeline_n < data->graphics.shader_count);
256    assert(data->graphics.flags & BITFIELD_BIT(MESA_SHADER_VERTEX));
257 
258    *vert_state_out = *data->graphics.vert_shader_states[0];
259 }
260 
pvr_hard_code_graphics_fragment_state(const struct pvr_device_info * const dev_info,uint32_t pipeline_n,struct pvr_fragment_shader_state * const frag_state_out)261 void pvr_hard_code_graphics_fragment_state(
262    const struct pvr_device_info *const dev_info,
263    uint32_t pipeline_n,
264    struct pvr_fragment_shader_state *const frag_state_out)
265 {
266    const struct pvr_hard_coding_data *const data =
267       pvr_get_hard_coding_data(dev_info);
268 
269    assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
270    assert(pipeline_n < data->graphics.shader_count);
271    assert(data->graphics.flags & BITFIELD_BIT(MESA_SHADER_FRAGMENT));
272 
273    *frag_state_out = *data->graphics.frag_shader_states[0];
274 }
275 
pvr_hard_code_graphics_get_build_info(const struct pvr_device_info * const dev_info,uint32_t pipeline_n,gl_shader_stage stage,struct rogue_common_build_data * const common_build_data,struct rogue_build_data * const build_data,struct pvr_explicit_constant_usage * const explicit_const_usage)276 void pvr_hard_code_graphics_get_build_info(
277    const struct pvr_device_info *const dev_info,
278    uint32_t pipeline_n,
279    gl_shader_stage stage,
280    struct rogue_common_build_data *const common_build_data,
281    struct rogue_build_data *const build_data,
282    struct pvr_explicit_constant_usage *const explicit_const_usage)
283 {
284    const struct pvr_hard_coding_data *const data =
285       pvr_get_hard_coding_data(dev_info);
286 
287    assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS);
288    assert(pipeline_n < data->graphics.shader_count);
289    assert(data->graphics.flags & BITFIELD_BIT(stage));
290 
291    switch (stage) {
292    case MESA_SHADER_VERTEX:
293       assert(data->graphics.build_infos[pipeline_n]->vert_common_data.temps ==
294              data->graphics.vert_shader_states[pipeline_n]
295                 ->stage_state.pds_temps_count);
296 
297       assert(data->graphics.build_infos[pipeline_n]->vert_common_data.coeffs ==
298              data->graphics.vert_shader_states[pipeline_n]
299                 ->stage_state.coefficient_size);
300 
301       build_data->vs = data->graphics.build_infos[pipeline_n]->stage_data.vs;
302       *common_build_data =
303          data->graphics.build_infos[pipeline_n]->vert_common_data;
304       *explicit_const_usage =
305          data->graphics.build_infos[pipeline_n]->vert_explicit_conts_usage;
306 
307       break;
308 
309    case MESA_SHADER_FRAGMENT:
310       assert(data->graphics.build_infos[pipeline_n]->frag_common_data.temps ==
311              data->graphics.frag_shader_states[pipeline_n]
312                 ->stage_state.pds_temps_count);
313 
314       assert(data->graphics.build_infos[pipeline_n]->frag_common_data.coeffs ==
315              data->graphics.frag_shader_states[pipeline_n]
316                 ->stage_state.coefficient_size);
317 
318       build_data->fs = data->graphics.build_infos[pipeline_n]->stage_data.fs;
319       *common_build_data =
320          data->graphics.build_infos[pipeline_n]->frag_common_data;
321       *explicit_const_usage =
322          data->graphics.build_infos[pipeline_n]->frag_explicit_conts_usage;
323 
324       break;
325 
326    default:
327       unreachable("Unsupported stage.");
328    }
329 }
330 
pvr_hard_code_get_idfwdf_program(const struct pvr_device_info * const dev_info,struct util_dynarray * program_out,uint32_t * usc_shareds_out,uint32_t * usc_temps_out)331 void pvr_hard_code_get_idfwdf_program(
332    const struct pvr_device_info *const dev_info,
333    struct util_dynarray *program_out,
334    uint32_t *usc_shareds_out,
335    uint32_t *usc_temps_out)
336 {
337    static const uint8_t shader[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
338 
339    mesa_loge("No hard coded idfwdf program. Returning empty program.");
340 
341    util_dynarray_append_mem(program_out, ARRAY_SIZE(shader), &shader[0]);
342 
343    *usc_shareds_out = 12U;
344    *usc_temps_out = 4U;
345 }
346 
pvr_hard_code_get_passthrough_vertex_shader(const struct pvr_device_info * const dev_info,struct util_dynarray * program_out)347 void pvr_hard_code_get_passthrough_vertex_shader(
348    const struct pvr_device_info *const dev_info,
349    struct util_dynarray *program_out)
350 {
351    static const uint8_t shader[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
352 
353    mesa_loge(
354       "No hard coded passthrough vertex shader. Returning empty shader.");
355 
356    util_dynarray_append_mem(program_out, ARRAY_SIZE(shader), &shader[0]);
357 };
358 
359 /* Render target array (RTA). */
pvr_hard_code_get_passthrough_rta_vertex_shader(const struct pvr_device_info * const dev_info,struct util_dynarray * program_out)360 void pvr_hard_code_get_passthrough_rta_vertex_shader(
361    const struct pvr_device_info *const dev_info,
362    struct util_dynarray *program_out)
363 {
364    uint32_t shader[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
365 
366    util_dynarray_append_mem(program_out, ARRAY_SIZE(shader), &shader);
367 
368    mesa_loge("No hard coded passthrough rta vertex shader. Returning "
369              "empty shader.");
370 }
371