diff --git a/src/gallium/drivers/r300/compiler/nir_to_rc.c b/src/gallium/drivers/r300/compiler/nir_to_rc.c index 4cc38adca9e..bf30b02dc54 100644 --- a/src/gallium/drivers/r300/compiler/nir_to_rc.c +++ b/src/gallium/drivers/r300/compiler/nir_to_rc.c @@ -56,6 +56,7 @@ struct ntr_compile { nir_function_impl *impl; struct pipe_screen *screen; struct ureg_program *ureg; + struct r300_shader_semantics *semantics; /* Options */ bool lower_fabs; @@ -244,6 +245,59 @@ ntr_tgsi_var_usage_mask(const struct nir_variable *var) return BITFIELD_RANGE(var->data.location_frac, num_components); } +static void +ntr_read_input_output(struct ntr_compile *c, gl_varying_slot location, unsigned base) +{ + if (base >= c->semantics->num_total) + c->semantics->num_total = base + 1; + + switch (location) { + case VARYING_SLOT_POS: + if (c->s->info.stage == MESA_SHADER_VERTEX) + c->semantics->pos = base; + else + c->semantics->wpos = base; + break; + case VARYING_SLOT_PSIZ: + c->semantics->psize = base; + break; + case VARYING_SLOT_COL0: + c->semantics->color[0] = base; + break; + case VARYING_SLOT_COL1: + c->semantics->color[1] = base; + break; + case VARYING_SLOT_BFC0: + c->semantics->bcolor[0] = base; + break; + case VARYING_SLOT_BFC1: + c->semantics->bcolor[1] = base; + break; + case VARYING_SLOT_FOGC: + c->semantics->fog = base; + break; + case VARYING_SLOT_FACE: + assert(c->s->info.stage == MESA_SHADER_FRAGMENT); + c->semantics->face = base; + break; + case VARYING_SLOT_EDGE: + assert(c->s->info.stage == MESA_SHADER_VERTEX); + fprintf(stderr, "r300 VP: cannot handle edgeflag output.\n"); + break; + default: + if (location >= VARYING_SLOT_VAR0 && location <= VARYING_SLOT_VAR31) { + unsigned index = location - VARYING_SLOT_VAR0; + if (c->semantics->generic[index] == ATTR_UNUSED) + c->semantics->num_generic++; + c->semantics->generic[index] = base; + } else { + printf("Unhandled varying slot: %u\n", location); + UNREACHABLE("Unhandled varying slot"); + } + break; + } +} + static struct ureg_dst ntr_output_decl(struct ntr_compile *c, nir_intrinsic_instr *instr, uint32_t *frac) { @@ -274,6 +328,8 @@ ntr_output_decl(struct ntr_compile *c, nir_intrinsic_instr *instr, uint32_t *fra tgsi_get_gl_varying_semantic(semantics.location, true, &semantic_name, &semantic_index); + ntr_read_input_output(c, semantics.location, base); + uint32_t usage_mask = BITFIELD_RANGE(*frac, instr->num_components); out = ureg_DECL_output_layout(c->ureg, semantic_name, semantic_index, 0, base, usage_mask, 0, semantics.num_slots, false); @@ -1002,6 +1058,9 @@ ntr_emit_load_input(struct ntr_compile *c, nir_intrinsic_instr *instr) struct ureg_src input; nir_io_semantics semantics = nir_intrinsic_io_semantics(instr); + if (c->s->info.stage == MESA_SHADER_FRAGMENT) + ntr_read_input_output(c, semantics.location, base); + if (c->s->info.stage == MESA_SHADER_VERTEX) { input = ureg_DECL_vs_input(c->ureg, base); for (int i = 1; i < semantics.num_slots; i++) @@ -1787,7 +1846,8 @@ ntr_fixup_varying_slots(nir_shader *s, nir_variable_mode mode) */ const void * nir_to_rc(struct nir_shader *s, struct pipe_screen *screen, - struct r300_fragment_program_external_state state) + struct r300_fragment_program_external_state state, + union r300_shader_code rc) { struct ntr_compile *c; const void *tgsi_tokens; @@ -1795,6 +1855,11 @@ nir_to_rc(struct nir_shader *s, struct pipe_screen *screen, c = rzalloc(NULL, struct ntr_compile); c->screen = screen; c->lower_fabs = !is_r500 && s->info.stage == MESA_SHADER_VERTEX; + if (s->info.stage == MESA_SHADER_FRAGMENT) { + c->semantics = &rc.f->inputs; + } else { + c->semantics = &rc.v->outputs; + } ntr_fixup_varying_slots(s, s->info.stage == MESA_SHADER_FRAGMENT ? nir_var_shader_in : nir_var_shader_out); @@ -1971,7 +2036,6 @@ nir_to_rc(struct nir_shader *s, struct pipe_screen *screen, ureg_destroy(c->ureg); ralloc_free(c); - ralloc_free(s); return tgsi_tokens; } diff --git a/src/gallium/drivers/r300/compiler/nir_to_rc.h b/src/gallium/drivers/r300/compiler/nir_to_rc.h index da5fa64f6dd..858c31d910b 100644 --- a/src/gallium/drivers/r300/compiler/nir_to_rc.h +++ b/src/gallium/drivers/r300/compiler/nir_to_rc.h @@ -9,13 +9,22 @@ #include #include "compiler/nir/nir.h" #include "pipe/p_defines.h" +#include "r300_fs.h" +#include "r300_shader_semantics.h" +#include "r300_vs.h" struct nir_shader; struct pipe_screen; struct r300_fragment_program_external_state; +union r300_shader_code { + struct r300_fragment_shader_code *f; + struct r300_vertex_shader_code *v; +}; -const void *nir_to_rc(struct nir_shader *s, struct pipe_screen *screen, - struct r300_fragment_program_external_state state); +const void * +nir_to_rc(struct nir_shader *s, struct pipe_screen *screen, + struct r300_fragment_program_external_state state, + union r300_shader_code rc); void ntr_fixup_varying_slots(struct nir_shader *s, nir_variable_mode mode); diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index a2c3fb8ff36..ab472405288 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -26,52 +26,6 @@ #include "nir.h" #include "nir/tgsi_to_nir.h" -/* Convert info about FS input semantics to r300_shader_semantics. */ -void r300_shader_read_fs_inputs(struct tgsi_shader_info* info, - struct r300_shader_semantics* fs_inputs) -{ - int i; - unsigned index; - - r300_shader_semantics_reset(fs_inputs); - - for (i = 0; i < info->num_inputs; i++) { - index = info->input_semantic_index[i]; - - switch (info->input_semantic_name[i]) { - case TGSI_SEMANTIC_COLOR: - assert(index < ATTR_COLOR_COUNT); - fs_inputs->color[index] = i; - break; - - case TGSI_SEMANTIC_GENERIC: - assert(index < ATTR_GENERIC_COUNT); - fs_inputs->generic[index] = i; - fs_inputs->num_generic++; - break; - - case TGSI_SEMANTIC_FOG: - assert(index == 0); - fs_inputs->fog = i; - break; - - case TGSI_SEMANTIC_POSITION: - assert(index == 0); - fs_inputs->wpos = i; - break; - - case TGSI_SEMANTIC_FACE: - assert(index == 0); - fs_inputs->face = i; - break; - - default: - fprintf(stderr, "r300: FP: Unknown input semantic: %i\n", - info->input_semantic_name[i]); - } - } -} - static void find_output_registers(struct r300_fragment_program_compiler * compiler, struct r300_fragment_shader_code *shader) { @@ -412,14 +366,16 @@ static void r300_translate_fragment_shader( struct tgsi_to_rc ttr; int wpos, face; unsigned i; + union r300_shader_code code; + code.f = shader; - if (state.type == PIPE_SHADER_IR_NIR) { - nir_shader *clone = nir_shader_clone(NULL, state.ir.nir); - state.tokens = nir_to_rc(clone, (struct pipe_screen *)r300->screen, shader->compare_state); - } + r300_shader_semantics_reset(&shader->inputs); + + nir_shader *clone = nir_shader_clone(NULL, state.ir.nir); + state.tokens = nir_to_rc(clone, (struct pipe_screen *)r300->screen, shader->compare_state, + code); tgsi_scan_shader(state.tokens, &shader->info); - r300_shader_read_fs_inputs(&shader->info, &shader->inputs); wpos = shader->inputs.wpos; face = shader->inputs.face; @@ -456,13 +412,11 @@ static void r300_translate_fragment_shader( /* Translate TGSI to our internal representation */ ttr.compiler = &compiler.Base; - ttr.info = &shader->info; + ttr.shader = clone; r300_tgsi_to_rc(&ttr, state.tokens); - - if (state.type == PIPE_SHADER_IR_NIR) { - FREE((void*)state.tokens); - } + ralloc_free(clone); + FREE((void*)state.tokens); if (ttr.error) { shader->error = strdup("Cannot translate a shader from TGSI."); diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h index 82d5b59e67b..48b3cbaedea 100644 --- a/src/gallium/drivers/r300/r300_fs.h +++ b/src/gallium/drivers/r300/r300_fs.h @@ -13,6 +13,8 @@ #include "compiler/radeon_code.h" #include "r300_shader_semantics.h" +struct r300_context; + struct r300_fragment_shader_code { struct rX00_fragment_program_code code; struct tgsi_shader_info info; @@ -56,9 +58,6 @@ struct r300_fragment_shader { struct r300_fragment_shader_code* first; }; -void r300_shader_read_fs_inputs(struct tgsi_shader_info* info, - struct r300_shader_semantics* fs_inputs); - /* Return TRUE if the shader was switched and should be re-emitted. */ bool r300_pick_fragment_shader(struct r300_context *r300, struct r300_fragment_shader* fs, diff --git a/src/gallium/drivers/r300/r300_shader_semantics.h b/src/gallium/drivers/r300/r300_shader_semantics.h index a7f6db8dc72..60c21b88552 100644 --- a/src/gallium/drivers/r300/r300_shader_semantics.h +++ b/src/gallium/drivers/r300/r300_shader_semantics.h @@ -27,6 +27,9 @@ struct r300_shader_semantics { int wpos; int num_generic; + + /* Total number of used inputs/outputs. */ + unsigned num_total; }; static inline void r300_shader_semantics_reset( @@ -50,6 +53,7 @@ static inline void r300_shader_semantics_reset( } info->num_generic = 0; + info->num_total = 0; } #endif diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index f6c1968de21..e0bfeb99302 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -221,7 +221,13 @@ void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, /* Allocate constants placeholders. * * Note: What if declared constants are not contiguous? */ - for(i = 0; i <= ttr->info->file_max[TGSI_FILE_CONSTANT]; ++i) { + unsigned num_constants = 0; + nir_foreach_variable_with_modes (var, ttr->shader, nir_var_mem_ubo) { + assert(num_constants == 0); + unsigned size = glsl_get_explicit_size(var->interface_type, false); + num_constants = DIV_ROUND_UP(size, 16); + } + for(i = 0; i < num_constants; ++i) { struct rc_constant constant; memset(&constant, 0, sizeof(constant)); constant.Type = RC_CONSTANT_EXTERNAL; diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.h b/src/gallium/drivers/r300/r300_tgsi_to_rc.h index 5a9cffdad72..0026e5b5533 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.h +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.h @@ -7,6 +7,7 @@ #define R300_TGSI_TO_RC_H #include "util/compiler.h" +#include "nir/nir.h" struct radeon_compiler; @@ -21,7 +22,7 @@ struct swizzled_imms { struct tgsi_to_rc { struct radeon_compiler * compiler; - const struct tgsi_shader_info * info; + struct nir_shader * shader; int immediate_offset; diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index d097b6d5388..c23737aec14 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -90,13 +90,12 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c) { struct r300_vertex_shader_code * vs = c->UserData; struct r300_shader_semantics* outputs = &vs->outputs; - struct tgsi_shader_info* info = &vs->info; int i, reg = 0; bool any_bcolor_used = outputs->bcolor[0] != ATTR_UNUSED || outputs->bcolor[1] != ATTR_UNUSED; /* Fill in the input mapping */ - for (i = 0; i < info->num_inputs; i++) + for (i = 0; i < vs->s->num_inputs; i++) c->code->inputs[i] = i; /* Position. */ @@ -167,19 +166,24 @@ void r300_translate_vertex_shader(struct r300_context *r300, struct r300_vertex_program_compiler compiler; struct tgsi_to_rc ttr; unsigned i; + struct r300_vertex_shader_code *vs = shader->shader; + r300_shader_semantics_reset(&vs->outputs); - nir_shader *clone = nir_shader_clone(NULL, shader->state.ir.nir); + union r300_shader_code code; + code.v = vs; + + vs->s = nir_shader_clone(NULL, shader->state.ir.nir); struct r300_fragment_program_external_state external_state = {}; - shader->state.tokens = nir_to_rc(clone, (struct pipe_screen *)r300->screen, external_state); - - r300_init_vs_outputs(r300, shader); + shader->state.tokens = nir_to_rc(vs->s, (struct pipe_screen *)r300->screen, + external_state, code); + vs->outputs.wpos = vs->outputs.num_total; /* Nothing to do if the shader does not write gl_Position. */ if (vs->outputs.pos == ATTR_UNUSED) { vs->dummy = true; FREE((void*)shader->state.tokens); - return; + goto cleanup; } /* Setup the compiler */ @@ -208,7 +212,7 @@ void r300_translate_vertex_shader(struct r300_context *r300, /* Translate TGSI to our internal representation */ ttr.compiler = &compiler.Base; - ttr.info = &vs->info; + ttr.shader = vs->s; r300_tgsi_to_rc(&ttr, shader->state.tokens); FREE((void*)shader->state.tokens); @@ -216,14 +220,14 @@ void r300_translate_vertex_shader(struct r300_context *r300, if (ttr.error) { vs->error = strdup("Cannot translate shader from TGSI"); vs->dummy = true; - return; + goto cleanup; } if (compiler.Base.Program.Constants.Count > 200) { compiler.Base.remove_unused_constants = true; } - compiler.RequiredOutputs = ~(~0U << (vs->info.num_outputs + (vs->wpos ? 1 : 0))); + compiler.RequiredOutputs = ~(~0U << (vs->outputs.num_total + (vs->wpos ? 1 : 0))); compiler.SetHwInputOutput = &set_vertex_inputs_outputs; /* Insert the WPOS output. */ @@ -234,9 +238,8 @@ void r300_translate_vertex_shader(struct r300_context *r300, r3xx_compile_vertex_program(&compiler); if (compiler.Base.Error) { vs->error = strdup(compiler.Base.ErrorMsg); - rc_destroy(&compiler.Base); vs->dummy = true; - return; + goto cleanup; } /* Initialize numbers of constants for each type. */ @@ -252,5 +255,7 @@ void r300_translate_vertex_shader(struct r300_context *r300, vs->immediates_count = vs->code.constants.Count - vs->externals_count; /* And, finally... */ +cleanup: + ralloc_free(vs->s); rc_destroy(&compiler.Base); } diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index c4b6dc0bdd8..1e12a5cac96 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -20,6 +20,7 @@ struct r300_vertex_shader_code { /* Parent class */ struct tgsi_shader_info info; + struct nir_shader *s; struct r300_shader_semantics outputs; /* Whether the shader was replaced by a dummy one due to a shader