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:
Pavel Ondračka 2026-05-07 12:51:32 +02:00 committed by Marge Bot
parent e5a893c3aa
commit bbd9b31eef
10 changed files with 189 additions and 360 deletions

View file

@ -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);
}

View file

@ -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);

View file

@ -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',

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);
}

View file

@ -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 */

View file

@ -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);
}

View file

@ -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);