v3d: Refactor compiler entrypoints.

Before, I had per-stage entryoints with some helpers shared between them.
As I extended for compute shaders and shader-db, it turned out that the
other common code in the middle wanted to be shared too.
This commit is contained in:
Eric Anholt
2018-12-26 13:20:25 -08:00
parent 0805060573
commit d2b899c0ec
3 changed files with 174 additions and 193 deletions

View File

@@ -706,19 +706,9 @@ const struct v3d_compiler *v3d_compiler_init(const struct v3d_device_info *devin
void v3d_compiler_free(const struct v3d_compiler *compiler);
void v3d_optimize_nir(struct nir_shader *s);
uint64_t *v3d_compile_vs(const struct v3d_compiler *compiler,
struct v3d_vs_key *key,
struct v3d_vs_prog_data *prog_data,
nir_shader *s,
void (*debug_output)(const char *msg,
void *debug_output_data),
void *debug_output_data,
int program_id, int variant_id,
uint32_t *final_assembly_size);
uint64_t *v3d_compile_fs(const struct v3d_compiler *compiler,
struct v3d_fs_key *key,
struct v3d_fs_prog_data *prog_data,
uint64_t *v3d_compile(const struct v3d_compiler *compiler,
struct v3d_key *key,
struct v3d_prog_data **prog_data,
nir_shader *s,
void (*debug_output)(const char *msg,
void *debug_output_data),

View File

@@ -625,14 +625,6 @@ v3d_lower_nir(struct v3d_compile *c)
NIR_PASS_V(c->s, nir_lower_tex, &tex_options);
}
static void
v3d_lower_nir_late(struct v3d_compile *c)
{
NIR_PASS_V(c->s, v3d_nir_lower_io, c);
NIR_PASS_V(c->s, v3d_nir_lower_txf_ms, c);
NIR_PASS_V(c->s, nir_lower_idiv);
}
static void
v3d_set_prog_data_uniforms(struct v3d_compile *c,
struct v3d_prog_data *prog_data)
@@ -685,109 +677,9 @@ v3d_set_prog_data_ubo(struct v3d_compile *c,
}
static void
v3d_set_prog_data(struct v3d_compile *c,
struct v3d_prog_data *prog_data)
v3d_vs_set_prog_data(struct v3d_compile *c,
struct v3d_vs_prog_data *prog_data)
{
prog_data->threads = c->threads;
prog_data->single_seg = !c->last_thrsw;
prog_data->spill_size = c->spill_size;
v3d_set_prog_data_uniforms(c, prog_data);
v3d_set_prog_data_ubo(c, prog_data);
}
static uint64_t *
v3d_return_qpu_insts(struct v3d_compile *c, uint32_t *final_assembly_size)
{
*final_assembly_size = c->qpu_inst_count * sizeof(uint64_t);
uint64_t *qpu_insts = malloc(*final_assembly_size);
if (!qpu_insts)
return NULL;
memcpy(qpu_insts, c->qpu_insts, *final_assembly_size);
char *shaderdb;
int ret = asprintf(&shaderdb,
"%s shader: %d inst, %d threads, %d loops, "
"%d uniforms, %d:%d spills:fills",
vir_get_stage_name(c),
c->qpu_inst_count,
c->threads,
c->loops,
c->num_uniforms,
c->spills,
c->fills);
if (ret >= 0) {
c->debug_output(shaderdb, c->debug_output_data);
free(shaderdb);
}
vir_compile_destroy(c);
return qpu_insts;
}
uint64_t *v3d_compile_vs(const struct v3d_compiler *compiler,
struct v3d_vs_key *key,
struct v3d_vs_prog_data *prog_data,
nir_shader *s,
void (*debug_output)(const char *msg,
void *debug_output_data),
void *debug_output_data,
int program_id, int variant_id,
uint32_t *final_assembly_size)
{
struct v3d_compile *c = vir_compile_init(compiler, &key->base, s,
debug_output, debug_output_data,
program_id, variant_id);
c->vs_key = key;
/* Split our I/O vars and dead code eliminate the unused
* components.
*/
NIR_PASS_V(c->s, nir_lower_io_to_scalar_early,
nir_var_shader_in | nir_var_shader_out);
uint64_t used_outputs[4] = {0};
for (int i = 0; i < c->vs_key->num_fs_inputs; i++) {
int slot = v3d_slot_get_slot(c->vs_key->fs_inputs[i]);
int comp = v3d_slot_get_component(c->vs_key->fs_inputs[i]);
used_outputs[comp] |= 1ull << slot;
}
NIR_PASS_V(c->s, nir_remove_unused_io_vars,
&c->s->outputs, used_outputs, NULL); /* demotes to globals */
NIR_PASS_V(c->s, nir_lower_global_vars_to_local);
v3d_optimize_nir(c->s);
NIR_PASS_V(c->s, nir_remove_dead_variables, nir_var_shader_in);
NIR_PASS_V(c->s, nir_lower_io, nir_var_shader_in | nir_var_shader_out,
type_size_vec4,
(nir_lower_io_options)0);
v3d_lower_nir(c);
if (key->clamp_color)
NIR_PASS_V(c->s, nir_lower_clamp_color_outputs);
if (key->base.ucp_enables) {
NIR_PASS_V(c->s, nir_lower_clip_vs, key->base.ucp_enables,
false);
NIR_PASS_V(c->s, nir_lower_io_to_scalar,
nir_var_shader_out);
}
/* Note: VS output scalarizing must happen after nir_lower_clip_vs. */
NIR_PASS_V(c->s, nir_lower_io_to_scalar, nir_var_shader_out);
v3d_lower_nir_late(c);
v3d_optimize_nir(c->s);
NIR_PASS_V(c->s, nir_lower_bool_to_int32);
NIR_PASS_V(c->s, nir_convert_from_ssa, true);
v3d_nir_to_vir(c);
v3d_set_prog_data(c, &prog_data->base);
prog_data->base.num_inputs = c->num_inputs;
/* The vertex data gets format converted by the VPM so that
@@ -799,9 +691,9 @@ uint64_t *v3d_compile_vs(const struct v3d_compiler *compiler,
prog_data->vpm_input_size += c->vattr_sizes[i];
}
prog_data->uses_vid = (s->info.system_values_read &
prog_data->uses_vid = (c->s->info.system_values_read &
(1ull << SYSTEM_VALUE_VERTEX_ID));
prog_data->uses_iid = (s->info.system_values_read &
prog_data->uses_iid = (c->s->info.system_values_read &
(1ull << SYSTEM_VALUE_INSTANCE_ID));
if (prog_data->uses_vid)
@@ -839,8 +731,6 @@ uint64_t *v3d_compile_vs(const struct v3d_compiler *compiler,
int vpm_output_batches = vpm_output_sectors / prog_data->vpm_output_size;
assert(vpm_output_batches >= 2);
prog_data->vcm_cache_size = CLAMP(vpm_output_batches - 1, 2, 4);
return v3d_return_qpu_insts(c, final_assembly_size);
}
static void
@@ -865,6 +755,77 @@ v3d_set_fs_prog_data_inputs(struct v3d_compile *c,
}
}
static void
v3d_fs_set_prog_data(struct v3d_compile *c,
struct v3d_fs_prog_data *prog_data)
{
v3d_set_fs_prog_data_inputs(c, prog_data);
prog_data->writes_z = (c->s->info.outputs_written &
(1 << FRAG_RESULT_DEPTH));
prog_data->discard = (c->s->info.fs.uses_discard ||
c->fs_key->sample_alpha_to_coverage);
prog_data->uses_center_w = c->uses_center_w;
}
static void
v3d_set_prog_data(struct v3d_compile *c,
struct v3d_prog_data *prog_data)
{
prog_data->threads = c->threads;
prog_data->single_seg = !c->last_thrsw;
prog_data->spill_size = c->spill_size;
v3d_set_prog_data_uniforms(c, prog_data);
v3d_set_prog_data_ubo(c, prog_data);
if (c->s->info.stage == MESA_SHADER_VERTEX) {
v3d_vs_set_prog_data(c, (struct v3d_vs_prog_data *)prog_data);
} else {
assert(c->s->info.stage == MESA_SHADER_FRAGMENT);
v3d_fs_set_prog_data(c, (struct v3d_fs_prog_data *)prog_data);
}
}
static uint64_t *
v3d_return_qpu_insts(struct v3d_compile *c, uint32_t *final_assembly_size)
{
*final_assembly_size = c->qpu_inst_count * sizeof(uint64_t);
uint64_t *qpu_insts = malloc(*final_assembly_size);
if (!qpu_insts)
return NULL;
memcpy(qpu_insts, c->qpu_insts, *final_assembly_size);
vir_compile_destroy(c);
return qpu_insts;
}
static void
v3d_nir_lower_vs_early(struct v3d_compile *c)
{
/* Split our I/O vars and dead code eliminate the unused
* components.
*/
NIR_PASS_V(c->s, nir_lower_io_to_scalar_early,
nir_var_shader_in | nir_var_shader_out);
uint64_t used_outputs[4] = {0};
for (int i = 0; i < c->vs_key->num_fs_inputs; i++) {
int slot = v3d_slot_get_slot(c->vs_key->fs_inputs[i]);
int comp = v3d_slot_get_component(c->vs_key->fs_inputs[i]);
used_outputs[comp] |= 1ull << slot;
}
NIR_PASS_V(c->s, nir_remove_unused_io_vars,
&c->s->outputs, used_outputs, NULL); /* demotes to globals */
NIR_PASS_V(c->s, nir_lower_global_vars_to_local);
v3d_optimize_nir(c->s);
NIR_PASS_V(c->s, nir_remove_dead_variables, nir_var_shader_in);
NIR_PASS_V(c->s, nir_lower_io, nir_var_shader_in | nir_var_shader_out,
type_size_vec4,
(nir_lower_io_options)0);
}
static void
v3d_fixup_fs_output_types(struct v3d_compile *c)
{
@@ -895,9 +856,57 @@ v3d_fixup_fs_output_types(struct v3d_compile *c)
}
}
uint64_t *v3d_compile_fs(const struct v3d_compiler *compiler,
struct v3d_fs_key *key,
struct v3d_fs_prog_data *prog_data,
static void
v3d_nir_lower_fs_early(struct v3d_compile *c)
{
if (c->fs_key->int_color_rb || c->fs_key->uint_color_rb)
v3d_fixup_fs_output_types(c);
}
static void
v3d_nir_lower_vs_late(struct v3d_compile *c)
{
if (c->vs_key->clamp_color)
NIR_PASS_V(c->s, nir_lower_clamp_color_outputs);
if (c->key->ucp_enables) {
NIR_PASS_V(c->s, nir_lower_clip_vs, c->key->ucp_enables,
false);
NIR_PASS_V(c->s, nir_lower_io_to_scalar,
nir_var_shader_out);
}
/* Note: VS output scalarizing must happen after nir_lower_clip_vs. */
NIR_PASS_V(c->s, nir_lower_io_to_scalar, nir_var_shader_out);
}
static void
v3d_nir_lower_fs_late(struct v3d_compile *c)
{
if (c->fs_key->light_twoside)
NIR_PASS_V(c->s, nir_lower_two_sided_color);
if (c->fs_key->clamp_color)
NIR_PASS_V(c->s, nir_lower_clamp_color_outputs);
if (c->fs_key->alpha_test) {
NIR_PASS_V(c->s, nir_lower_alpha_test,
c->fs_key->alpha_test_func,
false);
}
if (c->key->ucp_enables)
NIR_PASS_V(c->s, nir_lower_clip_fs, c->key->ucp_enables);
/* Note: FS input scalarizing must happen after
* nir_lower_two_sided_color, which only handles a vec4 at a time.
*/
NIR_PASS_V(c->s, nir_lower_io_to_scalar, nir_var_shader_in);
}
uint64_t *v3d_compile(const struct v3d_compiler *compiler,
struct v3d_key *key,
struct v3d_prog_data **out_prog_data,
nir_shader *s,
void (*debug_output)(const char *msg,
void *debug_output_data),
@@ -905,51 +914,53 @@ uint64_t *v3d_compile_fs(const struct v3d_compiler *compiler,
int program_id, int variant_id,
uint32_t *final_assembly_size)
{
struct v3d_compile *c = vir_compile_init(compiler, &key->base, s,
struct v3d_prog_data *prog_data;
struct v3d_compile *c = vir_compile_init(compiler, key, s,
debug_output, debug_output_data,
program_id, variant_id);
c->fs_key = key;
switch (c->s->info.stage) {
case MESA_SHADER_VERTEX:
c->vs_key = (struct v3d_vs_key *)key;
prog_data = rzalloc_size(NULL, sizeof(struct v3d_vs_prog_data));
break;
case MESA_SHADER_FRAGMENT:
c->fs_key = (struct v3d_fs_key *)key;
prog_data = rzalloc_size(NULL, sizeof(struct v3d_fs_prog_data));
break;
default:
unreachable("unsupported shader stage");
}
if (key->int_color_rb || key->uint_color_rb)
v3d_fixup_fs_output_types(c);
if (c->s->info.stage == MESA_SHADER_VERTEX) {
v3d_nir_lower_vs_early(c);
} else {
assert(c->s->info.stage == MESA_SHADER_FRAGMENT);
v3d_nir_lower_fs_early(c);
}
v3d_lower_nir(c);
if (key->light_twoside)
NIR_PASS_V(c->s, nir_lower_two_sided_color);
if (key->clamp_color)
NIR_PASS_V(c->s, nir_lower_clamp_color_outputs);
if (key->alpha_test) {
NIR_PASS_V(c->s, nir_lower_alpha_test, key->alpha_test_func,
false);
if (c->s->info.stage == MESA_SHADER_VERTEX) {
v3d_nir_lower_vs_late(c);
} else {
assert(c->s->info.stage == MESA_SHADER_FRAGMENT);
v3d_nir_lower_fs_late(c);
}
if (key->base.ucp_enables)
NIR_PASS_V(c->s, nir_lower_clip_fs, key->base.ucp_enables);
NIR_PASS_V(c->s, v3d_nir_lower_io, c);
NIR_PASS_V(c->s, v3d_nir_lower_txf_ms, c);
NIR_PASS_V(c->s, nir_lower_idiv);
/* Note: FS input scalarizing must happen after
* nir_lower_two_sided_color, which only handles a vec4 at a time.
*/
NIR_PASS_V(c->s, nir_lower_io_to_scalar, nir_var_shader_in);
v3d_lower_nir_late(c);
v3d_optimize_nir(c->s);
NIR_PASS_V(c->s, nir_lower_bool_to_int32);
NIR_PASS_V(c->s, nir_convert_from_ssa, true);
v3d_nir_to_vir(c);
v3d_set_prog_data(c, &prog_data->base);
v3d_set_fs_prog_data_inputs(c, prog_data);
prog_data->writes_z = (c->s->info.outputs_written &
(1 << FRAG_RESULT_DEPTH));
prog_data->discard = (c->s->info.fs.uses_discard ||
c->fs_key->sample_alpha_to_coverage);
prog_data->uses_center_w = c->uses_center_w;
v3d_set_prog_data(c, prog_data);
*out_prog_data = prog_data;
return v3d_return_qpu_insts(c, final_assembly_size);
}

View File

@@ -354,32 +354,12 @@ v3d_get_compiled_shader(struct v3d_context *v3d, struct v3d_key *key)
uint64_t *qpu_insts;
uint32_t shader_size;
switch (s->info.stage) {
case MESA_SHADER_VERTEX:
shader->prog_data.vs = rzalloc(shader, struct v3d_vs_prog_data);
qpu_insts = v3d_compile_vs(v3d->screen->compiler,
(struct v3d_vs_key *)key,
shader->prog_data.vs, s,
qpu_insts = v3d_compile(v3d->screen->compiler, key,
&shader->prog_data.base, s,
v3d_shader_debug_output,
v3d,
program_id, variant_id,
&shader_size);
break;
case MESA_SHADER_FRAGMENT:
shader->prog_data.fs = rzalloc(shader, struct v3d_fs_prog_data);
qpu_insts = v3d_compile_fs(v3d->screen->compiler,
(struct v3d_fs_key *)key,
shader->prog_data.fs, s,
v3d_shader_debug_output,
v3d,
program_id, variant_id,
&shader_size);
break;
default:
unreachable("bad stage");
}
program_id, variant_id, &shader_size);
ralloc_steal(shader, shader->prog_data.base);
v3d_set_shader_uniform_dirty_flags(shader);