From bbd9b31eeff304bce1435490004f47fc7b7994a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Ondra=C4=8Dka?= Date: Thu, 7 May 2026 12:51:32 +0200 Subject: [PATCH] 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: --- src/gallium/drivers/r300/compiler/nir_to_rc.c | 237 ++++++++++++------ src/gallium/drivers/r300/compiler/nir_to_rc.h | 5 +- src/gallium/drivers/r300/meson.build | 2 - src/gallium/drivers/r300/r300_fs.c | 68 ++--- src/gallium/drivers/r300/r300_fs.h | 3 +- src/gallium/drivers/r300/r300_hyperz.c | 2 +- src/gallium/drivers/r300/r300_tgsi_to_rc.c | 169 ------------- src/gallium/drivers/r300/r300_tgsi_to_rc.h | 35 --- src/gallium/drivers/r300/r300_vs.c | 24 +- src/gallium/drivers/r300/r300_vs.h | 4 +- 10 files changed, 189 insertions(+), 360 deletions(-) delete mode 100644 src/gallium/drivers/r300/r300_tgsi_to_rc.c delete mode 100644 src/gallium/drivers/r300/r300_tgsi_to_rc.h diff --git a/src/gallium/drivers/r300/compiler/nir_to_rc.c b/src/gallium/drivers/r300/compiler/nir_to_rc.c index e631e78fd4b..950f1dc7643 100644 --- a/src/gallium/drivers/r300/compiler/nir_to_rc.c +++ b/src/gallium/drivers/r300/compiler/nir_to_rc.c @@ -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); } diff --git a/src/gallium/drivers/r300/compiler/nir_to_rc.h b/src/gallium/drivers/r300/compiler/nir_to_rc.h index c55964c7731..6a388db7bd1 100644 --- a/src/gallium/drivers/r300/compiler/nir_to_rc.h +++ b/src/gallium/drivers/r300/compiler/nir_to_rc.h @@ -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); diff --git a/src/gallium/drivers/r300/meson.build b/src/gallium/drivers/r300/meson.build index 402b8d15f88..51f75e09b01 100644 --- a/src/gallium/drivers/r300/meson.build +++ b/src/gallium/drivers/r300/meson.build @@ -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', diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 58e1a520485..79a3cf997a4 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.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; diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h index 48b3cbaedea..b836a786c5e 100644 --- a/src/gallium/drivers/r300/r300_fs.h +++ b/src/gallium/drivers/r300/r300_fs.h @@ -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; diff --git a/src/gallium/drivers/r300/r300_hyperz.c b/src/gallium/drivers/r300/r300_hyperz.c index 6e9cd800c0d..ddec6f3eadb 100644 --- a/src/gallium/drivers/r300/r300_hyperz.c +++ b/src/gallium/drivers/r300/r300_hyperz.c @@ -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; diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c deleted file mode 100644 index b62c66d1a9a..00000000000 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2009 Nicolai Hähnle - * SPDX-License-Identifier: MIT - */ - -#include -#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); -} diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.h b/src/gallium/drivers/r300/r300_tgsi_to_rc.h deleted file mode 100644 index 0026e5b5533..00000000000 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2009 Nicolai Hähnle - * 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 */ diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c index 4612c1aa4bf..f5721fa2311 100644 --- a/src/gallium/drivers/r300/r300_vs.c +++ b/src/gallium/drivers/r300/r300_vs.c @@ -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); } diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h index 1e12a5cac96..7a7441f5b0d 100644 --- a/src/gallium/drivers/r300/r300_vs.h +++ b/src/gallium/drivers/r300/r300_vs.h @@ -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);