Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/drivers/freedreno/ir3/ir3_cmdline.c
4574 views
1
/*
2
* Copyright (C) 2014 Rob Clark <[email protected]>
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the "Software"),
6
* to deal in the Software without restriction, including without limitation
7
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
* and/or sell copies of the Software, and to permit persons to whom the
9
* Software is 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
18
* THE 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
* Authors:
24
* Rob Clark <[email protected]>
25
*/
26
27
#include <err.h>
28
#include <fcntl.h>
29
#include <getopt.h>
30
#include <stdint.h>
31
#include <stdio.h>
32
#include <stdlib.h>
33
#include <sys/mman.h>
34
#include <sys/stat.h>
35
#include <sys/types.h>
36
37
#include "nir/tgsi_to_nir.h"
38
#include "tgsi/tgsi_dump.h"
39
#include "tgsi/tgsi_parse.h"
40
#include "tgsi/tgsi_text.h"
41
42
#include "ir3/instr-a3xx.h"
43
#include "ir3/ir3.h"
44
#include "ir3/ir3_compiler.h"
45
#include "ir3/ir3_gallium.h"
46
#include "ir3/ir3_nir.h"
47
48
#include "main/mtypes.h"
49
50
#include "compiler/glsl/gl_nir.h"
51
#include "compiler/glsl/glsl_to_nir.h"
52
#include "compiler/glsl/standalone.h"
53
#include "compiler/nir_types.h"
54
#include "compiler/spirv/nir_spirv.h"
55
56
#include "pipe/p_context.h"
57
58
static void
59
dump_info(struct ir3_shader_variant *so, const char *str)
60
{
61
uint32_t *bin;
62
const char *type = ir3_shader_stage(so);
63
bin = ir3_shader_assemble(so);
64
printf("; %s: %s\n", type, str);
65
ir3_shader_disasm(so, bin, stdout);
66
}
67
68
static void
69
insert_sorted(struct exec_list *var_list, nir_variable *new_var)
70
{
71
nir_foreach_variable_in_list (var, var_list) {
72
if (var->data.location > new_var->data.location) {
73
exec_node_insert_node_before(&var->node, &new_var->node);
74
return;
75
}
76
}
77
exec_list_push_tail(var_list, &new_var->node);
78
}
79
80
static void
81
sort_varyings(nir_shader *nir, nir_variable_mode mode)
82
{
83
struct exec_list new_list;
84
exec_list_make_empty(&new_list);
85
nir_foreach_variable_with_modes_safe (var, nir, mode) {
86
exec_node_remove(&var->node);
87
insert_sorted(&new_list, var);
88
}
89
exec_list_append(&nir->variables, &new_list);
90
}
91
92
static void
93
fixup_varying_slots(nir_shader *nir, nir_variable_mode mode)
94
{
95
nir_foreach_variable_with_modes (var, nir, mode) {
96
if (var->data.location >= VARYING_SLOT_VAR0) {
97
var->data.location += 9;
98
} else if ((var->data.location >= VARYING_SLOT_TEX0) &&
99
(var->data.location <= VARYING_SLOT_TEX7)) {
100
var->data.location += VARYING_SLOT_VAR0 - VARYING_SLOT_TEX0;
101
}
102
}
103
}
104
105
static struct ir3_compiler *compiler;
106
107
static nir_shader *
108
load_glsl(unsigned num_files, char *const *files, gl_shader_stage stage)
109
{
110
static const struct standalone_options options = {
111
.glsl_version = 310,
112
.do_link = true,
113
.lower_precision = true,
114
};
115
struct gl_shader_program *prog;
116
const nir_shader_compiler_options *nir_options =
117
ir3_get_compiler_options(compiler);
118
static struct gl_context local_ctx;
119
120
prog = standalone_compile_shader(&options, num_files, files, &local_ctx);
121
if (!prog)
122
errx(1, "couldn't parse `%s'", files[0]);
123
124
nir_shader *nir = glsl_to_nir(&local_ctx, prog, stage, nir_options);
125
126
/* required NIR passes: */
127
if (nir_options->lower_all_io_to_temps ||
128
nir->info.stage == MESA_SHADER_VERTEX ||
129
nir->info.stage == MESA_SHADER_GEOMETRY) {
130
NIR_PASS_V(nir, nir_lower_io_to_temporaries,
131
nir_shader_get_entrypoint(nir), true, true);
132
} else if (nir->info.stage == MESA_SHADER_FRAGMENT) {
133
NIR_PASS_V(nir, nir_lower_io_to_temporaries,
134
nir_shader_get_entrypoint(nir), true, false);
135
}
136
137
NIR_PASS_V(nir, nir_lower_global_vars_to_local);
138
NIR_PASS_V(nir, nir_split_var_copies);
139
NIR_PASS_V(nir, nir_lower_var_copies);
140
141
NIR_PASS_V(nir, nir_split_var_copies);
142
NIR_PASS_V(nir, nir_lower_var_copies);
143
nir_print_shader(nir, stdout);
144
NIR_PASS_V(nir, gl_nir_lower_atomics, prog, true);
145
NIR_PASS_V(nir, gl_nir_lower_buffers, prog);
146
NIR_PASS_V(nir, nir_lower_atomics_to_ssbo);
147
nir_print_shader(nir, stdout);
148
149
switch (stage) {
150
case MESA_SHADER_VERTEX:
151
nir_assign_var_locations(nir, nir_var_shader_in, &nir->num_inputs,
152
ir3_glsl_type_size);
153
154
/* Re-lower global vars, to deal with any dead VS inputs. */
155
NIR_PASS_V(nir, nir_lower_global_vars_to_local);
156
157
sort_varyings(nir, nir_var_shader_out);
158
nir_assign_var_locations(nir, nir_var_shader_out, &nir->num_outputs,
159
ir3_glsl_type_size);
160
fixup_varying_slots(nir, nir_var_shader_out);
161
break;
162
case MESA_SHADER_FRAGMENT:
163
sort_varyings(nir, nir_var_shader_in);
164
nir_assign_var_locations(nir, nir_var_shader_in, &nir->num_inputs,
165
ir3_glsl_type_size);
166
fixup_varying_slots(nir, nir_var_shader_in);
167
nir_assign_var_locations(nir, nir_var_shader_out, &nir->num_outputs,
168
ir3_glsl_type_size);
169
break;
170
case MESA_SHADER_COMPUTE:
171
case MESA_SHADER_KERNEL:
172
break;
173
default:
174
errx(1, "unhandled shader stage: %d", stage);
175
}
176
177
nir_assign_var_locations(nir, nir_var_uniform, &nir->num_uniforms,
178
ir3_glsl_type_size);
179
180
NIR_PASS_V(nir, nir_lower_system_values);
181
NIR_PASS_V(nir, nir_lower_compute_system_values, NULL);
182
183
NIR_PASS_V(nir, nir_lower_frexp);
184
NIR_PASS_V(nir, nir_lower_io,
185
nir_var_shader_in | nir_var_shader_out | nir_var_uniform,
186
ir3_glsl_type_size, (nir_lower_io_options)0);
187
NIR_PASS_V(nir, gl_nir_lower_samplers, prog);
188
189
return nir;
190
}
191
192
static int
193
read_file(const char *filename, void **ptr, size_t *size)
194
{
195
int fd, ret;
196
struct stat st;
197
198
*ptr = MAP_FAILED;
199
200
fd = open(filename, O_RDONLY);
201
if (fd == -1) {
202
warnx("couldn't open `%s'", filename);
203
return 1;
204
}
205
206
ret = fstat(fd, &st);
207
if (ret)
208
errx(1, "couldn't stat `%s'", filename);
209
210
*size = st.st_size;
211
*ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
212
if (*ptr == MAP_FAILED)
213
errx(1, "couldn't map `%s'", filename);
214
215
close(fd);
216
217
return 0;
218
}
219
220
static void
221
debug_func(void *priv, enum nir_spirv_debug_level level, size_t spirv_offset,
222
const char *message)
223
{
224
// printf("%s\n", message);
225
}
226
227
static nir_shader *
228
load_spirv(const char *filename, const char *entry, gl_shader_stage stage)
229
{
230
const struct spirv_to_nir_options spirv_options = {
231
/* these caps are just make-believe */
232
.caps = {
233
.draw_parameters = true,
234
.float64 = true,
235
.image_read_without_format = true,
236
.image_write_without_format = true,
237
.int64 = true,
238
.variable_pointers = true,
239
},
240
.debug = {
241
.func = debug_func,
242
}
243
};
244
nir_shader *nir;
245
void *buf;
246
size_t size;
247
248
read_file(filename, &buf, &size);
249
250
nir = spirv_to_nir(buf, size / 4, NULL, 0, /* spec_entries */
251
stage, entry, &spirv_options,
252
ir3_get_compiler_options(compiler));
253
254
nir_print_shader(nir, stdout);
255
256
return nir;
257
}
258
259
static const char *shortopts = "g:hv";
260
261
static const struct option longopts[] = {
262
{"gpu", required_argument, 0, 'g'},
263
{"help", no_argument, 0, 'h'},
264
{"verbose", no_argument, 0, 'v'},
265
};
266
267
static void
268
print_usage(void)
269
{
270
printf("Usage: ir3_compiler [OPTIONS]... <file.tgsi | file.spv entry_point "
271
"| (file.vert | file.frag)*>\n");
272
printf(" -g, --gpu GPU_ID - specify gpu-id (default 320)\n");
273
printf(" -h, --help - show this message\n");
274
printf(" -v, --verbose - verbose compiler/debug messages\n");
275
}
276
277
int
278
main(int argc, char **argv)
279
{
280
int ret = 0, opt;
281
char *filenames[2];
282
int num_files = 0;
283
unsigned stage = 0;
284
struct ir3_shader_key key = {};
285
unsigned gpu_id = 320;
286
const char *info;
287
const char *spirv_entry = NULL;
288
void *ptr;
289
bool from_tgsi = false;
290
size_t size;
291
292
while ((opt = getopt_long_only(argc, argv, shortopts, longopts, NULL)) !=
293
-1) {
294
switch (opt) {
295
case 'g':
296
gpu_id = strtol(optarg, NULL, 0);
297
break;
298
case 'v':
299
ir3_shader_debug |= IR3_DBG_OPTMSGS | IR3_DBG_DISASM;
300
break;
301
default:
302
printf("unrecognized arg: %c\n", opt);
303
FALLTHROUGH;
304
case 'h':
305
print_usage();
306
return 0;
307
}
308
}
309
310
if (optind >= argc) {
311
fprintf(stderr, "no file specified!\n");
312
print_usage();
313
return 0;
314
}
315
316
unsigned n = optind;
317
while (n < argc) {
318
char *filename = argv[n];
319
char *ext = strrchr(filename, '.');
320
321
if (strcmp(ext, ".tgsi") == 0) {
322
if (num_files != 0)
323
errx(1, "in TGSI mode, only a single file may be specified");
324
from_tgsi = true;
325
} else if (strcmp(ext, ".spv") == 0) {
326
if (num_files != 0)
327
errx(1, "in SPIR-V mode, only a single file may be specified");
328
stage = MESA_SHADER_COMPUTE;
329
filenames[num_files++] = filename;
330
n++;
331
if (n == argc)
332
errx(1, "in SPIR-V mode, an entry point must be specified");
333
spirv_entry = argv[n];
334
n++;
335
} else if (strcmp(ext, ".comp") == 0) {
336
if (from_tgsi || spirv_entry)
337
errx(1, "cannot mix GLSL/TGSI/SPIRV");
338
if (num_files >= ARRAY_SIZE(filenames))
339
errx(1, "too many GLSL files");
340
stage = MESA_SHADER_COMPUTE;
341
} else if (strcmp(ext, ".frag") == 0) {
342
if (from_tgsi || spirv_entry)
343
errx(1, "cannot mix GLSL/TGSI/SPIRV");
344
if (num_files >= ARRAY_SIZE(filenames))
345
errx(1, "too many GLSL files");
346
stage = MESA_SHADER_FRAGMENT;
347
} else if (strcmp(ext, ".vert") == 0) {
348
if (from_tgsi)
349
errx(1, "cannot mix GLSL and TGSI");
350
if (num_files >= ARRAY_SIZE(filenames))
351
errx(1, "too many GLSL files");
352
stage = MESA_SHADER_VERTEX;
353
} else {
354
print_usage();
355
return -1;
356
}
357
358
filenames[num_files++] = filename;
359
360
n++;
361
}
362
363
nir_shader *nir;
364
365
compiler = ir3_compiler_create(NULL, gpu_id, false);
366
367
if (from_tgsi) {
368
struct tgsi_token toks[65536];
369
const nir_shader_compiler_options *nir_options =
370
ir3_get_compiler_options(compiler);
371
372
ret = read_file(filenames[0], &ptr, &size);
373
if (ret) {
374
print_usage();
375
return ret;
376
}
377
378
if (ir3_shader_debug & IR3_DBG_OPTMSGS)
379
printf("%s\n", (char *)ptr);
380
381
if (!tgsi_text_translate(ptr, toks, ARRAY_SIZE(toks)))
382
errx(1, "could not parse `%s'", filenames[0]);
383
384
if (ir3_shader_debug & IR3_DBG_OPTMSGS)
385
tgsi_dump(toks, 0);
386
387
nir = tgsi_to_nir_noscreen(toks, nir_options);
388
NIR_PASS_V(nir, nir_lower_global_vars_to_local);
389
} else if (spirv_entry) {
390
nir = load_spirv(filenames[0], spirv_entry, stage);
391
392
NIR_PASS_V(nir, nir_lower_io, nir_var_shader_in | nir_var_shader_out,
393
ir3_glsl_type_size, (nir_lower_io_options)0);
394
395
/* TODO do this somewhere else */
396
nir_lower_int64(nir);
397
nir_lower_system_values(nir);
398
nir_lower_compute_system_values(nir, NULL);
399
} else if (num_files > 0) {
400
nir = load_glsl(num_files, filenames, stage);
401
} else {
402
print_usage();
403
return -1;
404
}
405
406
ir3_nir_lower_io_to_temporaries(nir);
407
ir3_finalize_nir(compiler, nir);
408
ir3_nir_post_finalize(compiler, nir);
409
410
struct ir3_shader *shader = rzalloc_size(NULL, sizeof(*shader));
411
shader->compiler = compiler;
412
shader->type = stage;
413
shader->nir = nir;
414
415
struct ir3_shader_variant *v = rzalloc_size(shader, sizeof(*v));
416
v->type = shader->type;
417
v->shader = shader;
418
v->key = key;
419
v->const_state = rzalloc_size(v, sizeof(*v->const_state));
420
421
shader->variants = v;
422
shader->variant_count = 1;
423
424
ir3_nir_lower_variant(v, nir);
425
426
info = "NIR compiler";
427
ret = ir3_compile_shader_nir(compiler, v);
428
if (ret) {
429
fprintf(stderr, "compiler failed!\n");
430
return ret;
431
}
432
dump_info(v, info);
433
434
return 0;
435
}
436
437