• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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