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