mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-06-04 06:38:19 +02:00
r300: emit RC instructions directly from nir_to_rc
Instead of going through the ureg / TGSI tokens / r300_tgsi_to_rc
parsing round-trip, walk the ntr_insn list and rc_constants_add /
rc_insert_new_instruction the result straight into the
radeon_compiler that the caller passes in. Translation reuses the
rc_translate_* helpers extracted in the previous commit.
Changes touching the surrounding code:
- nir_to_rc returns void and takes a struct radeon_compiler *.
- ntr_compile tracks immediates and UBO size in its own
util_dynarray instead of relying on ureg_DECL_immediate /
ureg_DECL_constant2D's bookkeeping.
- ntr_output_decl tracks the FS output color/depth indices so
nir_to_rc can populate compiler->OutputColor[] /
compiler->OutputDepth at the end - find_output_registers is gone.
- r300_translate_{fragment,vertex}_shader drop the tgsi_scan_shader
+ r300_tgsi_to_rc + ttr.error dance and switch to checking
compiler.Base.Error.
- write_all (gl_FragColor vs gl_FragData[0]) now comes from a NIR
walk in r300_translate_fragment_shader rather than reading the
TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS property.
- r300_tgsi_to_rc.{c,h} are deleted, meson.build updated, and the
obsolete header includes go away in r300_fs.c / r300_vs.c.
Assisted-by: Codex (GPT-5.5)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41577>
This commit is contained in:
parent
e5a893c3aa
commit
bbd9b31eef
10 changed files with 189 additions and 360 deletions
|
|
@ -10,6 +10,8 @@
|
|||
#include "compiler/nir/nir_legacy.h"
|
||||
#include "compiler/nir/nir_worklist.h"
|
||||
#include "compiler/radeon_code.h"
|
||||
#include "compiler/radeon_compiler.h"
|
||||
#include "compiler/radeon_program.h"
|
||||
#include "compiler/radeon_program_constants.h"
|
||||
#include "pipe/p_screen.h"
|
||||
#include "pipe/p_state.h"
|
||||
|
|
@ -47,6 +49,10 @@ struct ntr_block {
|
|||
int end_ip;
|
||||
};
|
||||
|
||||
struct ntr_immediate {
|
||||
float values[4];
|
||||
};
|
||||
|
||||
struct ntr_reg_interval {
|
||||
uint32_t start, end;
|
||||
};
|
||||
|
|
@ -93,6 +99,20 @@ struct ntr_compile {
|
|||
uint64_t centroid_inputs;
|
||||
|
||||
uint32_t first_ubo;
|
||||
|
||||
/* RC-side state for direct emission. */
|
||||
struct radeon_compiler *compiler;
|
||||
/* one struct ntr_immediate per NIR load_const */
|
||||
struct util_dynarray immediates;
|
||||
/* UBO size in vec4s (0 if no UBO) */
|
||||
unsigned ubo_size;
|
||||
/* offset for IMMEDIATE indices in the compiler's constants table */
|
||||
unsigned immediate_offset;
|
||||
|
||||
/* FS output tracking. */
|
||||
int fs_output_color_index[4];
|
||||
int fs_output_depth_index;
|
||||
unsigned num_outputs;
|
||||
};
|
||||
|
||||
static struct ureg_dst
|
||||
|
|
@ -323,6 +343,14 @@ ntr_output_decl(struct ntr_compile *c, nir_intrinsic_instr *instr, uint32_t *fra
|
|||
}
|
||||
|
||||
out = ureg_DECL_output(c->ureg, semantic_name, semantic_index);
|
||||
if (semantics.location == FRAG_RESULT_DEPTH) {
|
||||
c->fs_output_depth_index = out.Index;
|
||||
} else if (semantic_name == TGSI_SEMANTIC_COLOR &&
|
||||
semantic_index < ARRAY_SIZE(c->fs_output_color_index)) {
|
||||
c->fs_output_color_index[semantic_index] = out.Index;
|
||||
}
|
||||
if (out.Index >= c->num_outputs)
|
||||
c->num_outputs = out.Index + 1;
|
||||
} else {
|
||||
unsigned semantic_name, semantic_index;
|
||||
|
||||
|
|
@ -333,6 +361,8 @@ ntr_output_decl(struct ntr_compile *c, nir_intrinsic_instr *instr, uint32_t *fra
|
|||
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);
|
||||
if (out.Index >= c->num_outputs)
|
||||
c->num_outputs = out.Index + 1;
|
||||
}
|
||||
|
||||
unsigned write_mask;
|
||||
|
|
@ -513,7 +543,15 @@ ntr_setup_outputs(struct ntr_compile *c)
|
|||
unsigned semantic_name, semantic_index;
|
||||
tgsi_get_gl_frag_result_semantic(var->data.location, &semantic_name, &semantic_index);
|
||||
|
||||
(void)ureg_DECL_output(c->ureg, semantic_name, semantic_index);
|
||||
struct ureg_dst out = ureg_DECL_output(c->ureg, semantic_name, semantic_index);
|
||||
if (var->data.location == FRAG_RESULT_DEPTH) {
|
||||
c->fs_output_depth_index = out.Index;
|
||||
} else if (semantic_name == TGSI_SEMANTIC_COLOR &&
|
||||
semantic_index < ARRAY_SIZE(c->fs_output_color_index)) {
|
||||
c->fs_output_color_index[semantic_index] = out.Index;
|
||||
}
|
||||
if (out.Index >= c->num_outputs)
|
||||
c->num_outputs = out.Index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -590,8 +628,7 @@ ntr_setup_uniforms(struct ntr_compile *c)
|
|||
assert(ubo == 0 && size == 0);
|
||||
size = glsl_get_explicit_size(var->interface_type, false);
|
||||
}
|
||||
if (size)
|
||||
ureg_DECL_constant2D(c->ureg, 0, DIV_ROUND_UP(size, 16) - 1, 0);
|
||||
c->ubo_size = size ? DIV_ROUND_UP(size, 16) : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -630,7 +667,11 @@ ntr_get_load_const_src(struct ntr_compile *c, nir_load_const_instr *instr)
|
|||
for (int i = 0; i < num_components; i++)
|
||||
values[i] = uif(instr->value[i].u32);
|
||||
|
||||
return ureg_DECL_immediate(c->ureg, values, 4);
|
||||
unsigned index = util_dynarray_num_elements(&c->immediates, struct ntr_immediate);
|
||||
struct ntr_immediate *slot =
|
||||
util_dynarray_grow(&c->immediates, struct ntr_immediate, 1);
|
||||
memcpy(slot->values, values, sizeof(values));
|
||||
return ureg_src_register(TGSI_FILE_IMMEDIATE, index);
|
||||
}
|
||||
|
||||
static struct ureg_src
|
||||
|
|
@ -1466,14 +1507,6 @@ ntr_emit_block(struct ntr_compile *c, nir_block *block)
|
|||
|
||||
nir_foreach_instr (instr, block) {
|
||||
ntr_emit_instr(c, instr);
|
||||
|
||||
/* Sanity check that we didn't accidentally ureg_OPCODE() instead of ntr_OPCODE(). */
|
||||
if (ureg_get_instruction_number(c->ureg) != 0) {
|
||||
fprintf(stderr, "Emitted ureg insn during: ");
|
||||
nir_print_instr(instr, stderr);
|
||||
fprintf(stderr, "\n");
|
||||
UNREACHABLE("emitted ureg insn");
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the if condition for ntr_emit_if(), which we have to do before
|
||||
|
|
@ -1512,74 +1545,78 @@ ntr_emit_cf_list(struct ntr_compile *c, struct exec_list *list)
|
|||
}
|
||||
|
||||
static void
|
||||
ntr_emit_block_ureg(struct ntr_compile *c, struct nir_block *block)
|
||||
ntr_translate_dst(struct ntr_compile *c, struct rc_dst_register *rc_dst,
|
||||
struct ureg_dst src)
|
||||
{
|
||||
rc_dst->File = rc_translate_register_file(src.File);
|
||||
rc_dst->Index = src.Index;
|
||||
rc_dst->WriteMask = src.WriteMask;
|
||||
if (src.Indirect)
|
||||
rc_error(c->compiler,
|
||||
"r300: Relative addressing of destination operands is unsupported.\n");
|
||||
}
|
||||
|
||||
static void
|
||||
ntr_translate_src(struct ntr_compile *c, struct rc_src_register *rc_src,
|
||||
struct ureg_src src)
|
||||
{
|
||||
rc_src->File = rc_translate_register_file(src.File);
|
||||
int index = src.Index;
|
||||
if (src.File == TGSI_FILE_IMMEDIATE)
|
||||
index += c->immediate_offset;
|
||||
/* Negative offsets to relative addressing should have been lowered in NIR */
|
||||
assert(index >= 0);
|
||||
if (index >= RC_REGISTER_MAX_INDEX)
|
||||
rc_error(c->compiler, "r300: Register index too high.\n");
|
||||
rc_src->Index = index;
|
||||
rc_src->RelAddr = src.Indirect;
|
||||
rc_src->Swizzle = src.SwizzleX;
|
||||
rc_src->Swizzle |= src.SwizzleY << 3;
|
||||
rc_src->Swizzle |= src.SwizzleZ << 6;
|
||||
rc_src->Swizzle |= src.SwizzleW << 9;
|
||||
rc_src->Abs = src.Absolute;
|
||||
rc_src->Negate = src.Negate ? RC_MASK_XYZW : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ntr_emit_block_rc(struct ntr_compile *c, struct nir_block *block)
|
||||
{
|
||||
struct ntr_block *ntr_block = ntr_block_from_nir(c, block);
|
||||
|
||||
/* Emit the ntr insns to tgsi_ureg. */
|
||||
util_dynarray_foreach (&ntr_block->insns, struct ntr_insn, insn) {
|
||||
const struct tgsi_opcode_info *opcode_info = tgsi_get_opcode_info(insn->opcode);
|
||||
struct rc_instruction *rc_insn =
|
||||
rc_insert_new_instruction(c->compiler, c->compiler->Program.Instructions.Prev);
|
||||
|
||||
switch (insn->opcode) {
|
||||
case TGSI_OPCODE_IF:
|
||||
ureg_IF(c->ureg, insn->src[0], &c->cf_label);
|
||||
break;
|
||||
rc_insn->U.I.Opcode = rc_translate_opcode(insn->opcode);
|
||||
|
||||
case TGSI_OPCODE_ELSE:
|
||||
ureg_fixup_label(c->ureg, c->current_if_else, ureg_get_instruction_number(c->ureg));
|
||||
ureg_ELSE(c->ureg, &c->cf_label);
|
||||
c->current_if_else = c->cf_label;
|
||||
break;
|
||||
if (opcode_info->num_dst > 0) {
|
||||
rc_insn->U.I.SaturateMode = rc_translate_saturate(insn->dst[0].Saturate);
|
||||
ntr_translate_dst(c, &rc_insn->U.I.DstReg, insn->dst[0]);
|
||||
}
|
||||
|
||||
case TGSI_OPCODE_ENDIF:
|
||||
ureg_fixup_label(c->ureg, c->current_if_else, ureg_get_instruction_number(c->ureg));
|
||||
ureg_ENDIF(c->ureg);
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_BGNLOOP:
|
||||
/* GLSL-to-TGSI never set the begin/end labels to anything, even though nvfx
|
||||
* does reference BGNLOOP's. Follow the former behavior unless something comes up
|
||||
* with a need.
|
||||
*/
|
||||
ureg_BGNLOOP(c->ureg, &c->cf_label);
|
||||
break;
|
||||
|
||||
case TGSI_OPCODE_ENDLOOP:
|
||||
ureg_ENDLOOP(c->ureg, &c->cf_label);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (insn->is_tex) {
|
||||
int num_offsets = 0;
|
||||
for (int i = 0; i < ARRAY_SIZE(insn->tex_offset); i++) {
|
||||
if (insn->tex_offset[i].File != TGSI_FILE_NULL)
|
||||
num_offsets = i + 1;
|
||||
}
|
||||
ureg_tex_insn(c->ureg, insn->opcode, insn->dst, opcode_info->num_dst, insn->tex_target,
|
||||
insn->tex_offset, num_offsets, insn->src, opcode_info->num_src);
|
||||
for (unsigned i = 0; i < (unsigned)opcode_info->num_src; i++) {
|
||||
if (insn->src[i].File == TGSI_FILE_SAMPLER) {
|
||||
rc_insn->U.I.TexSrcUnit = insn->src[i].Index;
|
||||
} else {
|
||||
ureg_insn(c->ureg, insn->opcode, insn->dst, opcode_info->num_dst, insn->src,
|
||||
opcode_info->num_src, insn->precise);
|
||||
ntr_translate_src(c, &rc_insn->U.I.SrcReg[i], insn->src[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (insn->is_tex) {
|
||||
rc_insn->U.I.TexSrcTarget = rc_translate_tex_target(insn->tex_target);
|
||||
rc_insn->U.I.TexSwizzle = RC_SWIZZLE_XYZW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ntr_emit_if_ureg(struct ntr_compile *c, nir_if *if_stmt)
|
||||
ntr_emit_if_rc(struct ntr_compile *c, nir_if *if_stmt)
|
||||
{
|
||||
/* Note: the last block emitted our IF opcode. */
|
||||
|
||||
int if_stack = c->current_if_else;
|
||||
c->current_if_else = c->cf_label;
|
||||
|
||||
/* Either the then or else block includes the ENDIF, which will fix up the
|
||||
* IF(/ELSE)'s label for jumping
|
||||
*/
|
||||
/* The block before this if/else has already emitted the IF opcode into
|
||||
* our ntr_insn list. RC is structural so it doesn't need label fixups. */
|
||||
ntr_emit_cf_list_ureg(c, &if_stmt->then_list);
|
||||
ntr_emit_cf_list_ureg(c, &if_stmt->else_list);
|
||||
|
||||
c->current_if_else = if_stack;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1588,11 +1625,11 @@ ntr_emit_cf_list_ureg(struct ntr_compile *c, struct exec_list *list)
|
|||
foreach_list_typed (nir_cf_node, node, node, list) {
|
||||
switch (node->type) {
|
||||
case nir_cf_node_block:
|
||||
ntr_emit_block_ureg(c, nir_cf_node_as_block(node));
|
||||
ntr_emit_block_rc(c, nir_cf_node_as_block(node));
|
||||
break;
|
||||
|
||||
case nir_cf_node_if:
|
||||
ntr_emit_if_ureg(c, nir_cf_node_as_if(node));
|
||||
ntr_emit_if_rc(c, nir_cf_node_as_if(node));
|
||||
break;
|
||||
|
||||
case nir_cf_node_loop:
|
||||
|
|
@ -1609,6 +1646,32 @@ ntr_emit_cf_list_ureg(struct ntr_compile *c, struct exec_list *list)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ntr_add_constants(struct ntr_compile *c)
|
||||
{
|
||||
/* Add UBO constants first (they show up before immediates in the
|
||||
* compiler's constants table; the immediate offset compensates for
|
||||
* this). */
|
||||
for (unsigned i = 0; i < c->ubo_size; i++) {
|
||||
struct rc_constant constant;
|
||||
memset(&constant, 0, sizeof(constant));
|
||||
constant.Type = RC_CONSTANT_EXTERNAL;
|
||||
constant.UseMask = RC_MASK_XYZW;
|
||||
constant.u.External = i;
|
||||
rc_constants_add(&c->compiler->Program.Constants, &constant);
|
||||
}
|
||||
c->immediate_offset = c->compiler->Program.Constants.Count;
|
||||
|
||||
util_dynarray_foreach (&c->immediates, struct ntr_immediate, imm) {
|
||||
struct rc_constant constant;
|
||||
constant.Type = RC_CONSTANT_IMMEDIATE;
|
||||
constant.UseMask = RC_MASK_XYZW;
|
||||
for (unsigned j = 0; j < 4; j++)
|
||||
constant.u.Immediate[j] = imm->values[j];
|
||||
rc_constants_add(&c->compiler->Program.Constants, &constant);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ntr_emit_impl(struct ntr_compile *c, nir_function_impl *impl)
|
||||
{
|
||||
|
|
@ -1637,7 +1700,8 @@ ntr_emit_impl(struct ntr_compile *c, nir_function_impl *impl)
|
|||
|
||||
ntr_allocate_regs_unoptimized(c, impl);
|
||||
|
||||
/* Turn the ntr insns into actual TGSI tokens */
|
||||
/* Add constants and emit RC instructions directly. */
|
||||
ntr_add_constants(c);
|
||||
ntr_emit_cf_list_ureg(c, &impl->body);
|
||||
|
||||
ralloc_free(c->liveness);
|
||||
|
|
@ -1841,23 +1905,27 @@ ntr_fixup_varying_slots(nir_shader *s, nir_variable_mode mode)
|
|||
}
|
||||
|
||||
/**
|
||||
* Translates the NIR shader to TGSI.
|
||||
* Translates the NIR shader to RC instructions on the given compiler.
|
||||
*
|
||||
* This requires some lowering of the NIR shader to prepare it for translation.
|
||||
* We take ownership of the NIR shader passed, returning a reference to the new
|
||||
* TGSI tokens instead. If you need to keep the NIR, then pass us a clone.
|
||||
* This requires some lowering of the NIR shader to prepare it for
|
||||
* translation. We take ownership of the NIR shader passed; if you need to
|
||||
* keep the NIR, then pass us a clone.
|
||||
*/
|
||||
const void *
|
||||
void
|
||||
nir_to_rc(struct nir_shader *s, struct pipe_screen *screen,
|
||||
struct r300_fragment_program_external_state state,
|
||||
union r300_shader_code rc)
|
||||
union r300_shader_code rc, struct radeon_compiler *compiler)
|
||||
{
|
||||
struct ntr_compile *c;
|
||||
const void *tgsi_tokens;
|
||||
bool is_r500 = r300_screen(screen)->caps.is_r500;
|
||||
c = rzalloc(NULL, struct ntr_compile);
|
||||
c->screen = screen;
|
||||
c->compiler = compiler;
|
||||
c->lower_fabs = !is_r500 && s->info.stage == MESA_SHADER_VERTEX;
|
||||
util_dynarray_init(&c->immediates, c);
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(c->fs_output_color_index); i++)
|
||||
c->fs_output_color_index[i] = -1;
|
||||
c->fs_output_depth_index = -1;
|
||||
if (s->info.stage == MESA_SHADER_FRAGMENT) {
|
||||
c->semantics = &rc.f->inputs;
|
||||
} else {
|
||||
|
|
@ -2007,18 +2075,27 @@ nir_to_rc(struct nir_shader *s, struct pipe_screen *screen,
|
|||
/* Emit the main function */
|
||||
nir_function_impl *impl = nir_shader_get_entrypoint(c->s);
|
||||
ntr_emit_impl(c, impl);
|
||||
ureg_END(c->ureg);
|
||||
|
||||
tgsi_tokens = ureg_get_tokens(c->ureg, NULL);
|
||||
|
||||
if (NIR_DEBUG(TGSI)) {
|
||||
fprintf(stderr, "TGSI after translation from NIR:\n");
|
||||
tgsi_dump(tgsi_tokens, 0);
|
||||
/* For FS, populate the FS-specific compiler outputs. */
|
||||
if (s->info.stage == MESA_SHADER_FRAGMENT) {
|
||||
struct r300_fragment_program_compiler *fc =
|
||||
(struct r300_fragment_program_compiler *)compiler;
|
||||
rc.f->uses_discard = s->info.fs.uses_discard;
|
||||
fc->OutputDepth = c->fs_output_depth_index >= 0 ? c->fs_output_depth_index
|
||||
: c->num_outputs;
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(c->fs_output_color_index); i++) {
|
||||
fc->OutputColor[i] = c->fs_output_color_index[i] >= 0
|
||||
? c->fs_output_color_index[i]
|
||||
: c->num_outputs;
|
||||
}
|
||||
} else if (s->info.stage == MESA_SHADER_VERTEX) {
|
||||
rc.v->num_inputs = s->num_inputs;
|
||||
}
|
||||
|
||||
rc_calculate_inputs_outputs(compiler);
|
||||
|
||||
ureg_destroy(c->ureg);
|
||||
|
||||
ralloc_free(c);
|
||||
|
||||
return tgsi_tokens;
|
||||
ralloc_free(s);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,15 +21,16 @@
|
|||
struct nir_shader;
|
||||
struct pipe_screen;
|
||||
struct r300_fragment_program_external_state;
|
||||
struct radeon_compiler;
|
||||
union r300_shader_code {
|
||||
struct r300_fragment_shader_code *f;
|
||||
struct r300_vertex_shader_code *v;
|
||||
};
|
||||
|
||||
const void *
|
||||
void
|
||||
nir_to_rc(struct nir_shader *s, struct pipe_screen *screen,
|
||||
struct r300_fragment_program_external_state state,
|
||||
union r300_shader_code rc);
|
||||
union r300_shader_code rc, struct radeon_compiler *compiler);
|
||||
|
||||
void
|
||||
ntr_fixup_varying_slots(struct nir_shader *s, nir_variable_mode mode);
|
||||
|
|
|
|||
|
|
@ -36,8 +36,6 @@ files_r300 = files(
|
|||
'r300_texture_desc.c',
|
||||
'r300_texture_desc.h',
|
||||
'r300_texture.h',
|
||||
'r300_tgsi_to_rc.c',
|
||||
'r300_tgsi_to_rc.h',
|
||||
'r300_transfer.c',
|
||||
'r300_transfer.h',
|
||||
'r300_vs.c',
|
||||
|
|
|
|||
|
|
@ -18,38 +18,12 @@
|
|||
#include "r300_fs.h"
|
||||
#include "r300_reg.h"
|
||||
#include "r300_texture.h"
|
||||
#include "r300_tgsi_to_rc.h"
|
||||
|
||||
#include "compiler/radeon_compiler.h"
|
||||
#include "compiler/nir_to_rc.h"
|
||||
#include "nir.h"
|
||||
#include "compiler/nir/nir_builder.h"
|
||||
|
||||
static void find_output_registers(struct r300_fragment_program_compiler * compiler,
|
||||
struct r300_fragment_shader_code *shader)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* Mark the outputs as not present initially */
|
||||
compiler->OutputColor[0] = shader->info.num_outputs;
|
||||
compiler->OutputColor[1] = shader->info.num_outputs;
|
||||
compiler->OutputColor[2] = shader->info.num_outputs;
|
||||
compiler->OutputColor[3] = shader->info.num_outputs;
|
||||
compiler->OutputDepth = shader->info.num_outputs;
|
||||
|
||||
/* Now see where they really are. */
|
||||
for(i = 0; i < shader->info.num_outputs; ++i) {
|
||||
switch(shader->info.output_semantic_name[i]) {
|
||||
case TGSI_SEMANTIC_COLOR:
|
||||
compiler->OutputColor[shader->info.output_semantic_index[i]] = i;
|
||||
break;
|
||||
case TGSI_SEMANTIC_POSITION:
|
||||
compiler->OutputDepth = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void allocate_hardware_inputs(
|
||||
struct r300_fragment_program_compiler * c,
|
||||
void (*allocate)(void * data, unsigned input, unsigned hwreg),
|
||||
|
|
@ -356,7 +330,6 @@ static void r300_translate_fragment_shader(
|
|||
struct pipe_shader_state state)
|
||||
{
|
||||
struct r300_fragment_program_compiler compiler;
|
||||
struct tgsi_to_rc ttr;
|
||||
int wpos, face;
|
||||
unsigned i;
|
||||
union r300_shader_code code;
|
||||
|
|
@ -364,14 +337,15 @@ static void r300_translate_fragment_shader(
|
|||
|
||||
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);
|
||||
|
||||
wpos = shader->inputs.wpos;
|
||||
face = shader->inputs.face;
|
||||
/* gl_FragColor (vs. gl_FragData[0]) makes the FS write the same value
|
||||
* to all bound color buffers. */
|
||||
shader->write_all = false;
|
||||
nir_foreach_shader_out_variable(var, state.ir.nir) {
|
||||
if (var->data.location == FRAG_RESULT_COLOR) {
|
||||
shader->write_all = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup the compiler. */
|
||||
memset(&compiler, 0, sizeof(compiler));
|
||||
|
|
@ -398,25 +372,21 @@ static void r300_translate_fragment_shader(
|
|||
compiler.AllocateHwInputs = &allocate_hardware_inputs;
|
||||
compiler.UserData = &shader->inputs;
|
||||
|
||||
find_output_registers(&compiler, shader);
|
||||
nir_shader *clone = nir_shader_clone(NULL, state.ir.nir);
|
||||
nir_to_rc(clone, (struct pipe_screen *)r300->screen, shader->compare_state,
|
||||
code, &compiler.Base);
|
||||
|
||||
shader->write_all =
|
||||
shader->info.properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS];
|
||||
|
||||
/* Translate TGSI to our internal representation */
|
||||
ttr.compiler = &compiler.Base;
|
||||
ttr.shader = clone;
|
||||
|
||||
r300_tgsi_to_rc(&ttr, state.tokens);
|
||||
ralloc_free(clone);
|
||||
FREE((void*)state.tokens);
|
||||
|
||||
if (ttr.error) {
|
||||
shader->error = strdup("Cannot translate a shader from TGSI.");
|
||||
if (compiler.Base.Error) {
|
||||
shader->error = strdup(compiler.Base.ErrorMsg ? compiler.Base.ErrorMsg
|
||||
: "Cannot translate shader from NIR.");
|
||||
rc_destroy(&compiler.Base);
|
||||
r300_dummy_fragment_shader(r300, shader);
|
||||
return;
|
||||
}
|
||||
|
||||
wpos = shader->inputs.wpos;
|
||||
face = shader->inputs.face;
|
||||
|
||||
if (!r300->screen->caps.is_r500 ||
|
||||
compiler.Base.Program.Constants.Count > 200) {
|
||||
compiler.Base.remove_unused_constants = true;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
#define R300_FS_H
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "tgsi/tgsi_scan.h"
|
||||
#include "compiler/radeon_code.h"
|
||||
#include "r300_shader_semantics.h"
|
||||
|
||||
|
|
@ -17,7 +16,6 @@ struct r300_context;
|
|||
|
||||
struct r300_fragment_shader_code {
|
||||
struct rX00_fragment_program_code code;
|
||||
struct tgsi_shader_info info;
|
||||
struct r300_shader_semantics inputs;
|
||||
|
||||
/* Whether the shader was replaced by a dummy one due to a shader
|
||||
|
|
@ -41,6 +39,7 @@ struct r300_fragment_shader_code {
|
|||
struct r300_fragment_shader_code* next;
|
||||
|
||||
bool write_all;
|
||||
bool uses_discard;
|
||||
|
||||
/* Error message in case compilation failed. */
|
||||
char *error;
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ static void r300_update_ztop(struct r300_context* r300)
|
|||
/* ZS writes */
|
||||
if (util_writes_depth_stencil(r300->dsa_state.state) &&
|
||||
(r300_dsa_alpha_test_enabled(r300->dsa_state.state) || /* (1) */
|
||||
r300_fs(r300)->shader->info.uses_kill)) { /* (2) */
|
||||
r300_fs(r300)->shader->uses_discard)) { /* (2) */
|
||||
ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
|
||||
} else if (r300_fragment_shader_writes_depth(r300_fs(r300))) { /* (5) */
|
||||
ztop_state->z_buffer_top = R300_ZTOP_DISABLE;
|
||||
|
|
|
|||
|
|
@ -1,169 +0,0 @@
|
|||
/*
|
||||
* Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "r300_tgsi_to_rc.h"
|
||||
|
||||
#include "compiler/nir_to_rc.h"
|
||||
#include "compiler/radeon_compiler.h"
|
||||
|
||||
#include "tgsi/tgsi_info.h"
|
||||
#include "tgsi/tgsi_parse.h"
|
||||
#include "tgsi/tgsi_scan.h"
|
||||
#include "tgsi/tgsi_util.h"
|
||||
|
||||
#include "util/compiler.h"
|
||||
|
||||
static int translate_register_index(
|
||||
struct tgsi_to_rc * ttr,
|
||||
unsigned file,
|
||||
int index)
|
||||
{
|
||||
if (file == TGSI_FILE_IMMEDIATE)
|
||||
return ttr->immediate_offset + index;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
static void transform_dstreg(
|
||||
struct tgsi_to_rc * ttr,
|
||||
struct rc_dst_register * dst,
|
||||
struct tgsi_full_dst_register * src)
|
||||
{
|
||||
dst->File = rc_translate_register_file(src->Register.File);
|
||||
dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index);
|
||||
dst->WriteMask = src->Register.WriteMask;
|
||||
|
||||
if (src->Register.Indirect) {
|
||||
ttr->error = true;
|
||||
fprintf(stderr, "r300: Relative addressing of destination operands "
|
||||
"is unsupported.\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void transform_srcreg(
|
||||
struct tgsi_to_rc * ttr,
|
||||
struct rc_src_register * dst,
|
||||
struct tgsi_full_src_register * src)
|
||||
{
|
||||
dst->File = rc_translate_register_file(src->Register.File);
|
||||
int index = translate_register_index(ttr, src->Register.File, src->Register.Index);
|
||||
/* Negative offsets to relative addressing should have been lowered in NIR */
|
||||
assert(index >= 0);
|
||||
/* Also check for overflow */
|
||||
if (index >= RC_REGISTER_MAX_INDEX) {
|
||||
ttr->error = true;
|
||||
fprintf(stderr, "r300: Register index too high.\n");
|
||||
}
|
||||
dst->Index = index;
|
||||
dst->RelAddr = src->Register.Indirect;
|
||||
dst->Swizzle = tgsi_util_get_full_src_register_swizzle(src, 0);
|
||||
dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 1) << 3;
|
||||
dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 2) << 6;
|
||||
dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 3) << 9;
|
||||
dst->Abs = src->Register.Absolute;
|
||||
dst->Negate = src->Register.Negate ? RC_MASK_XYZW : 0;
|
||||
}
|
||||
|
||||
static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_texture src)
|
||||
{
|
||||
dst->U.I.TexSrcTarget = rc_translate_tex_target(src.Texture);
|
||||
dst->U.I.TexSwizzle = RC_SWIZZLE_XYZW;
|
||||
}
|
||||
|
||||
static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_instruction * src)
|
||||
{
|
||||
struct rc_instruction * dst;
|
||||
int i;
|
||||
|
||||
dst = rc_insert_new_instruction(ttr->compiler, ttr->compiler->Program.Instructions.Prev);
|
||||
dst->U.I.Opcode = rc_translate_opcode(src->Instruction.Opcode);
|
||||
dst->U.I.SaturateMode = rc_translate_saturate(src->Instruction.Saturate);
|
||||
|
||||
if (src->Instruction.NumDstRegs)
|
||||
transform_dstreg(ttr, &dst->U.I.DstReg, &src->Dst[0]);
|
||||
|
||||
for(i = 0; i < src->Instruction.NumSrcRegs; ++i) {
|
||||
if (src->Src[i].Register.File == TGSI_FILE_SAMPLER)
|
||||
dst->U.I.TexSrcUnit = src->Src[i].Register.Index;
|
||||
else
|
||||
transform_srcreg(ttr, &dst->U.I.SrcReg[i], &src->Src[i]);
|
||||
}
|
||||
|
||||
/* Texturing. */
|
||||
if (src->Instruction.Texture)
|
||||
transform_texture(dst, src->Texture);
|
||||
}
|
||||
|
||||
static void handle_immediate(struct tgsi_to_rc * ttr,
|
||||
struct tgsi_full_immediate * imm,
|
||||
unsigned index)
|
||||
{
|
||||
struct rc_constant constant;
|
||||
|
||||
constant.Type = RC_CONSTANT_IMMEDIATE;
|
||||
constant.UseMask = RC_MASK_XYZW;
|
||||
for (unsigned i = 0; i < 4; ++i)
|
||||
constant.u.Immediate[i] = imm->u[i].Float;
|
||||
rc_constants_add(&ttr->compiler->Program.Constants, &constant);
|
||||
}
|
||||
|
||||
void r300_tgsi_to_rc(struct tgsi_to_rc * ttr,
|
||||
const struct tgsi_token * tokens)
|
||||
{
|
||||
struct tgsi_full_instruction *inst;
|
||||
struct tgsi_parse_context parser;
|
||||
unsigned imm_index = 0;
|
||||
int i;
|
||||
|
||||
ttr->error = false;
|
||||
|
||||
/* Allocate constants placeholders.
|
||||
*
|
||||
* Note: What if declared constants are not contiguous? */
|
||||
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;
|
||||
constant.UseMask = RC_MASK_XYZW;
|
||||
constant.u.External = i;
|
||||
rc_constants_add(&ttr->compiler->Program.Constants, &constant);
|
||||
}
|
||||
|
||||
ttr->immediate_offset = ttr->compiler->Program.Constants.Count;
|
||||
|
||||
tgsi_parse_init(&parser, tokens);
|
||||
|
||||
while (!tgsi_parse_end_of_tokens(&parser)) {
|
||||
tgsi_parse_token(&parser);
|
||||
|
||||
switch (parser.FullToken.Token.Type) {
|
||||
case TGSI_TOKEN_TYPE_DECLARATION:
|
||||
break;
|
||||
case TGSI_TOKEN_TYPE_IMMEDIATE:
|
||||
handle_immediate(ttr, &parser.FullToken.FullImmediate, imm_index);
|
||||
imm_index++;
|
||||
break;
|
||||
case TGSI_TOKEN_TYPE_INSTRUCTION:
|
||||
inst = &parser.FullToken.FullInstruction;
|
||||
if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
|
||||
break;
|
||||
}
|
||||
|
||||
transform_instruction(ttr, inst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tgsi_parse_free(&parser);
|
||||
|
||||
rc_calculate_inputs_outputs(ttr->compiler);
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef R300_TGSI_TO_RC_H
|
||||
#define R300_TGSI_TO_RC_H
|
||||
|
||||
#include "util/compiler.h"
|
||||
#include "nir/nir.h"
|
||||
|
||||
struct radeon_compiler;
|
||||
|
||||
struct tgsi_full_declaration;
|
||||
struct tgsi_shader_info;
|
||||
struct tgsi_token;
|
||||
|
||||
struct swizzled_imms {
|
||||
unsigned index;
|
||||
unsigned swizzle;
|
||||
};
|
||||
|
||||
struct tgsi_to_rc {
|
||||
struct radeon_compiler * compiler;
|
||||
struct nir_shader * shader;
|
||||
|
||||
int immediate_offset;
|
||||
|
||||
/* If an error occurred. */
|
||||
bool error;
|
||||
};
|
||||
|
||||
void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens);
|
||||
|
||||
#endif /* R300_TGSI_TO_RC_H */
|
||||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include "r300_context.h"
|
||||
#include "r300_screen.h"
|
||||
#include "r300_tgsi_to_rc.h"
|
||||
#include "r300_reg.h"
|
||||
|
||||
#include "tgsi/tgsi_dump.h"
|
||||
|
|
@ -95,7 +94,7 @@ static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
|
|||
outputs->bcolor[1] != ATTR_UNUSED;
|
||||
|
||||
/* Fill in the input mapping */
|
||||
for (i = 0; i < vs->s->num_inputs; i++)
|
||||
for (i = 0; i < vs->num_inputs; i++)
|
||||
c->code->inputs[i] = i;
|
||||
|
||||
/* Position. */
|
||||
|
|
@ -193,7 +192,6 @@ void r300_translate_vertex_shader(struct r300_context *r300,
|
|||
struct r300_vertex_shader *shader)
|
||||
{
|
||||
struct r300_vertex_program_compiler compiler;
|
||||
struct tgsi_to_rc ttr;
|
||||
unsigned i;
|
||||
|
||||
struct r300_vertex_shader_code *vs = shader->shader;
|
||||
|
|
@ -204,28 +202,21 @@ void r300_translate_vertex_shader(struct r300_context *r300,
|
|||
|
||||
r300_setup_vs_compiler(r300, &compiler, vs);
|
||||
|
||||
vs->s = nir_shader_clone(NULL, shader->state.ir.nir);
|
||||
nir_shader *clone = nir_shader_clone(NULL, shader->state.ir.nir);
|
||||
struct r300_fragment_program_external_state external_state = {};
|
||||
shader->state.tokens = nir_to_rc(vs->s, (struct pipe_screen *)r300->screen,
|
||||
external_state, code);
|
||||
nir_to_rc(clone, (struct pipe_screen *)r300->screen,
|
||||
external_state, code, &compiler.Base);
|
||||
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);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Translate TGSI to our internal representation */
|
||||
ttr.compiler = &compiler.Base;
|
||||
ttr.shader = vs->s;
|
||||
|
||||
r300_tgsi_to_rc(&ttr, shader->state.tokens);
|
||||
FREE((void*)shader->state.tokens);
|
||||
|
||||
if (ttr.error) {
|
||||
vs->error = strdup("Cannot translate shader from TGSI");
|
||||
if (compiler.Base.Error) {
|
||||
vs->error = strdup(compiler.Base.ErrorMsg ? compiler.Base.ErrorMsg
|
||||
: "Cannot translate shader from NIR");
|
||||
vs->dummy = true;
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -263,6 +254,5 @@ void r300_translate_vertex_shader(struct r300_context *r300,
|
|||
|
||||
/* And, finally... */
|
||||
cleanup:
|
||||
ralloc_free(vs->s);
|
||||
rc_destroy(&compiler.Base);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ struct r300_vertex_shader_code {
|
|||
/* Parent class */
|
||||
|
||||
struct tgsi_shader_info info;
|
||||
struct nir_shader *s;
|
||||
unsigned num_inputs;
|
||||
struct r300_shader_semantics outputs;
|
||||
|
||||
/* Whether the shader was replaced by a dummy one due to a shader
|
||||
|
|
@ -57,8 +57,6 @@ struct r300_vertex_shader {
|
|||
void *draw_vs;
|
||||
};
|
||||
|
||||
struct nir_shader;
|
||||
|
||||
void r300_init_vs_outputs(struct r300_context *r300,
|
||||
struct r300_vertex_shader *vs);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue