mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-06-04 15:18:15 +02:00
r300: collect input/output info directly from NIR
The NIR IO intrinsics already carry the locations and register bases used for the generated declarations, so fill r300_shader_semantics while emitting the NIR loads and stores. This removes the FS input semantic scan and lets the VS output setup use the same NIR-derived information. Track the total number of used inputs/outputs as well. Also stop depending on tgsi_info for the external constants. Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41577>
This commit is contained in:
parent
3c295e513c
commit
cb7449effb
9 changed files with 120 additions and 77 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,13 +9,22 @@
|
|||
#include <stdbool.h>
|
||||
#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);
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue