From d0c398a8e2985b855f923aec3470cef8734a622a Mon Sep 17 00:00:00 2001 From: Nicolai Hähnle Date: Thu, 30 Jul 2009 23:45:34 +0200 Subject: r300g: Use radeon compiler for fragment programs This is entirely untested on R500, and needs more testing on R300. --- src/gallium/drivers/r300/Makefile | 1 - src/gallium/drivers/r300/r300_context.h | 60 +-- src/gallium/drivers/r300/r300_debug.c | 228 ----------- src/gallium/drivers/r300/r300_debug.h | 35 -- src/gallium/drivers/r300/r300_emit.c | 216 +++++++---- src/gallium/drivers/r300/r300_emit.h | 11 +- src/gallium/drivers/r300/r300_fs.c | 162 ++++---- src/gallium/drivers/r300/r300_fs.h | 15 + src/gallium/drivers/r300/r300_fs_inlines.h | 158 -------- src/gallium/drivers/r300/r300_state.c | 23 +- src/gallium/drivers/r300/r300_state_derived.c | 1 + src/gallium/drivers/r300/r300_surface.c | 8 +- src/gallium/drivers/r300/r300_tgsi_to_rc.c | 44 ++- src/gallium/drivers/r300/r3xx_fs.c | 100 ++--- src/gallium/drivers/r300/r3xx_fs.h | 52 +-- src/gallium/drivers/r300/r5xx_fs.c | 540 +++++--------------------- src/gallium/drivers/r300/r5xx_fs.h | 108 +----- 17 files changed, 450 insertions(+), 1312 deletions(-) delete mode 100644 src/gallium/drivers/r300/r300_debug.c delete mode 100644 src/gallium/drivers/r300/r300_debug.h delete mode 100644 src/gallium/drivers/r300/r300_fs_inlines.h (limited to 'src/gallium/drivers/r300') diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index 93c2152edc..d7a2c8c462 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -9,7 +9,6 @@ C_SOURCES = \ r300_chipset.c \ r300_clear.c \ r300_context.c \ - r300_debug.c \ r300_emit.c \ r300_flush.c \ r300_fs.c \ diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index c1ef64e4ee..6984225967 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -34,6 +34,7 @@ #include "r300_screen.h" #include "r300_winsys.h" +struct r300_fragment_shader; struct r300_vertex_shader; struct r300_blend_state { @@ -151,65 +152,6 @@ struct r300_constant_buffer { unsigned count; }; -struct r300_fragment_shader { - /* Parent class */ - struct pipe_shader_state state; - struct tgsi_shader_info info; - - /* Has this shader been translated yet? */ - boolean translated; - - /* Pixel stack size */ - int stack_size; - - /* Are there immediates in this shader? - * If not, we can heavily optimize recompilation. */ - boolean uses_imms; -}; - -struct r3xx_fragment_shader { - /* Parent class */ - struct r300_fragment_shader shader; - - /* Number of ALU instructions */ - int alu_instruction_count; - - /* Number of texture instructions */ - int tex_instruction_count; - - /* Number of texture indirections */ - int indirections; - - /* Indirection node offsets */ - int alu_offset[4]; - - /* Machine instructions */ - struct { - uint32_t alu_rgb_inst; - uint32_t alu_rgb_addr; - uint32_t alu_alpha_inst; - uint32_t alu_alpha_addr; - } instructions[64]; /* XXX magic num */ -}; - -struct r5xx_fragment_shader { - /* Parent class */ - struct r300_fragment_shader shader; - - /* Number of used instructions */ - int instruction_count; - - /* Machine instructions */ - struct { - uint32_t inst0; - uint32_t inst1; - uint32_t inst2; - uint32_t inst3; - uint32_t inst4; - uint32_t inst5; - } instructions[256]; /*< XXX magic number */ -}; - struct r300_texture { /* Parent class */ struct pipe_texture tex; diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c deleted file mode 100644 index aae8a4fbde..0000000000 --- a/src/gallium/drivers/r300/r300_debug.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2009 Corbin Simpson - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#include "r300_debug.h" - - -static char* r5xx_fs_swiz[] = { - " R", - " G", - " B", - " A", - " 0", - ".5", - " 1", - " U", -}; - -static char* r5xx_fs_op_rgb[] = { - "MAD", - "DP3", - "DP4", - "D2A", - "MIN", - "MAX", - "---", - "CND", - "CMP", - "FRC", - "SOP", - "MDH", - "MDV", -}; - -static char* r5xx_fs_op_alpha[] = { - "MAD", - " DP", - "MIN", - "MAX", - "---", - "CND", - "CMP", - "FRC", - "EX2", - "LN2", - "RCP", - "RSQ", - "SIN", - "COS", - "MDH", - "MDV", -}; - -static char* r5xx_fs_mask[] = { - "NONE", - "R ", - " G ", - "RG ", - " B ", - "R B ", - " GB ", - "RGB ", - " A", - "R A", - " G A", - "RG A", - " BA", - "R BA", - " GBA", - "RGBA", -}; - -static char* r5xx_fs_tex[] = { - " NOP", - " LD", - "TEXKILL", - " PROJ", - "LODBIAS", - " LOD", - " DXDY", -}; - - -void r3xx_dump_fs(struct r3xx_fragment_shader* fs) -{ - int i; - - for (i = 0; i < fs->alu_instruction_count; i++) { - } -} - -void r5xx_fs_dump(struct r5xx_fragment_shader* fs) -{ - int i; - uint32_t inst; - - for (i = 0; i < fs->instruction_count; i++) { - inst = fs->instructions[i].inst0; - debug_printf("%d: 0: CMN_INST 0x%08x:", i, inst); - switch (inst & 0x3) { - case R500_INST_TYPE_ALU: - debug_printf("ALU "); - break; - case R500_INST_TYPE_OUT: - debug_printf("OUT "); - break; - case R500_INST_TYPE_FC: - debug_printf("FC "); - break; - case R500_INST_TYPE_TEX: - debug_printf("TEX "); - break; - } - debug_printf("%s %s %s %s ", - inst & R500_INST_TEX_SEM_WAIT ? "TEX_WAIT" : "", - inst & R500_INST_LAST ? "LAST" : "", - inst & R500_INST_NOP ? "NOP" : "", - inst & R500_INST_ALU_WAIT ? "ALU_WAIT" : ""); - debug_printf("wmask: %s omask: %s\n", - r5xx_fs_mask[(inst >> 11) & 0xf], - r5xx_fs_mask[(inst >> 15) & 0xf]); - switch (inst & 0x3) { - case R500_INST_TYPE_ALU: - case R500_INST_TYPE_OUT: - inst = fs->instructions[i].inst1; - debug_printf(" 1: RGB_ADDR 0x%08x:", inst); - debug_printf("Addr0: %d%c, Addr1: %d%c, " - "Addr2: %d%c, srcp:%d\n", - inst & 0xff, (inst & (1 << 8)) ? 'c' : 't', - (inst >> 10) & 0xff, (inst & (1 << 18)) ? 'c' : 't', - (inst >> 20) & 0xff, (inst & (1 << 28)) ? 'c' : 't', - (inst >> 30)); - - inst = fs->instructions[i].inst2; - debug_printf(" 2: ALPHA_ADDR 0x%08x:", inst); - debug_printf("Addr0: %d%c, Addr1: %d%c, " - "Addr2: %d%c, srcp:%d\n", - inst & 0xff, (inst & (1 << 8)) ? 'c' : 't', - (inst >> 10) & 0xff, (inst & (1 << 18)) ? 'c' : 't', - (inst >> 20) & 0xff, (inst & (1 << 28)) ? 'c' : 't', - (inst >> 30)); - - inst = fs->instructions[i].inst3; - debug_printf(" 3: RGB_INST 0x%08x:", inst); - debug_printf("rgb_A_src:%d %s/%s/%s %d " - "rgb_B_src:%d %s/%s/%s %d\n", - inst & 0x3, r5xx_fs_swiz[(inst >> 2) & 0x7], - r5xx_fs_swiz[(inst >> 5) & 0x7], - r5xx_fs_swiz[(inst >> 8) & 0x7], - (inst >> 11) & 0x3, (inst >> 13) & 0x3, - r5xx_fs_swiz[(inst >> 15) & 0x7], - r5xx_fs_swiz[(inst >> 18) & 0x7], - r5xx_fs_swiz[(inst >> 21) & 0x7], - (inst >> 24) & 0x3); - - inst = fs->instructions[i].inst4; - debug_printf(" 4: ALPHA_INST 0x%08x:", inst); - debug_printf("%s dest:%d%s alp_A_src:%d %s %d " - "alp_B_src:%d %s %d w:%d\n", - r5xx_fs_op_alpha[inst & 0xf], (inst >> 4) & 0x7f, - inst & (1<<11) ? "(rel)":"", (inst >> 12) & 0x3, - r5xx_fs_swiz[(inst >> 14) & 0x7], (inst >> 17) & 0x3, - (inst >> 19) & 0x3, r5xx_fs_swiz[(inst >> 21) & 0x7], - (inst >> 24) & 0x3, (inst >> 31) & 0x1); - - inst = fs->instructions[i].inst5; - debug_printf(" 5: RGBA_INST 0x%08x:", inst); - debug_printf("%s dest:%d%s rgb_C_src:%d %s/%s/%s %d " - "alp_C_src:%d %s %d\n", - r5xx_fs_op_rgb[inst & 0xf], (inst >> 4) & 0x7f, - inst & (1 << 11) ? "(rel)":"", (inst >> 12) & 0x3, - r5xx_fs_swiz[(inst >> 14) & 0x7], - r5xx_fs_swiz[(inst >> 17) & 0x7], - r5xx_fs_swiz[(inst >> 20) & 0x7], - (inst >> 23) & 0x3, (inst >> 25) & 0x3, - r5xx_fs_swiz[(inst >> 27) & 0x7], (inst >> 30) & 0x3); - break; - case R500_INST_TYPE_FC: - /* XXX don't even bother yet */ - break; - case R500_INST_TYPE_TEX: - inst = fs->instructions[i].inst1; - debug_printf(" 1: TEX_INST 0x%08x: id: %d " - "op:%s, %s, %s %s\n", - inst, (inst >> 16) & 0xf, - r5xx_fs_tex[(inst >> 22) & 0x7], - (inst & (1 << 25)) ? "ACQ" : "", - (inst & (1 << 26)) ? "IGNUNC" : "", - (inst & (1 << 27)) ? "UNSCALED" : "SCALED"); - - inst = fs->instructions[i].inst2; - debug_printf(" 2: TEX_ADDR 0x%08x: " - "src: %d%s %s/%s/%s/%s dst: %d%s %s/%s/%s/%s\n", - inst, inst & 0x7f, inst & (1 << 7) ? "(rel)" : "", - r5xx_fs_swiz[(inst >> 8) & 0x3], - r5xx_fs_swiz[(inst >> 10) & 0x3], - r5xx_fs_swiz[(inst >> 12) & 0x3], - r5xx_fs_swiz[(inst >> 14) & 0x3], - (inst >> 16) & 0x7f, inst & (1 << 23) ? "(rel)" : "", - r5xx_fs_swiz[(inst >> 24) & 0x3], - r5xx_fs_swiz[(inst >> 26) & 0x3], - r5xx_fs_swiz[(inst >> 28) & 0x3], - r5xx_fs_swiz[(inst >> 30) & 0x3]); - - inst = fs->instructions[i].inst3; - debug_printf(" 3: TEX_DXDY 0x%08x\n", inst); - break; - } - } -} diff --git a/src/gallium/drivers/r300/r300_debug.h b/src/gallium/drivers/r300/r300_debug.h deleted file mode 100644 index c551bd548e..0000000000 --- a/src/gallium/drivers/r300/r300_debug.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2009 Corbin Simpson - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef R300_DEBUG_H -#define R300_DEBUG_H - -#include "r300_reg.h" -#include "r300_fs.h" -#include "r300_vs.h" - -void r5xx_fs_dump(struct r5xx_fragment_shader* fs); -void r3xx_dump_fs(struct r3xx_fragment_shader* fs); - -void r300_vs_dump(struct r300_vertex_shader* vs); - -#endif /* R300_DEBUG_H */ diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index e9ca4ac662..e0c38a06e4 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -24,6 +24,7 @@ #include "r300_emit.h" +#include "r300_fs.h" #include "r300_vs.h" void r300_emit_blend_state(struct r300_context* r300, @@ -111,73 +112,158 @@ void r300_emit_dsa_state(struct r300_context* r300, END_CS; } -void r300_emit_fragment_shader(struct r300_context* r300, - struct r3xx_fragment_shader* fs) +static const float * get_shader_constant( + struct r300_context * r300, + struct rc_constant * constant, + struct r300_constant_buffer * externals) +{ + static const float zero[4] = { 0.0, 0.0, 0.0, 0.0 }; + switch(constant->Type) { + case RC_CONSTANT_EXTERNAL: + return externals->constants[constant->u.External]; + + case RC_CONSTANT_IMMEDIATE: + return constant->u.Immediate; + + default: + debug_printf("r300: Implementation error: Unhandled constant type %i\n", + constant->Type); + return zero; + } +} + +/* Convert a normal single-precision float into the 7.16 format + * used by the R300 fragment shader. + */ +static uint32_t pack_float24(float f) +{ + union { + float fl; + uint32_t u; + } u; + float mantissa; + int exponent; + uint32_t float24 = 0; + + if (f == 0.0) + return 0; + + u.fl = f; + + mantissa = frexpf(f, &exponent); + + /* Handle -ve */ + if (mantissa < 0) { + float24 |= (1 << 23); + mantissa = mantissa * -1.0; + } + /* Handle exponent, bias of 63 */ + exponent += 62; + float24 |= (exponent << 16); + /* Kill 7 LSB of mantissa */ + float24 |= (u.u & 0x7FFFFF) >> 7; + + return float24; +} + +void r300_emit_fragment_program_code(struct r300_context* r300, + struct rX00_fragment_program_code* generic_code, + struct r300_constant_buffer* externals) { + struct r300_fragment_program_code * code = &generic_code->code.r300; + struct rc_constant_list * constants = &generic_code->constants; int i; CS_LOCALS(r300); - BEGIN_CS(22); - - OUT_CS_REG(R300_US_CONFIG, fs->indirections); - OUT_CS_REG(R300_US_PIXSIZE, fs->shader.stack_size); - /* XXX figure out exactly how big the sizes are on this reg */ - OUT_CS_REG(R300_US_CODE_OFFSET, 0x40); - /* XXX figure these ones out a bit better kthnx */ - OUT_CS_REG(R300_US_CODE_ADDR_0, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_1, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_2, 0x0); - OUT_CS_REG(R300_US_CODE_ADDR_3, 0x40 | R300_RGBA_OUT); - - for (i = 0; i < fs->alu_instruction_count; i++) { - OUT_CS_REG(R300_US_ALU_RGB_INST_0 + (4 * i), - fs->instructions[i].alu_rgb_inst); - OUT_CS_REG(R300_US_ALU_RGB_ADDR_0 + (4 * i), - fs->instructions[i].alu_rgb_addr); - OUT_CS_REG(R300_US_ALU_ALPHA_INST_0 + (4 * i), - fs->instructions[i].alu_alpha_inst); - OUT_CS_REG(R300_US_ALU_ALPHA_ADDR_0 + (4 * i), - fs->instructions[i].alu_alpha_addr); + BEGIN_CS(15 + + code->alu.length * 4 + + (code->tex.length ? (1 + code->tex.length) : 0) + + (constants->Count ? (1 + constants->Count * 4) : 0)); + + OUT_CS_REG(R300_US_CONFIG, code->config); + OUT_CS_REG(R300_US_PIXSIZE, code->pixsize); + OUT_CS_REG(R300_US_CODE_OFFSET, code->code_offset); + + OUT_CS_REG_SEQ(R300_US_CODE_ADDR_0, 4); + for(i = 0; i < 4; ++i) + OUT_CS(code->code_addr[i]); + + OUT_CS_REG_SEQ(R300_US_ALU_RGB_INST_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CS(code->alu.inst[i].rgb_inst); + + OUT_CS_REG_SEQ(R300_US_ALU_RGB_ADDR_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CS(code->alu.inst[i].rgb_addr); + + OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_INST_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CS(code->alu.inst[i].alpha_inst); + + OUT_CS_REG_SEQ(R300_US_ALU_ALPHA_ADDR_0, code->alu.length); + for (i = 0; i < code->alu.length; i++) + OUT_CS(code->alu.inst[i].alpha_addr); + + if (code->tex.length) { + OUT_CS_REG_SEQ(R300_US_TEX_INST_0, code->tex.length); + for(i = 0; i < code->tex.length; ++i) + OUT_CS(code->tex.inst[i]); + } + + if (constants->Count) { + OUT_CS_ONE_REG(R300_PFS_PARAM_0_X, constants->Count * 4); + for(i = 0; i < constants->Count; ++i) { + const float * data = get_shader_constant(r300, &constants->Constants[i], externals); + OUT_CS(pack_float24(data[0])); + OUT_CS(pack_float24(data[1])); + OUT_CS(pack_float24(data[2])); + OUT_CS(pack_float24(data[3])); + } } END_CS; } -void r500_emit_fragment_shader(struct r300_context* r300, - struct r5xx_fragment_shader* fs) +void r500_emit_fragment_program_code(struct r300_context* r300, + struct rX00_fragment_program_code* generic_code, + struct r300_constant_buffer* externals) { + struct r500_fragment_program_code * code = &generic_code->code.r500; + struct rc_constant_list * constants = &generic_code->constants; int i; - struct r300_constant_buffer* constants = - &r300->shader_constants[PIPE_SHADER_FRAGMENT]; CS_LOCALS(r300); - BEGIN_CS(9 + (fs->instruction_count * 6) + (constants->count ? 3 : 0) + - (constants->count * 4)); - OUT_CS_REG(R500_US_CONFIG, R500_ZERO_TIMES_ANYTHING_EQUALS_ZERO); - OUT_CS_REG(R500_US_PIXSIZE, fs->shader.stack_size); - OUT_CS_REG(R500_US_CODE_ADDR, R500_US_CODE_START_ADDR(0) | - R500_US_CODE_END_ADDR(fs->instruction_count)); + BEGIN_CS(13 + + ((code->inst_end + 1) * 6) + + (constants->Count ? (3 + (constants->Count * 4)) : 0)); + OUT_CS_REG(R500_US_CONFIG, 0); + OUT_CS_REG(R500_US_PIXSIZE, code->max_temp_idx); + OUT_CS_REG(R500_US_CODE_RANGE, + R500_US_CODE_RANGE_ADDR(0) | R500_US_CODE_RANGE_SIZE(code->inst_end)); + OUT_CS_REG(R500_US_CODE_OFFSET, 0); + OUT_CS_REG(R500_US_CODE_ADDR, + R500_US_CODE_START_ADDR(0) | R500_US_CODE_END_ADDR(code->inst_end)); OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_INSTR); - OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, fs->instruction_count * 6); - for (i = 0; i < fs->instruction_count; i++) { - OUT_CS(fs->instructions[i].inst0); - OUT_CS(fs->instructions[i].inst1); - OUT_CS(fs->instructions[i].inst2); - OUT_CS(fs->instructions[i].inst3); - OUT_CS(fs->instructions[i].inst4); - OUT_CS(fs->instructions[i].inst5); - } - - if (constants->count) { - OUT_CS_REG(R500_GA_US_VECTOR_INDEX, - R500_GA_US_VECTOR_INDEX_TYPE_CONST); - OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->count * 4); - for (i = 0; i < constants->count; i++) { - OUT_CS_32F(constants->constants[i][0]); - OUT_CS_32F(constants->constants[i][1]); - OUT_CS_32F(constants->constants[i][2]); - OUT_CS_32F(constants->constants[i][3]); + OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, (code->inst_end + 1) * 6); + for (i = 0; i <= code->inst_end; i++) { + OUT_CS(code->inst[i].inst0); + OUT_CS(code->inst[i].inst1); + OUT_CS(code->inst[i].inst2); + OUT_CS(code->inst[i].inst3); + OUT_CS(code->inst[i].inst4); + OUT_CS(code->inst[i].inst5); + } + + if (constants->Count) { + OUT_CS_REG(R500_GA_US_VECTOR_INDEX, R500_GA_US_VECTOR_INDEX_TYPE_CONST); + OUT_CS_ONE_REG(R500_GA_US_VECTOR_DATA, constants->Count * 4); + for (i = 0; i < constants->Count; i++) { + const float * data = get_shader_constant(r300, &constants->Constants[i], externals); + OUT_CS_32F(data[0]); + OUT_CS_32F(data[1]); + OUT_CS_32F(data[2]); + OUT_CS_32F(data[3]); } } @@ -382,26 +468,6 @@ void r300_emit_vertex_format_state(struct r300_context* r300) END_CS; } -static const float * get_shader_constant( - struct r300_context * r300, - struct rc_constant * constant, - struct r300_constant_buffer * externals) -{ - static const float zero[4] = { 0.0, 0.0, 0.0, 0.0 }; - switch(constant->Type) { - case RC_CONSTANT_EXTERNAL: - return externals->constants[constant->u.External]; - - case RC_CONSTANT_IMMEDIATE: - return constant->u.Immediate; - - default: - debug_printf("r300: Implementation error: Unhandled constant type %i\n", - constant->Type); - return zero; - } -} - void r300_emit_vertex_program_code(struct r300_context* r300, struct r300_vertex_program_code* code, struct r300_constant_buffer* constants) @@ -589,11 +655,9 @@ validate: if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) { if (r300screen->caps->is_r500) { - r500_emit_fragment_shader(r300, - (struct r5xx_fragment_shader*)r300->fs); + r500_emit_fragment_program_code(r300, &r300->fs->code, &r300->shader_constants[PIPE_SHADER_FRAGMENT]); } else { - r300_emit_fragment_shader(r300, - (struct r3xx_fragment_shader*)r300->fs); + r300_emit_fragment_program_code(r300, &r300->fs->code, &r300->shader_constants[PIPE_SHADER_FRAGMENT]); } r300->dirty_state &= ~R300_NEW_FRAGMENT_SHADER; } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index fbc6487aa2..350691d592 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -30,6 +30,7 @@ #include "r300_screen.h" #include "r300_state_inlines.h" +struct rX00_fragment_program_code; struct r300_vertex_program_code; void r300_emit_blend_state(struct r300_context* r300, @@ -44,11 +45,13 @@ void r300_emit_clip_state(struct r300_context* r300, void r300_emit_dsa_state(struct r300_context* r300, struct r300_dsa_state* dsa); -void r300_emit_fragment_shader(struct r300_context* r300, - struct r3xx_fragment_shader* fs); +void r300_emit_fragment_program_code(struct r300_context* r300, + struct rX00_fragment_program_code* generic_code, + struct r300_constant_buffer* externals); -void r500_emit_fragment_shader(struct r300_context* r300, - struct r5xx_fragment_shader* fs); +void r500_emit_fragment_program_code(struct r300_context* r300, + struct rX00_fragment_program_code* generic_code, + struct r300_constant_buffer* externals); void r300_emit_fb_state(struct r300_context* r300, struct pipe_framebuffer_state* fb); diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index ca8ef99902..2cddb97038 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -23,89 +23,115 @@ #include "r300_fs.h" -void r300_translate_fragment_shader(struct r300_context* r300, - struct r300_fragment_shader* fs) -{ - struct tgsi_parse_context parser; - int i; - boolean is_r500 = r300_screen(r300->context.screen)->caps->is_r500; - struct r300_constant_buffer* consts = - &r300->shader_constants[PIPE_SHADER_FRAGMENT]; +#include "r300_tgsi_to_rc.h" - struct r300_fs_asm* assembler = CALLOC_STRUCT(r300_fs_asm); - if (assembler == NULL) { - return; - } - /* Setup starting offset for immediates. */ - assembler->imm_offset = consts->user_count; - /* Enable depth writes, if needed. */ - assembler->writes_depth = fs->info.writes_z; - - /* Make sure we start at the beginning of the shader. */ - if (is_r500) { - ((struct r5xx_fragment_shader*)fs)->instruction_count = 0; - } +#include "radeon_compiler.h" - tgsi_parse_init(&parser, fs->state.tokens); +static void find_output_registers(struct r300_fragment_program_compiler * compiler, + struct r300_fragment_shader * fs) +{ + unsigned i; - while (!tgsi_parse_end_of_tokens(&parser)) { - tgsi_parse_token(&parser); + /* Mark the outputs as not present initially */ + compiler->OutputColor = fs->info.num_outputs; + compiler->OutputDepth = fs->info.num_outputs; - /* This is seriously the lamest way to create fragment programs ever. - * I blame TGSI. */ - switch (parser.FullToken.Token.Type) { - case TGSI_TOKEN_TYPE_DECLARATION: - /* Allocated registers sitting at the beginning - * of the program. */ - r300_fs_declare(assembler, &parser.FullToken.FullDeclaration); + /* Now see where they really are. */ + for(i = 0; i < fs->info.num_outputs; ++i) { + switch(fs->info.output_semantic_name[i]) { + case TGSI_SEMANTIC_COLOR: + compiler->OutputColor = i; + break; + case TGSI_SEMANTIC_POSITION: + compiler->OutputDepth = i; break; - case TGSI_TOKEN_TYPE_IMMEDIATE: - debug_printf("r300: Emitting immediate to constant buffer, " - "position %d\n", - assembler->imm_offset + assembler->imm_count); - /* I am not amused by the length of these. */ - for (i = 0; i < 4; i++) { - consts->constants[assembler->imm_offset + - assembler->imm_count][i] = - parser.FullToken.FullImmediate.u[i].Float; - } - assembler->imm_count++; + } + } +} + +static void allocate_hardware_inputs( + struct r300_fragment_program_compiler * c, + void (*allocate)(void * data, unsigned input, unsigned hwreg), + void * mydata) +{ + struct tgsi_shader_info* info = &((struct r300_fragment_shader*)c->UserData)->info; + int total_colors = 0; + int colors = 0; + int total_generic = 0; + int generic = 0; + int i; + + for (i = 0; i < info->num_inputs; i++) { + switch (info->input_semantic_name[i]) { + case TGSI_SEMANTIC_COLOR: + total_colors++; break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - if (is_r500) { - r5xx_fs_instruction((struct r5xx_fragment_shader*)fs, - assembler, &parser.FullToken.FullInstruction); - } else { - r3xx_fs_instruction((struct r3xx_fragment_shader*)fs, - assembler, &parser.FullToken.FullInstruction); - } + case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_GENERIC: + total_generic++; break; } } - debug_printf("r300: fs: %d texs and %d colors, first free reg is %d\n", - assembler->tex_count, assembler->color_count, - assembler->tex_count + assembler->color_count); - - consts->count = consts->user_count + assembler->imm_count; - fs->uses_imms = assembler->imm_count; - debug_printf("r300: fs: %d total constants, " - "%d from user and %d from immediates\n", consts->count, - consts->user_count, assembler->imm_count); - r3xx_fs_finalize(fs, assembler); - if (is_r500) { - r5xx_fs_finalize((struct r5xx_fragment_shader*)fs, assembler); + for(i = 0; i < info->num_inputs; i++) { + switch (info->input_semantic_name[i]) { + case TGSI_SEMANTIC_COLOR: + allocate(mydata, i, colors); + colors++; + break; + case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_GENERIC: + allocate(mydata, i, total_colors + generic); + generic++; + break; + } } +} + +void r300_translate_fragment_shader(struct r300_context* r300, + struct r300_fragment_shader* fs) +{ + struct r300_fragment_program_compiler compiler; + struct tgsi_to_rc ttr; - tgsi_dump(fs->state.tokens, 0); - /* XXX finish r300 dumper too */ - if (is_r500) { - r5xx_fs_dump((struct r5xx_fragment_shader*)fs); + memset(&compiler, 0, sizeof(compiler)); + rc_init(&compiler.Base); + compiler.Base.Debug = 1; + + compiler.code = &fs->code; + compiler.is_r500 = r300_screen(r300->context.screen)->caps->is_r500; + compiler.AllocateHwInputs = &allocate_hardware_inputs; + compiler.UserData = fs; + + /* TODO: Program compilation depends on texture compare modes, + * which are sampler state. Therefore, programs need to be recompiled + * depending on this state as in the classic Mesa driver. + * + * This is not yet handled correctly. + */ + + find_output_registers(&compiler, fs); + + if (compiler.Base.Debug) { + debug_printf("r300: Initial vertex program\n"); + tgsi_dump(fs->state.tokens, 0); } - tgsi_parse_free(&parser); - FREE(assembler); + /* Translate TGSI to our internal representation */ + ttr.compiler = &compiler.Base; + ttr.info = &fs->info; + + r300_tgsi_to_rc(&ttr, fs->state.tokens); + + /* Invoke the compiler */ + r3xx_compile_fragment_program(&compiler); + if (compiler.Base.Error) { + /* Todo: Fail gracefully */ + fprintf(stderr, "r300 FP: Compiler error\n"); + abort(); + } /* And, finally... */ + rc_destroy(&compiler.Base); fs->translated = TRUE; } diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h index 18deb7a05e..9fab789402 100644 --- a/src/gallium/drivers/r300/r300_fs.h +++ b/src/gallium/drivers/r300/r300_fs.h @@ -30,6 +30,21 @@ #include "r3xx_fs.h" #include "r5xx_fs.h" +#include "radeon_code.h" + +struct r300_fragment_shader { + /* Parent class */ + struct pipe_shader_state state; + struct tgsi_shader_info info; + + /* Has this shader been translated yet? */ + boolean translated; + + /* Compiled code */ + struct rX00_fragment_program_code code; +}; + + void r300_translate_fragment_shader(struct r300_context* r300, struct r300_fragment_shader* fs); diff --git a/src/gallium/drivers/r300/r300_fs_inlines.h b/src/gallium/drivers/r300/r300_fs_inlines.h deleted file mode 100644 index be4be9465e..0000000000 --- a/src/gallium/drivers/r300/r300_fs_inlines.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2008 Corbin Simpson - * Joakim Sindholt - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, and/or sell copies of the Software, and to permit persons to whom - * the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - -#ifndef R300_FS_INLINES_H -#define R300_FS_INLINES_H - -#include "tgsi/tgsi_parse.h" - -#include "r300_context.h" -#include "r300_debug.h" -#include "r300_reg.h" -#include "r300_screen.h" -#include "r300_shader_inlines.h" - -/* Temporary struct used to hold assembly state while putting together - * fragment programs. */ -struct r300_fs_asm { - /* Pipe context. */ - struct r300_context* r300; - /* Number of colors. */ - unsigned color_count; - /* Number of texcoords. */ - unsigned tex_count; - /* Offset for temporary registers. Inputs and temporaries have no - * distinguishing markings, so inputs start at 0 and the first usable - * temporary register is after all inputs. */ - unsigned temp_offset; - /* Number of requested temporary registers. */ - unsigned temp_count; - /* Offset for immediate constants. Neither R300 nor R500 can do four - * inline constants per source, so instead we copy immediates into the - * constant buffer. */ - unsigned imm_offset; - /* Number of immediate constants. */ - unsigned imm_count; - /* Are depth writes enabled? */ - boolean writes_depth; - /* Depth write offset. This is the TGSI output that corresponds to - * depth writes. */ - unsigned depth_output; -}; - -static INLINE void r300_fs_declare(struct r300_fs_asm* assembler, - struct tgsi_full_declaration* decl) -{ - switch (decl->Declaration.File) { - case TGSI_FILE_INPUT: - switch (decl->Semantic.SemanticName) { - case TGSI_SEMANTIC_COLOR: - assembler->color_count++; - break; - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - assembler->tex_count++; - break; - default: - debug_printf("r300: fs: Bad semantic declaration %d\n", - decl->Semantic.SemanticName); - break; - } - break; - case TGSI_FILE_OUTPUT: - /* Depth write. Mark the position of the output so we can - * identify it later. */ - if (decl->Semantic.SemanticName == TGSI_SEMANTIC_POSITION) { - assembler->depth_output = decl->DeclarationRange.First; - } - break; - case TGSI_FILE_CONSTANT: - break; - case TGSI_FILE_TEMPORARY: - assembler->temp_count++; - break; - default: - debug_printf("r300: fs: Bad file %d\n", decl->Declaration.File); - break; - } - - assembler->temp_offset = assembler->color_count + assembler->tex_count; -} - -static INLINE unsigned r300_fs_src(struct r300_fs_asm* assembler, - struct tgsi_src_register* src) -{ - switch (src->File) { - case TGSI_FILE_NULL: - return 0; - case TGSI_FILE_INPUT: - /* XXX may be wrong */ - return src->Index; - break; - case TGSI_FILE_TEMPORARY: - return src->Index + assembler->temp_offset; - break; - case TGSI_FILE_IMMEDIATE: - return (src->Index + assembler->imm_offset) | (1 << 8); - break; - case TGSI_FILE_CONSTANT: - /* XXX magic */ - return src->Index | (1 << 8); - break; - default: - debug_printf("r300: fs: Unimplemented src %d\n", src->File); - break; - } - return 0; -} - -static INLINE unsigned r300_fs_dst(struct r300_fs_asm* assembler, - struct tgsi_dst_register* dst) -{ - switch (dst->File) { - case TGSI_FILE_NULL: - /* This happens during KIL instructions. */ - return 0; - break; - case TGSI_FILE_OUTPUT: - return 0; - break; - case TGSI_FILE_TEMPORARY: - return dst->Index + assembler->temp_offset; - break; - default: - debug_printf("r300: fs: Unimplemented dst %d\n", dst->File); - break; - } - return 0; -} - -static INLINE boolean r300_fs_is_depr(struct r300_fs_asm* assembler, - struct tgsi_dst_register* dst) -{ - return (assembler->writes_depth && - (dst->File == TGSI_FILE_OUTPUT) && - (dst->Index == assembler->depth_output)); -} - -#endif /* R300_FS_INLINES_H */ diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 33f1d7e79f..bb4b4be50f 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -32,6 +32,7 @@ #include "r300_reg.h" #include "r300_state_inlines.h" #include "r300_fs.h" +#include "r300_vs.h" /* r300_state: Functions used to intialize state context by translating * Gallium state objects into semi-native r300 state objects. */ @@ -155,20 +156,6 @@ static void } r300->dirty_state |= R300_NEW_CONSTANTS; -#if 0 - /* If the number of constants have changed, invalidate the shader. */ - if (r300->shader_constants[shader].user_count != i) { - if (shader == PIPE_SHADER_FRAGMENT && r300->fs && - r300->fs->uses_imms) { - r300->fs->translated = FALSE; - r300_translate_fragment_shader(r300, r300->fs); - } else if (shader == PIPE_SHADER_VERTEX && r300->vs && - r300->vs->uses_imms) { - r300->vs->translated = FALSE; - r300_translate_vertex_shader(r300, r300->vs); - } - } -#endif } /* Create a new depth, stencil, and alpha state based on the CSO dsa state. @@ -285,14 +272,9 @@ static void static void* r300_create_fs_state(struct pipe_context* pipe, const struct pipe_shader_state* shader) { - struct r300_context* r300 = r300_context(pipe); struct r300_fragment_shader* fs = NULL; - if (r300_screen(r300->context.screen)->caps->is_r500) { - fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r5xx_fragment_shader); - } else { - fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r3xx_fragment_shader); - } + fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r300_fragment_shader); /* Copy state directly into shader. */ fs->state = *shader; @@ -325,6 +307,7 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) static void r300_delete_fs_state(struct pipe_context* pipe, void* shader) { struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; + rc_constants_destroy(&fs->code.constants); FREE(fs->state.tokens); FREE(shader); } diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index 5c67eb13ff..ea670f41fb 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -22,6 +22,7 @@ #include "r300_state_derived.h" +#include "r300_fs.h" #include "r300_vs.h" /* r300_state_derived: Various bits of state which are dependent upon diff --git a/src/gallium/drivers/r300/r300_surface.c b/src/gallium/drivers/r300/r300_surface.c index cf15333198..7dbfb64dbe 100644 --- a/src/gallium/drivers/r300/r300_surface.c +++ b/src/gallium/drivers/r300/r300_surface.c @@ -152,10 +152,10 @@ validate: /* Fragment shader setup */ if (caps->is_r500) { - r500_emit_fragment_shader(r300, &r5xx_passthrough_fragment_shader); + r500_emit_fragment_program_code(r300, &r5xx_passthrough_fragment_shader, 0); r300_emit_rs_block_state(r300, &r5xx_rs_block_clear_state); } else { - r300_emit_fragment_shader(r300, &r3xx_passthrough_fragment_shader); + r300_emit_fragment_program_code(r300, &r3xx_passthrough_fragment_shader, 0); r300_emit_rs_block_state(r300, &r3xx_rs_block_clear_state); } @@ -290,10 +290,10 @@ validate: /* Fragment shader setup */ if (caps->is_r500) { - r500_emit_fragment_shader(r300, &r5xx_texture_fragment_shader); + r500_emit_fragment_program_code(r300, &r5xx_texture_fragment_shader, 0); r300_emit_rs_block_state(r300, &r5xx_rs_block_copy_state); } else { - r300_emit_fragment_shader(r300, &r3xx_texture_fragment_shader); + r300_emit_fragment_program_code(r300, &r3xx_texture_fragment_shader, 0); r300_emit_rs_block_state(r300, &r3xx_rs_block_copy_state); } diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index f530b23380..3adbb715f3 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -224,6 +224,39 @@ static void transform_srcreg( dst->Negate ^= src->SrcRegister.Negate ? NEGATE_XYZW : 0; } +static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_ext_texture src) +{ + switch(src.Texture) { + case TGSI_TEXTURE_1D: + dst->I.TexSrcTarget = TEXTURE_1D_INDEX; + break; + case TGSI_TEXTURE_2D: + dst->I.TexSrcTarget = TEXTURE_2D_INDEX; + break; + case TGSI_TEXTURE_3D: + dst->I.TexSrcTarget = TEXTURE_3D_INDEX; + break; + case TGSI_TEXTURE_CUBE: + dst->I.TexSrcTarget = TEXTURE_CUBE_INDEX; + break; + case TGSI_TEXTURE_RECT: + dst->I.TexSrcTarget = TEXTURE_RECT_INDEX; + break; + case TGSI_TEXTURE_SHADOW1D: + dst->I.TexSrcTarget = TEXTURE_1D_INDEX; + dst->I.TexShadow = 1; + break; + case TGSI_TEXTURE_SHADOW2D: + dst->I.TexSrcTarget = TEXTURE_2D_INDEX; + dst->I.TexShadow = 1; + break; + case TGSI_TEXTURE_SHADOWRECT: + dst->I.TexSrcTarget = TEXTURE_RECT_INDEX; + dst->I.TexShadow = 1; + break; + } +} + static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_instruction * src) { if (src->Instruction.Opcode == TGSI_OPCODE_END) @@ -238,10 +271,15 @@ static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_inst if (src->Instruction.NumDstRegs) transform_dstreg(ttr, &dst->I.DstReg, &src->FullDstRegisters[0]); - for(i = 0; i < src->Instruction.NumSrcRegs; ++i) - transform_srcreg(ttr, &dst->I.SrcReg[i], &src->FullSrcRegisters[i]); + for(i = 0; i < src->Instruction.NumSrcRegs; ++i) { + if (src->FullSrcRegisters[i].SrcRegister.File == TGSI_FILE_SAMPLER) + dst->I.TexSrcUnit = src->FullSrcRegisters[i].SrcRegister.Index; + else + transform_srcreg(ttr, &dst->I.SrcReg[i], &src->FullSrcRegisters[i]); + } - /* TODO: Textures */ + /* Texturing. */ + transform_texture(dst, src->InstructionExtTexture); } static void handle_immediate(struct tgsi_to_rc * ttr, struct tgsi_full_immediate * imm) diff --git a/src/gallium/drivers/r300/r3xx_fs.c b/src/gallium/drivers/r300/r3xx_fs.c index 6e05d76977..c1c1194d58 100644 --- a/src/gallium/drivers/r300/r3xx_fs.c +++ b/src/gallium/drivers/r300/r3xx_fs.c @@ -23,74 +23,52 @@ #include "r3xx_fs.h" -static INLINE uint32_t r3xx_rgb_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_MOV: - return R300_ALU_OUTC_CMP; - default: - return 0; - } -} +#include "r300_reg.h" -static INLINE uint32_t r3xx_alpha_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_MOV: - return R300_ALU_OUTA_CMP; - default: - return 0; - } -} +struct rX00_fragment_program_code r3xx_passthrough_fragment_shader = { + .code.r300.alu.length = 1, + .code.r300.tex.length = 0, -static INLINE void r3xx_emit_maths(struct r3xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_src_register* src, - struct tgsi_full_dst_register* dst, - unsigned op, - unsigned count) -{ - int i = fs->alu_instruction_count; + .code.r300.config = 0, + .code.r300.pixsize = 0, + .code.r300.code_offset = 0, + .code.r300.code_addr[3] = R300_RGBA_OUT, - fs->instructions[i].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | + .code.r300.alu.inst[0].rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - r3xx_rgb_op(op); - fs->instructions[i].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ; - fs->instructions[i].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | + R300_ALU_OUTC_CMP, + .code.r300.alu.inst[0].rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | + R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, + .code.r300.alu.inst[0].alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - r3xx_alpha_op(op); - fs->instructions[i].alu_alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT; + R300_ALU_OUTA_CMP, + .code.r300.alu.inst[0].alpha_addr = R300_ALPHA_ADDR0(0) | + R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, +}; - fs->alu_instruction_count++; -} +struct rX00_fragment_program_code r3xx_texture_fragment_shader = { + .code.r300.alu.length = 1, + .code.r300.tex.length = 1, -void r3xx_fs_finalize(struct r300_fragment_shader* fs, - struct r300_fs_asm* assembler) -{ - fs->stack_size = assembler->temp_count + assembler->temp_offset + 1; -} + .code.r300.config = R300_PFS_CNTL_FIRST_NODE_HAS_TEX, + .code.r300.pixsize = 0, + .code.r300.code_offset = 0, + .code.r300.code_addr[3] = R300_RGBA_OUT, -void r3xx_fs_instruction(struct r3xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst) -{ - switch (inst->Instruction.Opcode) { - case TGSI_OPCODE_MOV: - /* src0 -> src1 and src2 forced to zero */ - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[2] = r300_constant_zero; - r3xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - case TGSI_OPCODE_END: - break; - default: - debug_printf("r300: fs: Bad opcode %d\n", - inst->Instruction.Opcode); - break; - } -} + .code.r300.tex.inst[0] = R300_TEX_OP_LD << R300_TEX_INST_SHIFT, + + .code.r300.alu.inst[0].rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | + R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | + R300_ALU_OUTC_CMP, + .code.r300.alu.inst[0].rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | + R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, + .code.r300.alu.inst[0].alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | + R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | + R300_ALU_OUTA_CMP, + .code.r300.alu.inst[0].alpha_addr = R300_ALPHA_ADDR0(0) | + R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, +}; diff --git a/src/gallium/drivers/r300/r3xx_fs.h b/src/gallium/drivers/r300/r3xx_fs.h index 592898d899..51cd245724 100644 --- a/src/gallium/drivers/r300/r3xx_fs.h +++ b/src/gallium/drivers/r300/r3xx_fs.h @@ -24,55 +24,9 @@ #ifndef R3XX_FS_H #define R3XX_FS_H -#include "r300_fs_inlines.h" +#include "radeon_code.h" -static struct r3xx_fragment_shader r3xx_passthrough_fragment_shader = { - .alu_instruction_count = 1, - .tex_instruction_count = 0, - .indirections = 0, - .shader.stack_size = 1, - - .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - R300_ALU_OUTC_CMP, - .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, - .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - R300_ALU_OUTA_CMP, - .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, -}; - -static struct r3xx_fragment_shader r3xx_texture_fragment_shader = { - .alu_instruction_count = 1, - .tex_instruction_count = 0, - .indirections = 0, - .shader.stack_size = 1, - - .instructions[0].alu_rgb_inst = R300_RGB_SWIZA(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZB(R300_ALU_ARGC_SRC0C_XYZ) | - R300_RGB_SWIZC(R300_ALU_ARGC_ZERO) | - R300_ALU_OUTC_CMP, - .instructions[0].alu_rgb_addr = R300_RGB_ADDR0(0) | R300_RGB_ADDR1(0) | - R300_RGB_ADDR2(0) | R300_ALU_DSTC_OUTPUT_XYZ, - .instructions[0].alu_alpha_inst = R300_ALPHA_SWIZA(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - R300_ALU_OUTA_CMP, - .instructions[0].alu_alpha_addr = R300_ALPHA_ADDR0(0) | - R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT, -}; - -struct r300_fs_asm; - -void r3xx_fs_finalize(struct r300_fragment_shader* fs, - struct r300_fs_asm* assembler); - -void r3xx_fs_instruction(struct r3xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst); +struct rX00_fragment_program_code r3xx_passthrough_fragment_shader; +struct rX00_fragment_program_code r3xx_texture_fragment_shader; #endif /* R3XX_FS_H */ diff --git a/src/gallium/drivers/r300/r5xx_fs.c b/src/gallium/drivers/r300/r5xx_fs.c index 99d826278c..f072deab0d 100644 --- a/src/gallium/drivers/r300/r5xx_fs.c +++ b/src/gallium/drivers/r300/r5xx_fs.c @@ -23,445 +23,103 @@ #include "r5xx_fs.h" -static INLINE unsigned r5xx_fix_swiz(unsigned s) -{ - /* For historical reasons, the swizzle values x, y, z, w, and 0 are - * equivalent to the actual machine code, but 1 is not. Thus, we just - * adjust it a bit... */ - if (s == TGSI_EXTSWIZZLE_ONE) { - return R500_SWIZZLE_ONE; - } else { - return s; - } -} - -static uint32_t r5xx_rgba_swiz(struct tgsi_full_src_register* reg) -{ - if (reg->SrcRegister.Extended) { - return r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleX) | - (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleY) << 3) | - (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleZ) << 6) | - (r5xx_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleW) << 9); - } else { - return reg->SrcRegister.SwizzleX | - (reg->SrcRegister.SwizzleY << 3) | - (reg->SrcRegister.SwizzleZ << 6) | - (reg->SrcRegister.SwizzleW << 9); - } -} - -static uint32_t r5xx_strq_swiz(struct tgsi_full_src_register* reg) -{ - return reg->SrcRegister.SwizzleX | - (reg->SrcRegister.SwizzleY << 2) | - (reg->SrcRegister.SwizzleZ << 4) | - (reg->SrcRegister.SwizzleW << 6); -} - -static INLINE uint32_t r5xx_rgb_swiz(struct tgsi_full_src_register* reg) -{ - /* Only the first 9 bits... */ - return (r5xx_rgba_swiz(reg) & 0x1ff) | - (reg->SrcRegister.Negate ? (1 << 9) : 0) | - (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0); -} - -static INLINE uint32_t r5xx_alpha_swiz(struct tgsi_full_src_register* reg) -{ - /* Only the last 3 bits... */ - return (r5xx_rgba_swiz(reg) >> 9) | - (reg->SrcRegister.Negate ? (1 << 9) : 0) | - (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0); -} - -static INLINE uint32_t r5xx_rgba_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_COS: - case TGSI_OPCODE_EX2: - case TGSI_OPCODE_LG2: - case TGSI_OPCODE_RCP: - case TGSI_OPCODE_RSQ: - case TGSI_OPCODE_SIN: - return R500_ALU_RGBA_OP_SOP; - case TGSI_OPCODE_DDX: - return R500_ALU_RGBA_OP_MDH; - case TGSI_OPCODE_DDY: - return R500_ALU_RGBA_OP_MDV; - case TGSI_OPCODE_FRC: - return R500_ALU_RGBA_OP_FRC; - case TGSI_OPCODE_DP3: - return R500_ALU_RGBA_OP_DP3; - case TGSI_OPCODE_DP4: - case TGSI_OPCODE_DPH: - return R500_ALU_RGBA_OP_DP4; - case TGSI_OPCODE_ABS: - case TGSI_OPCODE_CMP: - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SWZ: - return R500_ALU_RGBA_OP_CMP; - case TGSI_OPCODE_ADD: - case TGSI_OPCODE_MAD: - case TGSI_OPCODE_MUL: - case TGSI_OPCODE_SUB: - return R500_ALU_RGBA_OP_MAD; - default: - return 0; - } -} - -static INLINE uint32_t r5xx_alpha_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_COS: - return R500_ALPHA_OP_COS; - case TGSI_OPCODE_EX2: - return R500_ALPHA_OP_EX2; - case TGSI_OPCODE_LG2: - return R500_ALPHA_OP_LN2; - case TGSI_OPCODE_RCP: - return R500_ALPHA_OP_RCP; - case TGSI_OPCODE_RSQ: - return R500_ALPHA_OP_RSQ; - case TGSI_OPCODE_FRC: - return R500_ALPHA_OP_FRC; - case TGSI_OPCODE_SIN: - return R500_ALPHA_OP_SIN; - case TGSI_OPCODE_DDX: - return R500_ALPHA_OP_MDH; - case TGSI_OPCODE_DDY: - return R500_ALPHA_OP_MDV; - case TGSI_OPCODE_DP3: - case TGSI_OPCODE_DP4: - case TGSI_OPCODE_DPH: - return R500_ALPHA_OP_DP; - case TGSI_OPCODE_ABS: - case TGSI_OPCODE_CMP: - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SWZ: - return R500_ALPHA_OP_CMP; - case TGSI_OPCODE_ADD: - case TGSI_OPCODE_MAD: - case TGSI_OPCODE_MUL: - case TGSI_OPCODE_SUB: - return R500_ALPHA_OP_MAD; - default: - return 0; - } -} - -static INLINE uint32_t r5xx_tex_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_KIL: - return R500_TEX_INST_TEXKILL; - case TGSI_OPCODE_TEX: - return R500_TEX_INST_LD; - case TGSI_OPCODE_TXB: - return R500_TEX_INST_LODBIAS; - case TGSI_OPCODE_TXP: - return R500_TEX_INST_PROJ; - default: - return 0; - } -} - -/* Setup an ALU operation. */ -static INLINE void r5xx_emit_maths(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_src_register* src, - struct tgsi_full_dst_register* dst, - unsigned op, - unsigned count) -{ - int i = fs->instruction_count; - - if (dst->DstRegister.File == TGSI_FILE_OUTPUT) { - fs->instructions[i].inst0 = R500_INST_TYPE_OUT; - if (r300_fs_is_depr(assembler, dst)) { - fs->instructions[i].inst4 = R500_W_OMASK; - } else { - fs->instructions[i].inst0 |= - R500_ALU_OMASK(dst->DstRegister.WriteMask); - } - } else { - fs->instructions[i].inst0 = R500_INST_TYPE_ALU | - R500_ALU_WMASK(dst->DstRegister.WriteMask); - } - - fs->instructions[i].inst0 |= R500_INST_TEX_SEM_WAIT; - - fs->instructions[i].inst4 |= - R500_ALPHA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister)); - fs->instructions[i].inst5 = - R500_ALU_RGBA_ADDRD(r300_fs_dst(assembler, &dst->DstRegister)); - - switch (count) { - case 3: - fs->instructions[i].inst1 = - R500_RGB_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister)); - fs->instructions[i].inst2 = - R500_ALPHA_ADDR2(r300_fs_src(assembler, &src[2].SrcRegister)); - fs->instructions[i].inst5 |= - R500_ALU_RGBA_SEL_C_SRC2 | - R500_SWIZ_RGBA_C(r5xx_rgb_swiz(&src[2])) | - R500_ALU_RGBA_ALPHA_SEL_C_SRC2 | - R500_SWIZ_ALPHA_C(r5xx_alpha_swiz(&src[2])); - case 2: - fs->instructions[i].inst1 |= - R500_RGB_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)); - fs->instructions[i].inst2 |= - R500_ALPHA_ADDR1(r300_fs_src(assembler, &src[1].SrcRegister)); - fs->instructions[i].inst3 = - R500_ALU_RGB_SEL_B_SRC1 | - R500_SWIZ_RGB_B(r5xx_rgb_swiz(&src[1])); - fs->instructions[i].inst4 |= - R500_ALPHA_SEL_B_SRC1 | - R500_SWIZ_ALPHA_B(r5xx_alpha_swiz(&src[1])); - case 1: - case 0: - default: - fs->instructions[i].inst1 |= - R500_RGB_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister)); - fs->instructions[i].inst2 |= - R500_ALPHA_ADDR0(r300_fs_src(assembler, &src[0].SrcRegister)); - fs->instructions[i].inst3 |= - R500_ALU_RGB_SEL_A_SRC0 | - R500_SWIZ_RGB_A(r5xx_rgb_swiz(&src[0])); - fs->instructions[i].inst4 |= - R500_ALPHA_SEL_A_SRC0 | - R500_SWIZ_ALPHA_A(r5xx_alpha_swiz(&src[0])); - break; - } - - fs->instructions[i].inst4 |= r5xx_alpha_op(op); - fs->instructions[i].inst5 |= r5xx_rgba_op(op); - - fs->instruction_count++; -} - -static INLINE void r5xx_emit_tex(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_src_register* src, - struct tgsi_full_dst_register* dst, - uint32_t op) -{ - int i = fs->instruction_count; - - fs->instructions[i].inst0 = R500_INST_TYPE_TEX | - R500_TEX_WMASK(dst->DstRegister.WriteMask) | - R500_INST_TEX_SEM_WAIT; - fs->instructions[i].inst1 = R500_TEX_ID(0) | - R500_TEX_SEM_ACQUIRE | //R500_TEX_IGNORE_UNCOVERED | - r5xx_tex_op(op); - fs->instructions[i].inst2 = - R500_TEX_SRC_ADDR(r300_fs_src(assembler, &src->SrcRegister)) | - R500_SWIZ_TEX_STRQ(r5xx_strq_swiz(src)) | - R500_TEX_DST_ADDR(r300_fs_dst(assembler, &dst->DstRegister)) | +#include "r300_reg.h" + +/* XXX this all should find its way back to r300_reg */ +/* Swizzle tools */ +#define R500_SWIZZLE_ZERO 4 +#define R500_SWIZZLE_HALF 5 +#define R500_SWIZZLE_ONE 6 +#define R500_SWIZ_RGB_ZERO ((4 << 0) | (4 << 3) | (4 << 6)) +#define R500_SWIZ_RGB_ONE ((6 << 0) | (6 << 3) | (6 << 6)) +#define R500_SWIZ_RGB_RGB ((0 << 0) | (1 << 3) | (2 << 6)) +#define R500_SWIZ_MOD_NEG 1 +#define R500_SWIZ_MOD_ABS 2 +#define R500_SWIZ_MOD_NEG_ABS 3 +/* Swizzles for inst2 */ +#define R500_SWIZ_TEX_STRQ(x) ((x) << 8) +#define R500_SWIZ_TEX_RGBA(x) ((x) << 24) +/* Swizzles for inst3 */ +#define R500_SWIZ_RGB_A(x) ((x) << 2) +#define R500_SWIZ_RGB_B(x) ((x) << 15) +/* Swizzles for inst4 */ +#define R500_SWIZ_ALPHA_A(x) ((x) << 14) +#define R500_SWIZ_ALPHA_B(x) ((x) << 21) +/* Swizzle for inst5 */ +#define R500_SWIZ_RGBA_C(x) ((x) << 14) +#define R500_SWIZ_ALPHA_C(x) ((x) << 27) +/* Writemasks */ +#define R500_TEX_WMASK(x) ((x) << 11) +#define R500_ALU_WMASK(x) ((x) << 11) +#define R500_ALU_OMASK(x) ((x) << 15) +#define R500_W_OMASK (1 << 31) + +struct rX00_fragment_program_code r5xx_passthrough_fragment_shader = { + .code.r500.max_temp_idx = 0, + .code.r500.inst_end = 0, + + .code.r500.inst[0].inst0 = R500_INST_TYPE_OUT | + R500_INST_TEX_SEM_WAIT | R500_INST_LAST | + R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | + R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, + .code.r500.inst[0].inst1 = + R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | + R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, + .code.r500.inst[0].inst2 = + R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | + R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, + .code.r500.inst[0].inst3 = + R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | + R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | + R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | + R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, + .code.r500.inst[0].inst4 = + R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, + .code.r500.inst[0].inst5 = + R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | + R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | + R500_ALU_RGBA_A_SWIZ_0, +}; + +struct rX00_fragment_program_code r5xx_texture_fragment_shader = { + .code.r500.max_temp_idx = 0, + .code.r500.inst_end = 1, + + .code.r500.inst[0].inst0 = R500_INST_TYPE_TEX | + R500_INST_TEX_SEM_WAIT | + R500_INST_RGB_WMASK_RGB | R500_INST_ALPHA_WMASK | + R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, + .code.r500.inst[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD | + R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED, + .code.r500.inst[0].inst2 = R500_TEX_SRC_ADDR(0) | + R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G | + R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A | + R500_TEX_DST_ADDR(0) | R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G | - R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A; - - if (dst->DstRegister.File == TGSI_FILE_OUTPUT) { - fs->instructions[i].inst2 |= - R500_TEX_DST_ADDR(assembler->temp_count + - assembler->temp_offset); - - fs->instruction_count++; - - /* Setup and emit a MOV. */ - src[0].SrcRegister.Index = assembler->temp_count; - src[0].SrcRegister.File = TGSI_FILE_TEMPORARY; - - src[1] = src[0]; - src[2] = r300_constant_zero; - r5xx_emit_maths(fs, assembler, src, dst, TGSI_OPCODE_MOV, 3); - } else { - fs->instruction_count++; - } -} - -void r5xx_fs_finalize(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler) -{ - /* XXX should this just go with OPCODE_END? */ - fs->instructions[fs->instruction_count - 1].inst0 |= - R500_INST_LAST; -} - -void r5xx_fs_instruction(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst) -{ - /* Switch between opcodes. When possible, prefer using the official - * AMD/ATI names for opcodes, please, as it facilitates using the - * documentation. */ - switch (inst->Instruction.Opcode) { - /* XXX trig needs extra prep */ - case TGSI_OPCODE_COS: - case TGSI_OPCODE_SIN: - /* The simple scalar ops. */ - case TGSI_OPCODE_EX2: - case TGSI_OPCODE_LG2: - case TGSI_OPCODE_RCP: - case TGSI_OPCODE_RSQ: - /* Copy red swizzle to alpha for src0 */ - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW = - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX; - inst->FullSrcRegisters[0].SrcRegister.SwizzleW = - inst->FullSrcRegisters[0].SrcRegister.SwizzleX; - /* Fall through */ - case TGSI_OPCODE_DDX: - case TGSI_OPCODE_DDY: - case TGSI_OPCODE_FRC: - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 1); - break; - - /* The dot products. */ - case TGSI_OPCODE_DPH: - /* Set alpha swizzle to one for src0 */ - if (!inst->FullSrcRegisters[0].SrcRegister.Extended) { - inst->FullSrcRegisters[0].SrcRegister.Extended = TRUE; - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX = - inst->FullSrcRegisters[0].SrcRegister.SwizzleX; - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleY = - inst->FullSrcRegisters[0].SrcRegister.SwizzleY; - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleZ = - inst->FullSrcRegisters[0].SrcRegister.SwizzleZ; - } - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW = - TGSI_EXTSWIZZLE_ONE; - /* Fall through */ - case TGSI_OPCODE_DP3: - case TGSI_OPCODE_DP4: - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 2); - break; - - /* Simple three-source operations. */ - case TGSI_OPCODE_CMP: - /* Swap src0 and src2 */ - inst->FullSrcRegisters[3] = inst->FullSrcRegisters[2]; - inst->FullSrcRegisters[2] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[0] = inst->FullSrcRegisters[3]; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - - /* The MAD variants. */ - case TGSI_OPCODE_SUB: - /* Just like ADD, but flip the negation on src1 first */ - inst->FullSrcRegisters[1].SrcRegister.Negate = - !inst->FullSrcRegisters[1].SrcRegister.Negate; - /* Fall through */ - case TGSI_OPCODE_ADD: - /* Force src0 to one, move all registers over */ - inst->FullSrcRegisters[2] = inst->FullSrcRegisters[1]; - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[0] = r300_constant_one; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - case TGSI_OPCODE_MUL: - /* Force our src2 to zero */ - inst->FullSrcRegisters[2] = r300_constant_zero; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - case TGSI_OPCODE_MAD: - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - - /* The MOV variants. */ - case TGSI_OPCODE_ABS: - /* Set absolute value modifiers. */ - inst->FullSrcRegisters[0].SrcRegisterExtMod.Absolute = TRUE; - /* Fall through */ - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SWZ: - /* src0 -> src1 and src2 forced to zero */ - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[0]; - inst->FullSrcRegisters[2] = r300_constant_zero; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - - /* The compound and hybrid insts. */ - case TGSI_OPCODE_LRP: - /* LRP DST A, B, C -> MAD TMP -A, C, C; MAD DST A, B, TMP */ - inst->FullSrcRegisters[3] = inst->FullSrcRegisters[1]; - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[2]; - inst->FullSrcRegisters[0].SrcRegister.Negate = - !(inst->FullSrcRegisters[0].SrcRegister.Negate); - inst->FullDstRegisters[1] = inst->FullDstRegisters[0]; - inst->FullDstRegisters[0].DstRegister.Index = - assembler->temp_count; - inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3); - inst->FullSrcRegisters[2].SrcRegister.Index = - assembler->temp_count; - inst->FullSrcRegisters[2].SrcRegister.File = TGSI_FILE_TEMPORARY; - inst->FullSrcRegisters[2].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; - inst->FullSrcRegisters[2].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; - inst->FullSrcRegisters[2].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z; - inst->FullSrcRegisters[2].SrcRegister.SwizzleW = TGSI_SWIZZLE_W; - inst->FullSrcRegisters[1] = inst->FullSrcRegisters[3]; - inst->FullSrcRegisters[0].SrcRegister.Negate = - !(inst->FullSrcRegisters[0].SrcRegister.Negate); - inst->FullDstRegisters[0] = inst->FullDstRegisters[1]; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_MAD, 3); - break; - case TGSI_OPCODE_POW: - /* POW DST A, B -> LG2 TMP A; MUL TMP TMP, B; EX2 DST TMP */ - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW = - inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX; - inst->FullSrcRegisters[0].SrcRegister.SwizzleW = - inst->FullSrcRegisters[0].SrcRegister.SwizzleX; - inst->FullDstRegisters[1] = inst->FullDstRegisters[0]; - inst->FullDstRegisters[0].DstRegister.Index = - assembler->temp_count; - inst->FullDstRegisters[0].DstRegister.File = TGSI_FILE_TEMPORARY; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_LG2, 1); - inst->FullSrcRegisters[0].SrcRegister.Index = - assembler->temp_count; - inst->FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_TEMPORARY; - inst->FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; - inst->FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; - inst->FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Z; - inst->FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_W; - inst->FullSrcRegisters[2] = r300_constant_zero; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_MUL, 3); - inst->FullDstRegisters[0] = inst->FullDstRegisters[1]; - r5xx_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_EX2, 1); - break; - - /* The texture instruction set. */ - case TGSI_OPCODE_KIL: - case TGSI_OPCODE_TEX: - case TGSI_OPCODE_TXB: - case TGSI_OPCODE_TXP: - r5xx_emit_tex(fs, assembler, &inst->FullSrcRegisters[0], - &inst->FullDstRegisters[0], inst->Instruction.Opcode); - break; - - /* This is the end. My only friend, the end. */ - case TGSI_OPCODE_END: - break; - default: - debug_printf("r300: fs: Bad opcode %d\n", - inst->Instruction.Opcode); - break; - } - - /* Clamp, if saturation flags are set. */ - if (inst->Instruction.Saturate == TGSI_SAT_ZERO_ONE) { - fs->instructions[fs->instruction_count - 1].inst0 |= - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP; - } -} + R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A, + .code.r500.inst[0].inst3 = 0x0, + .code.r500.inst[0].inst4 = 0x0, + .code.r500.inst[0].inst5 = 0x0, + + .code.r500.inst[1].inst0 = R500_INST_TYPE_OUT | + R500_INST_TEX_SEM_WAIT | R500_INST_LAST | + R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | + R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, + .code.r500.inst[1].inst1 = + R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | + R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, + .code.r500.inst[1].inst2 = + R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | + R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, + .code.r500.inst[1].inst3 = + R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | + R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | + R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | + R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, + .code.r500.inst[1].inst4 = + R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, + .code.r500.inst[1].inst5 = + R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | + R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | + R500_ALU_RGBA_A_SWIZ_0, +}; diff --git a/src/gallium/drivers/r300/r5xx_fs.h b/src/gallium/drivers/r300/r5xx_fs.h index 7e62c3352b..a4addde32b 100644 --- a/src/gallium/drivers/r300/r5xx_fs.h +++ b/src/gallium/drivers/r300/r5xx_fs.h @@ -24,111 +24,9 @@ #ifndef R5XX_FS_H #define R5XX_FS_H -#include "r300_fs_inlines.h" +#include "radeon_code.h" -/* XXX this all should find its way back to r300_reg */ -/* Swizzle tools */ -#define R500_SWIZZLE_ZERO 4 -#define R500_SWIZZLE_HALF 5 -#define R500_SWIZZLE_ONE 6 -#define R500_SWIZ_RGB_ZERO ((4 << 0) | (4 << 3) | (4 << 6)) -#define R500_SWIZ_RGB_ONE ((6 << 0) | (6 << 3) | (6 << 6)) -#define R500_SWIZ_RGB_RGB ((0 << 0) | (1 << 3) | (2 << 6)) -#define R500_SWIZ_MOD_NEG 1 -#define R500_SWIZ_MOD_ABS 2 -#define R500_SWIZ_MOD_NEG_ABS 3 -/* Swizzles for inst2 */ -#define R500_SWIZ_TEX_STRQ(x) ((x) << 8) -#define R500_SWIZ_TEX_RGBA(x) ((x) << 24) -/* Swizzles for inst3 */ -#define R500_SWIZ_RGB_A(x) ((x) << 2) -#define R500_SWIZ_RGB_B(x) ((x) << 15) -/* Swizzles for inst4 */ -#define R500_SWIZ_ALPHA_A(x) ((x) << 14) -#define R500_SWIZ_ALPHA_B(x) ((x) << 21) -/* Swizzle for inst5 */ -#define R500_SWIZ_RGBA_C(x) ((x) << 14) -#define R500_SWIZ_ALPHA_C(x) ((x) << 27) -/* Writemasks */ -#define R500_TEX_WMASK(x) ((x) << 11) -#define R500_ALU_WMASK(x) ((x) << 11) -#define R500_ALU_OMASK(x) ((x) << 15) -#define R500_W_OMASK (1 << 31) - -static struct r5xx_fragment_shader r5xx_passthrough_fragment_shader = { - .shader.stack_size = 0, - .instruction_count = 1, - .instructions[0].inst0 = R500_INST_TYPE_OUT | - R500_INST_TEX_SEM_WAIT | R500_INST_LAST | - R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, - .instructions[0].inst1 = - R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | - R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, - .instructions[0].inst2 = - R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | - R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, - .instructions[0].inst3 = - R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | - R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | - R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | - R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, - .instructions[0].inst4 = - R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, - .instructions[0].inst5 = - R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | - R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | - R500_ALU_RGBA_A_SWIZ_0, -}; - -static struct r5xx_fragment_shader r5xx_texture_fragment_shader = { - .shader.stack_size = 1, - .instruction_count = 2, - .instructions[0].inst0 = R500_INST_TYPE_TEX | - R500_INST_TEX_SEM_WAIT | - R500_INST_RGB_WMASK_RGB | R500_INST_ALPHA_WMASK | - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, - .instructions[0].inst1 = R500_TEX_ID(0) | R500_TEX_INST_LD | - R500_TEX_SEM_ACQUIRE | R500_TEX_IGNORE_UNCOVERED, - .instructions[0].inst2 = R500_TEX_SRC_ADDR(0) | - R500_TEX_SRC_S_SWIZ_R | R500_TEX_SRC_T_SWIZ_G | - R500_TEX_SRC_R_SWIZ_B | R500_TEX_SRC_Q_SWIZ_A | - R500_TEX_DST_ADDR(0) | - R500_TEX_DST_R_SWIZ_R | R500_TEX_DST_G_SWIZ_G | - R500_TEX_DST_B_SWIZ_B | R500_TEX_DST_A_SWIZ_A, - .instructions[0].inst3 = 0x0, - .instructions[0].inst4 = 0x0, - .instructions[0].inst5 = 0x0, - .instructions[1].inst0 = R500_INST_TYPE_OUT | - R500_INST_TEX_SEM_WAIT | R500_INST_LAST | - R500_INST_RGB_OMASK_RGB | R500_INST_ALPHA_OMASK | - R500_INST_RGB_CLAMP | R500_INST_ALPHA_CLAMP, - .instructions[1].inst1 = - R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | - R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST, - .instructions[1].inst2 = - R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | - R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST, - .instructions[1].inst3 = - R500_ALU_RGB_SEL_A_SRC0 | R500_ALU_RGB_R_SWIZ_A_R | - R500_ALU_RGB_G_SWIZ_A_G | R500_ALU_RGB_B_SWIZ_A_B | - R500_ALU_RGB_SEL_B_SRC0 | R500_ALU_RGB_R_SWIZ_B_R | - R500_ALU_RGB_B_SWIZ_B_G | R500_ALU_RGB_G_SWIZ_B_B, - .instructions[1].inst4 = - R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A, - .instructions[1].inst5 = - R500_ALU_RGBA_OP_CMP | R500_ALU_RGBA_R_SWIZ_0 | - R500_ALU_RGBA_G_SWIZ_0 | R500_ALU_RGBA_B_SWIZ_0 | - R500_ALU_RGBA_A_SWIZ_0, -}; - -struct r300_fs_asm; - -void r5xx_fs_finalize(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler); - -void r5xx_fs_instruction(struct r5xx_fragment_shader* fs, - struct r300_fs_asm* assembler, - struct tgsi_full_instruction* inst); +struct rX00_fragment_program_code r5xx_passthrough_fragment_shader; +struct rX00_fragment_program_code r5xx_texture_fragment_shader; #endif /* R5XX_FS_H */ -- cgit v1.2.3