From 622858884fc5923c9e7a0c1bb0e80b53f0acb5a7 Mon Sep 17 00:00:00 2001 From: Joakim Sindholt Date: Fri, 26 Jun 2009 01:08:13 +0200 Subject: r300-gallium: organize fragment/vertex shaders Appart from separating r3xx/r5xx fragment shaders, a more consistent naming scheme has been applied. From now on: r300 = all chips r3xx = R300/R400 only r5xx = R500 only This way r300_fragment_shader is the master struct, and the structs r3xx_fragment_shader and r5xx_fragment_shader inherits it. --- src/gallium/drivers/r300/Makefile | 6 +- src/gallium/drivers/r300/SConscript | 6 +- src/gallium/drivers/r300/r300_context.h | 12 +- src/gallium/drivers/r300/r300_debug.c | 54 +- src/gallium/drivers/r300/r300_debug.h | 17 +- src/gallium/drivers/r300/r300_emit.c | 8 +- src/gallium/drivers/r300/r300_emit.h | 4 +- src/gallium/drivers/r300/r300_fs.c | 109 ++++ src/gallium/drivers/r300/r300_fs.h | 36 ++ src/gallium/drivers/r300/r300_fs_inlines.h | 158 ++++++ src/gallium/drivers/r300/r300_shader_inlines.h | 47 ++ src/gallium/drivers/r300/r300_state.c | 14 +- src/gallium/drivers/r300/r300_state_shader.c | 718 ------------------------- src/gallium/drivers/r300/r300_state_shader.h | 220 -------- src/gallium/drivers/r300/r300_state_tcl.c | 412 -------------- src/gallium/drivers/r300/r300_state_tcl.h | 164 ------ src/gallium/drivers/r300/r300_surface.c | 16 +- src/gallium/drivers/r300/r300_surface.h | 12 +- src/gallium/drivers/r300/r300_vs.c | 412 ++++++++++++++ src/gallium/drivers/r300/r300_vs.h | 157 ++++++ src/gallium/drivers/r300/r3xx_fs.c | 96 ++++ src/gallium/drivers/r300/r3xx_fs.h | 76 +++ src/gallium/drivers/r300/r5xx_fs.c | 467 ++++++++++++++++ src/gallium/drivers/r300/r5xx_fs.h | 132 +++++ 24 files changed, 1766 insertions(+), 1587 deletions(-) create mode 100644 src/gallium/drivers/r300/r300_fs.c create mode 100644 src/gallium/drivers/r300/r300_fs.h create mode 100644 src/gallium/drivers/r300/r300_fs_inlines.h create mode 100644 src/gallium/drivers/r300/r300_shader_inlines.h delete mode 100644 src/gallium/drivers/r300/r300_state_shader.c delete mode 100644 src/gallium/drivers/r300/r300_state_shader.h delete mode 100644 src/gallium/drivers/r300/r300_state_tcl.c delete mode 100644 src/gallium/drivers/r300/r300_state_tcl.h create mode 100644 src/gallium/drivers/r300/r300_vs.c create mode 100644 src/gallium/drivers/r300/r300_vs.h create mode 100644 src/gallium/drivers/r300/r3xx_fs.c create mode 100644 src/gallium/drivers/r300/r3xx_fs.h create mode 100644 src/gallium/drivers/r300/r5xx_fs.c create mode 100644 src/gallium/drivers/r300/r5xx_fs.h (limited to 'src/gallium/drivers/r300') diff --git a/src/gallium/drivers/r300/Makefile b/src/gallium/drivers/r300/Makefile index e44f9b9dfc..faceec9842 100644 --- a/src/gallium/drivers/r300/Makefile +++ b/src/gallium/drivers/r300/Makefile @@ -4,20 +4,22 @@ include $(TOP)/configs/current LIBNAME = r300 C_SOURCES = \ + r3xx_fs.c \ + r5xx_fs.c \ r300_chipset.c \ r300_clear.c \ r300_context.c \ r300_debug.c \ r300_emit.c \ r300_flush.c \ + r300_fs.c \ r300_query.c \ r300_render.c \ r300_screen.c \ r300_state.c \ r300_state_derived.c \ r300_state_invariant.c \ - r300_state_shader.c \ - r300_state_tcl.c \ + r300_vs.c \ r300_surface.c \ r300_texture.c diff --git a/src/gallium/drivers/r300/SConscript b/src/gallium/drivers/r300/SConscript index 182ed2d459..493d7b28bc 100644 --- a/src/gallium/drivers/r300/SConscript +++ b/src/gallium/drivers/r300/SConscript @@ -5,20 +5,22 @@ env = env.Clone() r300 = env.ConvenienceLibrary( target = 'r300', source = [ + 'r3xx_fs.c', + 'r5xx_fs.c', 'r300_chipset.c', 'r300_clear.c', 'r300_context.c', 'r300_debug.c', 'r300_emit.c', 'r300_flush.c', + 'r300_fs.c', 'r300_query.c', 'r300_render.c', 'r300_screen.c', 'r300_state.c', 'r300_state_derived.c', 'r300_state_invariant.c', - 'r300_state_shader.c', - 'r300_state_tcl.c', + 'r300_vs.c', 'r300_surface.c', 'r300_texture.c', ]) diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 27bc7fd1a9..ae7857498f 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -149,7 +149,7 @@ struct r300_constant_buffer { unsigned count; }; -struct r3xx_fragment_shader { +struct r300_fragment_shader { /* Parent class */ struct pipe_shader_state state; struct tgsi_shader_info info; @@ -165,9 +165,9 @@ struct r3xx_fragment_shader { boolean uses_imms; }; -struct r300_fragment_shader { +struct r3xx_fragment_shader { /* Parent class */ - struct r3xx_fragment_shader shader; + struct r300_fragment_shader shader; /* Number of ALU instructions */ int alu_instruction_count; @@ -190,9 +190,9 @@ struct r300_fragment_shader { } instructions[64]; /* XXX magic num */ }; -struct r500_fragment_shader { +struct r5xx_fragment_shader { /* Parent class */ - struct r3xx_fragment_shader shader; + struct r300_fragment_shader shader; /* Number of used instructions */ int instruction_count; @@ -300,7 +300,7 @@ struct r300_context { /* Depth, stencil, and alpha state. */ struct r300_dsa_state* dsa_state; /* Fragment shader. */ - struct r3xx_fragment_shader* fs; + struct r300_fragment_shader* fs; /* Framebuffer state. We currently don't need our own version of this. */ struct pipe_framebuffer_state framebuffer_state; /* Rasterizer state. */ diff --git a/src/gallium/drivers/r300/r300_debug.c b/src/gallium/drivers/r300/r300_debug.c index 678cd2b812..c83e8526cf 100644 --- a/src/gallium/drivers/r300/r300_debug.c +++ b/src/gallium/drivers/r300/r300_debug.c @@ -22,7 +22,7 @@ #include "r300_debug.h" -static void r300_dump_fs(struct r300_fragment_shader* fs) +void r3xx_dump_fs(struct r3xx_fragment_shader* fs) { int i; @@ -30,7 +30,7 @@ static void r300_dump_fs(struct r300_fragment_shader* fs) } } -void r500_fs_dump(struct r500_fragment_shader* fs) +void r5xx_fs_dump(struct r5xx_fragment_shader* fs) { int i; uint32_t inst; @@ -58,8 +58,8 @@ void r500_fs_dump(struct r500_fragment_shader* fs) inst & R500_INST_NOP ? "NOP" : "", inst & R500_INST_ALU_WAIT ? "ALU_WAIT" : ""); debug_printf("wmask: %s omask: %s\n", - r500_fs_mask[(inst >> 11) & 0xf], - r500_fs_mask[(inst >> 15) & 0xf]); + 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: @@ -85,36 +85,36 @@ void r500_fs_dump(struct r500_fragment_shader* fs) 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, r500_fs_swiz[(inst >> 2) & 0x7], - r500_fs_swiz[(inst >> 5) & 0x7], - r500_fs_swiz[(inst >> 8) & 0x7], + 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, - r500_fs_swiz[(inst >> 15) & 0x7], - r500_fs_swiz[(inst >> 18) & 0x7], - r500_fs_swiz[(inst >> 21) & 0x7], + 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", - r500_fs_op_alpha[inst & 0xf], (inst >> 4) & 0x7f, + r5xx_fs_op_alpha[inst & 0xf], (inst >> 4) & 0x7f, inst & (1<<11) ? "(rel)":"", (inst >> 12) & 0x3, - r500_fs_swiz[(inst >> 14) & 0x7], (inst >> 17) & 0x3, - (inst >> 19) & 0x3, r500_fs_swiz[(inst >> 21) & 0x7], + 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", - r500_fs_op_rgb[inst & 0xf], (inst >> 4) & 0x7f, + r5xx_fs_op_rgb[inst & 0xf], (inst >> 4) & 0x7f, inst & (1 << 11) ? "(rel)":"", (inst >> 12) & 0x3, - r500_fs_swiz[(inst >> 14) & 0x7], - r500_fs_swiz[(inst >> 17) & 0x7], - r500_fs_swiz[(inst >> 20) & 0x7], + r5xx_fs_swiz[(inst >> 14) & 0x7], + r5xx_fs_swiz[(inst >> 17) & 0x7], + r5xx_fs_swiz[(inst >> 20) & 0x7], (inst >> 23) & 0x3, (inst >> 25) & 0x3, - r500_fs_swiz[(inst >> 27) & 0x7], (inst >> 30) & 0x3); + r5xx_fs_swiz[(inst >> 27) & 0x7], (inst >> 30) & 0x3); break; case R500_INST_TYPE_FC: /* XXX don't even bother yet */ @@ -124,7 +124,7 @@ void r500_fs_dump(struct r500_fragment_shader* fs) debug_printf(" 1: TEX_INST 0x%08x: id: %d " "op:%s, %s, %s %s\n", inst, (inst >> 16) & 0xf, - r500_fs_tex[(inst >> 22) & 0x7], + r5xx_fs_tex[(inst >> 22) & 0x7], (inst & (1 << 25)) ? "ACQ" : "", (inst & (1 << 26)) ? "IGNUNC" : "", (inst & (1 << 27)) ? "UNSCALED" : "SCALED"); @@ -133,15 +133,15 @@ void r500_fs_dump(struct r500_fragment_shader* fs) 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)" : "", - r500_fs_swiz[(inst >> 8) & 0x3], - r500_fs_swiz[(inst >> 10) & 0x3], - r500_fs_swiz[(inst >> 12) & 0x3], - r500_fs_swiz[(inst >> 14) & 0x3], + 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)" : "", - r500_fs_swiz[(inst >> 24) & 0x3], - r500_fs_swiz[(inst >> 26) & 0x3], - r500_fs_swiz[(inst >> 28) & 0x3], - r500_fs_swiz[(inst >> 30) & 0x3]); + 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); diff --git a/src/gallium/drivers/r300/r300_debug.h b/src/gallium/drivers/r300/r300_debug.h index c86410ec0a..6b58c1e250 100644 --- a/src/gallium/drivers/r300/r300_debug.h +++ b/src/gallium/drivers/r300/r300_debug.h @@ -24,10 +24,10 @@ #define R300_DEBUG_H #include "r300_reg.h" -#include "r300_state_shader.h" -#include "r300_state_tcl.h" +#include "r300_fs.h" +#include "r300_vs.h" -static char* r500_fs_swiz[] = { +static char* r5xx_fs_swiz[] = { " R", " G", " B", @@ -38,7 +38,7 @@ static char* r500_fs_swiz[] = { " U", }; -static char* r500_fs_op_rgb[] = { +static char* r5xx_fs_op_rgb[] = { "MAD", "DP3", "DP4", @@ -54,7 +54,7 @@ static char* r500_fs_op_rgb[] = { "MDV", }; -static char* r500_fs_op_alpha[] = { +static char* r5xx_fs_op_alpha[] = { "MAD", " DP", "MIN", @@ -73,7 +73,7 @@ static char* r500_fs_op_alpha[] = { "MDV", }; -static char* r500_fs_mask[] = { +static char* r5xx_fs_mask[] = { "NONE", "R ", " G ", @@ -92,7 +92,7 @@ static char* r500_fs_mask[] = { "RGBA", }; -static char* r500_fs_tex[] = { +static char* r5xx_fs_tex[] = { " NOP", " LD", "TEXKILL", @@ -203,7 +203,8 @@ static char* r300_vs_swiz_debug[] = { "U", }; -void r500_fs_dump(struct r500_fragment_shader* fs); +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); diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 93cf6909a3..1d297e8593 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -110,7 +110,7 @@ void r300_emit_dsa_state(struct r300_context* r300, } void r300_emit_fragment_shader(struct r300_context* r300, - struct r300_fragment_shader* fs) + struct r3xx_fragment_shader* fs) { int i; CS_LOCALS(r300); @@ -142,7 +142,7 @@ void r300_emit_fragment_shader(struct r300_context* r300, } void r500_emit_fragment_shader(struct r300_context* r300, - struct r500_fragment_shader* fs) + struct r5xx_fragment_shader* fs) { int i; struct r300_constant_buffer* constants = @@ -570,10 +570,10 @@ validate: if (r300->dirty_state & R300_NEW_FRAGMENT_SHADER) { if (r300screen->caps->is_r500) { r500_emit_fragment_shader(r300, - (struct r500_fragment_shader*)r300->fs); + (struct r5xx_fragment_shader*)r300->fs); } else { r300_emit_fragment_shader(r300, - (struct r300_fragment_shader*)r300->fs); + (struct r3xx_fragment_shader*)r300->fs); } 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 946f625bd8..196b6c58d3 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -43,10 +43,10 @@ void r300_emit_dsa_state(struct r300_context* r300, struct r300_dsa_state* dsa); void r300_emit_fragment_shader(struct r300_context* r300, - struct r300_fragment_shader* fs); + struct r3xx_fragment_shader* fs); void r500_emit_fragment_shader(struct r300_context* r300, - struct r500_fragment_shader* fs); + struct r5xx_fragment_shader* fs); 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 new file mode 100644 index 0000000000..4b304306d0 --- /dev/null +++ b/src/gallium/drivers/r300/r300_fs.c @@ -0,0 +1,109 @@ +/* + * 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. */ + +#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]; + + 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; + } + + tgsi_parse_init(&parser, fs->state.tokens); + + while (!tgsi_parse_end_of_tokens(&parser)) { + tgsi_parse_token(&parser); + + /* 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); + 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.ImmediateFloat32[i] + .Float; + } + assembler->imm_count++; + 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); + } + 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); + } + + tgsi_dump(fs->state.tokens, 0); + /* XXX finish r300 dumper too */ + if (is_r500) { + r5xx_fs_dump((struct r5xx_fragment_shader*)fs); + } + + tgsi_parse_free(&parser); + FREE(assembler); +} diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h new file mode 100644 index 0000000000..18deb7a05e --- /dev/null +++ b/src/gallium/drivers/r300/r300_fs.h @@ -0,0 +1,36 @@ +/* + * 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_H +#define R300_FS_H + +#include "tgsi/tgsi_dump.h" + +#include "r300_context.h" +#include "r3xx_fs.h" +#include "r5xx_fs.h" + +void r300_translate_fragment_shader(struct r300_context* r300, + struct r300_fragment_shader* fs); + + #endif /* R300_FS_H */ diff --git a/src/gallium/drivers/r300/r300_fs_inlines.h b/src/gallium/drivers/r300/r300_fs_inlines.h new file mode 100644 index 0000000000..be4be9465e --- /dev/null +++ b/src/gallium/drivers/r300/r300_fs_inlines.h @@ -0,0 +1,158 @@ +/* + * 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_shader_inlines.h b/src/gallium/drivers/r300/r300_shader_inlines.h new file mode 100644 index 0000000000..a04f45b03e --- /dev/null +++ b/src/gallium/drivers/r300/r300_shader_inlines.h @@ -0,0 +1,47 @@ +/* + * Copyright 2009 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_SHADER_INLINES_H +#define R300_SHADER_INLINES_H + +/* TGSI constants. TGSI is like XML: If it can't solve your problems, you're + * not using enough of it. */ +static const struct tgsi_full_src_register r300_constant_zero = { + .SrcRegister.Extended = TRUE, + .SrcRegister.File = TGSI_FILE_NULL, + .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO, + .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO, + .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO, + .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO, +}; + +static const struct tgsi_full_src_register r300_constant_one = { + .SrcRegister.Extended = TRUE, + .SrcRegister.File = TGSI_FILE_NULL, + .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ONE, + .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ONE, + .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ONE, + .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ONE, +}; + +#endif /* R300_SHADER_INLINES_H */ diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 01e2b51153..d70ef6ba28 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -29,7 +29,7 @@ #include "r300_context.h" #include "r300_reg.h" #include "r300_state_inlines.h" -#include "r300_state_shader.h" +#include "r300_fs.h" /* r300_state: Functions used to intialize state context by translating * Gallium state objects into semi-native r300 state objects. */ @@ -283,14 +283,12 @@ static void* r300_create_fs_state(struct pipe_context* pipe, const struct pipe_shader_state* shader) { struct r300_context* r300 = r300_context(pipe); - struct r3xx_fragment_shader* fs = NULL; + struct r300_fragment_shader* fs = NULL; if (r300_screen(r300->context.screen)->caps->is_r500) { - fs = - (struct r3xx_fragment_shader*)CALLOC_STRUCT(r500_fragment_shader); + fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r5xx_fragment_shader); } else { - fs = - (struct r3xx_fragment_shader*)CALLOC_STRUCT(r300_fragment_shader); + fs = (struct r300_fragment_shader*)CALLOC_STRUCT(r3xx_fragment_shader); } /* Copy state directly into shader. */ @@ -306,7 +304,7 @@ static void* r300_create_fs_state(struct pipe_context* pipe, static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); - struct r3xx_fragment_shader* fs = (struct r3xx_fragment_shader*)shader; + struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; if (fs == NULL) { r300->fs = NULL; @@ -324,7 +322,7 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) /* Delete fragment shader state. */ static void r300_delete_fs_state(struct pipe_context* pipe, void* shader) { - struct r3xx_fragment_shader* fs = (struct r3xx_fragment_shader*)shader; + struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; FREE(fs->state.tokens); FREE(shader); } diff --git a/src/gallium/drivers/r300/r300_state_shader.c b/src/gallium/drivers/r300/r300_state_shader.c deleted file mode 100644 index cc7f6a7c4b..0000000000 --- a/src/gallium/drivers/r300/r300_state_shader.c +++ /dev/null @@ -1,718 +0,0 @@ -/* - * Copyright 2008 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_state_shader.h" - -static 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)); -} - -static INLINE unsigned r500_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 r500_rgba_swiz(struct tgsi_full_src_register* reg) -{ - if (reg->SrcRegister.Extended) { - return r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleX) | - (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleY) << 3) | - (r500_fix_swiz(reg->SrcRegisterExtSwz.ExtSwizzleZ) << 6) | - (r500_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 r500_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 r500_rgb_swiz(struct tgsi_full_src_register* reg) -{ - /* Only the first 9 bits... */ - return (r500_rgba_swiz(reg) & 0x1ff) | - (reg->SrcRegister.Negate ? (1 << 9) : 0) | - (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0); -} - -static INLINE uint32_t r500_alpha_swiz(struct tgsi_full_src_register* reg) -{ - /* Only the last 3 bits... */ - return (r500_rgba_swiz(reg) >> 9) | - (reg->SrcRegister.Negate ? (1 << 9) : 0) | - (reg->SrcRegisterExtMod.Absolute ? (1 << 10) : 0); -} - -static INLINE uint32_t r300_rgb_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_MOV: - return R300_ALU_OUTC_CMP; - default: - return 0; - } -} - -static INLINE uint32_t r300_alpha_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_MOV: - return R300_ALU_OUTA_CMP; - default: - return 0; - } -} - -static INLINE uint32_t r500_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 r500_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 r500_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; - } -} - -static INLINE void r300_emit_maths(struct r300_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; - - fs->instructions[i].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_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_ALPHA_SWIZB(R300_ALU_ARGA_SRC0A) | - R300_ALPHA_SWIZC(R300_ALU_ARGA_ZERO) | - r300_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; - - fs->alu_instruction_count++; -} - -/* Setup an ALU operation. */ -static INLINE void r500_emit_maths(struct r500_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(r500_rgb_swiz(&src[2])) | - R500_ALU_RGBA_ALPHA_SEL_C_SRC2 | - R500_SWIZ_ALPHA_C(r500_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(r500_rgb_swiz(&src[1])); - fs->instructions[i].inst4 |= - R500_ALPHA_SEL_B_SRC1 | - R500_SWIZ_ALPHA_B(r500_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(r500_rgb_swiz(&src[0])); - fs->instructions[i].inst4 |= - R500_ALPHA_SEL_A_SRC0 | - R500_SWIZ_ALPHA_A(r500_alpha_swiz(&src[0])); - break; - } - - fs->instructions[i].inst4 |= r500_alpha_op(op); - fs->instructions[i].inst5 |= r500_rgba_op(op); - - fs->instruction_count++; -} - -static INLINE void r500_emit_tex(struct r500_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 | - r500_tex_op(op); - fs->instructions[i].inst2 = - R500_TEX_SRC_ADDR(r300_fs_src(assembler, &src->SrcRegister)) | - R500_SWIZ_TEX_STRQ(r500_strq_swiz(src)) | - R500_TEX_DST_ADDR(r300_fs_dst(assembler, &dst->DstRegister)) | - 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] = r500_constant_zero; - r500_emit_maths(fs, assembler, src, dst, TGSI_OPCODE_MOV, 3); - } else { - fs->instruction_count++; - } -} - -static void r300_fs_instruction(struct r300_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] = r500_constant_zero; - r300_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; - } -} - -static void r500_fs_instruction(struct r500_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: - r500_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: - r500_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]; - r500_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] = r500_constant_one; - r500_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] = r500_constant_zero; - r500_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, 3); - break; - case TGSI_OPCODE_MAD: - r500_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] = r500_constant_zero; - r500_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; - r500_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]; - r500_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; - r500_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] = r500_constant_zero; - r500_emit_maths(fs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], TGSI_OPCODE_MUL, 3); - inst->FullDstRegisters[0] = inst->FullDstRegisters[1]; - r500_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: - r500_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; - } -} - -static void r300_fs_finalize(struct r3xx_fragment_shader* fs, - struct r300_fs_asm* assembler) -{ - fs->stack_size = assembler->temp_count + assembler->temp_offset + 1; -} - -static void r500_fs_finalize(struct r500_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 r300_translate_fragment_shader(struct r300_context* r300, - struct r3xx_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]; - - 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 r500_fragment_shader*)fs)->instruction_count = 0; - } - - tgsi_parse_init(&parser, fs->state.tokens); - - while (!tgsi_parse_end_of_tokens(&parser)) { - tgsi_parse_token(&parser); - - /* 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); - 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.ImmediateFloat32[i] - .Float; - } - assembler->imm_count++; - break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - if (is_r500) { - r500_fs_instruction((struct r500_fragment_shader*)fs, - assembler, &parser.FullToken.FullInstruction); - } else { - r300_fs_instruction((struct r300_fragment_shader*)fs, - assembler, &parser.FullToken.FullInstruction); - } - 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); - r300_fs_finalize(fs, assembler); - if (is_r500) { - r500_fs_finalize((struct r500_fragment_shader*)fs, assembler); - } - - tgsi_dump(fs->state.tokens); - /* XXX finish r300 dumper too */ - if (is_r500) { - r500_fs_dump((struct r500_fragment_shader*)fs); - } - - tgsi_parse_free(&parser); - FREE(assembler); -} diff --git a/src/gallium/drivers/r300/r300_state_shader.h b/src/gallium/drivers/r300/r300_state_shader.h deleted file mode 100644 index b6087404ce..0000000000 --- a/src/gallium/drivers/r300/r300_state_shader.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright 2008 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_STATE_SHADER_H -#define R300_STATE_SHADER_H - -#include "tgsi/tgsi_parse.h" - -#include "r300_context.h" -#include "r300_debug.h" -#include "r300_reg.h" -#include "r300_screen.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) - -/* TGSI constants. TGSI is like XML: If it can't solve your problems, you're - * not using enough of it. */ -static const struct tgsi_full_src_register r500_constant_zero = { - .SrcRegister.Extended = TRUE, - .SrcRegister.File = TGSI_FILE_NULL, - .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO, -}; - -static const struct tgsi_full_src_register r500_constant_one = { - .SrcRegister.Extended = TRUE, - .SrcRegister.File = TGSI_FILE_NULL, - .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ONE, - .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ONE, - .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ONE, - .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ONE, -}; - -/* 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; -}; - -void r300_translate_fragment_shader(struct r300_context* r300, - struct r3xx_fragment_shader* fs); - -static struct r300_fragment_shader r300_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 r500_fragment_shader r500_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 r300_fragment_shader r300_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, -}; - -static struct r500_fragment_shader r500_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, -}; - -#endif /* R300_STATE_SHADER_H */ diff --git a/src/gallium/drivers/r300/r300_state_tcl.c b/src/gallium/drivers/r300/r300_state_tcl.c deleted file mode 100644 index 8cf8250425..0000000000 --- a/src/gallium/drivers/r300/r300_state_tcl.c +++ /dev/null @@ -1,412 +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_state_tcl.h" - -static void r300_vs_declare(struct r300_vs_asm* assembler, - struct tgsi_full_declaration* decl) -{ - switch (decl->Declaration.File) { - case TGSI_FILE_INPUT: - break; - case TGSI_FILE_OUTPUT: - switch (decl->Semantic.SemanticName) { - case TGSI_SEMANTIC_POSITION: - assembler->tab[decl->DeclarationRange.First] = 0; - break; - case TGSI_SEMANTIC_COLOR: - assembler->tab[decl->DeclarationRange.First] = - (assembler->point_size ? 1 : 0) + - assembler->out_colors; - break; - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - /* XXX multiple? */ - assembler->tab[decl->DeclarationRange.First] = - (assembler->point_size ? 1 : 0) + - assembler->out_colors + - assembler->out_texcoords; - break; - case TGSI_SEMANTIC_PSIZE: - assembler->tab[decl->DeclarationRange.First] = 1; - break; - default: - debug_printf("r300: vs: Bad semantic declaration %d\n", - decl->Semantic.SemanticName); - break; - } - break; - case TGSI_FILE_CONSTANT: - break; - case TGSI_FILE_TEMPORARY: - assembler->temp_count++; - break; - default: - debug_printf("r300: vs: Bad file %d\n", decl->Declaration.File); - break; - } -} - -static INLINE unsigned r300_vs_src_type(struct r300_vs_asm* assembler, - struct tgsi_src_register* src) -{ - switch (src->File) { - case TGSI_FILE_NULL: - case TGSI_FILE_INPUT: - /* Probably a zero or one swizzle */ - return R300_PVS_SRC_REG_INPUT; - case TGSI_FILE_TEMPORARY: - return R300_PVS_SRC_REG_TEMPORARY; - case TGSI_FILE_CONSTANT: - case TGSI_FILE_IMMEDIATE: - return R300_PVS_SRC_REG_CONSTANT; - default: - debug_printf("r300: vs: Unimplemented src type %d\n", src->File); - break; - } - return 0; -} - -static INLINE unsigned r300_vs_src(struct r300_vs_asm* assembler, - struct tgsi_src_register* src) -{ - switch (src->File) { - case TGSI_FILE_NULL: - case TGSI_FILE_INPUT: - case TGSI_FILE_TEMPORARY: - case TGSI_FILE_CONSTANT: - return src->Index; - case TGSI_FILE_IMMEDIATE: - return src->Index + assembler->imm_offset; - default: - debug_printf("r300: vs: Unimplemented src type %d\n", src->File); - break; - } - return 0; -} - -static INLINE unsigned r300_vs_dst_type(struct r300_vs_asm* assembler, - struct tgsi_dst_register* dst) -{ - switch (dst->File) { - case TGSI_FILE_TEMPORARY: - return R300_PVS_DST_REG_TEMPORARY; - case TGSI_FILE_OUTPUT: - return R300_PVS_DST_REG_OUT; - default: - debug_printf("r300: vs: Unimplemented dst type %d\n", dst->File); - break; - } - return 0; -} - -static INLINE unsigned r300_vs_dst(struct r300_vs_asm* assembler, - struct tgsi_dst_register* dst) -{ - switch (dst->File) { - case TGSI_FILE_TEMPORARY: - return dst->Index; - case TGSI_FILE_OUTPUT: - return assembler->tab[dst->Index]; - default: - debug_printf("r300: vs: Unimplemented dst %d\n", dst->File); - break; - } - return 0; -} - -static uint32_t r300_vs_op(unsigned op) -{ - switch (op) { - case TGSI_OPCODE_DP3: - case TGSI_OPCODE_DP4: - return R300_VE_DOT_PRODUCT; - case TGSI_OPCODE_MUL: - return R300_VE_MULTIPLY; - case TGSI_OPCODE_ADD: - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SUB: - case TGSI_OPCODE_SWZ: - return R300_VE_ADD; - case TGSI_OPCODE_MAX: - return R300_VE_MAXIMUM; - case TGSI_OPCODE_SLT: - return R300_VE_SET_LESS_THAN; - case TGSI_OPCODE_RSQ: - return R300_PVS_DST_MATH_INST | R300_ME_RECIP_DX; - case TGSI_OPCODE_MAD: - return R300_PVS_DST_MACRO_INST | R300_PVS_MACRO_OP_2CLK_MADD; - default: - break; - } - return 0; -} - -static uint32_t r300_vs_swiz(struct tgsi_full_src_register* reg) -{ - if (reg->SrcRegister.Extended) { - return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | - reg->SrcRegisterExtSwz.ExtSwizzleX | - (reg->SrcRegisterExtSwz.ExtSwizzleY << 3) | - (reg->SrcRegisterExtSwz.ExtSwizzleZ << 6) | - (reg->SrcRegisterExtSwz.ExtSwizzleW << 9); - } else { - return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | - reg->SrcRegister.SwizzleX | - (reg->SrcRegister.SwizzleY << 3) | - (reg->SrcRegister.SwizzleZ << 6) | - (reg->SrcRegister.SwizzleW << 9); - } -} - -/* XXX icky icky icky icky */ -static uint32_t r300_vs_scalar_swiz(struct tgsi_full_src_register* reg) -{ - if (reg->SrcRegister.Extended) { - return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | - reg->SrcRegisterExtSwz.ExtSwizzleX | - (reg->SrcRegisterExtSwz.ExtSwizzleX << 3) | - (reg->SrcRegisterExtSwz.ExtSwizzleX << 6) | - (reg->SrcRegisterExtSwz.ExtSwizzleX << 9); - } else { - return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | - reg->SrcRegister.SwizzleX | - (reg->SrcRegister.SwizzleX << 3) | - (reg->SrcRegister.SwizzleX << 6) | - (reg->SrcRegister.SwizzleX << 9); - } -} - -/* XXX scalar stupidity */ -static void r300_vs_emit_inst(struct r300_vertex_shader* vs, - struct r300_vs_asm* assembler, - struct tgsi_full_src_register* src, - struct tgsi_full_dst_register* dst, - unsigned op, - unsigned count, - boolean is_scalar) -{ - int i = vs->instruction_count; - vs->instructions[i].inst0 = R300_PVS_DST_OPCODE(r300_vs_op(op)) | - R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler, &dst->DstRegister)) | - R300_PVS_DST_OFFSET(r300_vs_dst(assembler, &dst->DstRegister)) | - R300_PVS_DST_WE(dst->DstRegister.WriteMask); - switch (count) { - case 3: - vs->instructions[i].inst3 = - R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, - &src[2].SrcRegister)) | - R300_PVS_SRC_OFFSET(r300_vs_src(assembler, - &src[2].SrcRegister)) | - R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[2])); - /* Fall through */ - case 2: - vs->instructions[i].inst2 = - R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, - &src[1].SrcRegister)) | - R300_PVS_SRC_OFFSET(r300_vs_src(assembler, - &src[1].SrcRegister)) | - R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[1])); - /* Fall through */ - case 1: - vs->instructions[i].inst1 = - R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, - &src[0].SrcRegister)) | - R300_PVS_SRC_OFFSET(r300_vs_src(assembler, - &src[0].SrcRegister)) | - /* XXX the icky, it burns */ - R300_PVS_SRC_SWIZZLE(is_scalar ? r300_vs_scalar_swiz(&src[0]) - : r300_vs_swiz(&src[0])); - break; - } - vs->instruction_count++; -} - -static void r300_vs_instruction(struct r300_vertex_shader* vs, - struct r300_vs_asm* assembler, - struct tgsi_full_instruction* inst) -{ - switch (inst->Instruction.Opcode) { - case TGSI_OPCODE_RSQ: - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 1, TRUE); - break; - case TGSI_OPCODE_SUB: - inst->FullSrcRegisters[1].SrcRegister.Negate = - !inst->FullSrcRegisters[1].SrcRegister.Negate; - /* Fall through */ - case TGSI_OPCODE_ADD: - case TGSI_OPCODE_MUL: - case TGSI_OPCODE_MAX: - case TGSI_OPCODE_SLT: - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 2, FALSE); - break; - case TGSI_OPCODE_DP3: - /* Set alpha swizzle to zero for src0 and src1 */ - 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_ZERO; - if (!inst->FullSrcRegisters[1].SrcRegister.Extended) { - inst->FullSrcRegisters[1].SrcRegister.Extended = TRUE; - inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleX = - inst->FullSrcRegisters[1].SrcRegister.SwizzleX; - inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleY = - inst->FullSrcRegisters[1].SrcRegister.SwizzleY; - inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleZ = - inst->FullSrcRegisters[1].SrcRegister.SwizzleZ; - } - inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleW = - TGSI_EXTSWIZZLE_ZERO; - /* Fall through */ - case TGSI_OPCODE_DP4: - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 2, FALSE); - break; - case TGSI_OPCODE_MOV: - case TGSI_OPCODE_SWZ: - inst->FullSrcRegisters[1] = r300_constant_zero; - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 2, FALSE); - break; - case TGSI_OPCODE_MAD: - r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, - &inst->FullDstRegisters[0], inst->Instruction.Opcode, - 3, FALSE); - break; - case TGSI_OPCODE_END: - break; - default: - debug_printf("r300: vs: Bad opcode %d\n", - inst->Instruction.Opcode); - break; - } -} - -static void r300_vs_init(struct r300_vertex_shader* vs, - struct r300_vs_asm* assembler) -{ - struct tgsi_shader_info* info = &vs->info; - int i; - - for (i = 0; i < info->num_outputs; i++) { - switch (info->output_semantic_name[i]) { - case TGSI_SEMANTIC_PSIZE: - assembler->point_size = TRUE; - break; - case TGSI_SEMANTIC_COLOR: - assembler->out_colors++; - break; - case TGSI_SEMANTIC_FOG: - case TGSI_SEMANTIC_GENERIC: - assembler->out_texcoords++; - break; - } - } - - vs->instruction_count = 0; -} - -void r300_translate_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs) -{ - struct tgsi_parse_context parser; - int i; - struct r300_constant_buffer* consts = - &r300->shader_constants[PIPE_SHADER_VERTEX]; - - struct r300_vs_asm* assembler = CALLOC_STRUCT(r300_vs_asm); - if (assembler == NULL) { - return; - } - - /* Init assembler. */ - r300_vs_init(vs, assembler); - - /* Setup starting offset for immediates. */ - assembler->imm_offset = consts->user_count; - - tgsi_parse_init(&parser, vs->state.tokens); - - while (!tgsi_parse_end_of_tokens(&parser)) { - tgsi_parse_token(&parser); - - /* 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_vs_declare(assembler, &parser.FullToken.FullDeclaration); - 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.ImmediateFloat32[i] - .Float; - } - assembler->imm_count++; - break; - case TGSI_TOKEN_TYPE_INSTRUCTION: - r300_vs_instruction(vs, assembler, - &parser.FullToken.FullInstruction); - break; - } - } - - debug_printf("r300: vs: %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; - vs->uses_imms = assembler->imm_count; - debug_printf("r300: vs: %d total constants, " - "%d from user and %d from immediates\n", consts->count, - consts->user_count, assembler->imm_count); - - debug_printf("r300: vs: tab: %d %d %d %d\n", assembler->tab[0], - assembler->tab[1], assembler->tab[2], assembler->tab[3]); - - tgsi_dump(vs->state.tokens); - /* XXX finish r300 vertex shader dumper */ - r300_vs_dump(vs); - - tgsi_parse_free(&parser); - FREE(assembler); -} diff --git a/src/gallium/drivers/r300/r300_state_tcl.h b/src/gallium/drivers/r300/r300_state_tcl.h deleted file mode 100644 index 2c8b586c2f..0000000000 --- a/src/gallium/drivers/r300/r300_state_tcl.h +++ /dev/null @@ -1,164 +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_STATE_TCL_H -#define R300_STATE_TCL_H - -#include "tgsi/tgsi_parse.h" - -#include "r300_context.h" -#include "r300_debug.h" -#include "r300_reg.h" -#include "r300_screen.h" - -/* XXX get these to r300_reg */ -#define R300_PVS_DST_OPCODE(x) ((x) << 0) -# define R300_VE_DOT_PRODUCT 1 -# define R300_VE_MULTIPLY 2 -# define R300_VE_ADD 3 -# define R300_VE_MAXIMUM 7 -# define R300_VE_SET_LESS_THAN 10 -#define R300_PVS_DST_MATH_INST (1 << 6) -# define R300_ME_RECIP_DX 6 -#define R300_PVS_DST_MACRO_INST (1 << 7) -# define R300_PVS_MACRO_OP_2CLK_MADD 0 -#define R300_PVS_DST_REG_TYPE(x) ((x) << 8) -# define R300_PVS_DST_REG_TEMPORARY 0 -# define R300_PVS_DST_REG_A0 1 -# define R300_PVS_DST_REG_OUT 2 -# define R300_PVS_DST_REG_OUT_REPL_X 3 -# define R300_PVS_DST_REG_ALT_TEMPORARY 4 -# define R300_PVS_DST_REG_INPUT 5 -#define R300_PVS_DST_OFFSET(x) ((x) << 13) -#define R300_PVS_DST_WE(x) ((x) << 20) -#define R300_PVS_DST_WE_XYZW (0xf << 20) - -#define R300_PVS_SRC_REG_TYPE(x) ((x) << 0) -# define R300_PVS_SRC_REG_TEMPORARY 0 -# define R300_PVS_SRC_REG_INPUT 1 -# define R300_PVS_SRC_REG_CONSTANT 2 -# define R300_PVS_SRC_REG_ALT_TEMPORARY 3 -#define R300_PVS_SRC_OFFSET(x) ((x) << 5) -#define R300_PVS_SRC_SWIZZLE(x) ((x) << 13) -# define R300_PVS_SRC_SELECT_X 0 -# define R300_PVS_SRC_SELECT_Y 1 -# define R300_PVS_SRC_SELECT_Z 2 -# define R300_PVS_SRC_SELECT_W 3 -# define R300_PVS_SRC_SELECT_FORCE_0 4 -# define R300_PVS_SRC_SELECT_FORCE_1 5 -# define R300_PVS_SRC_SWIZZLE_XYZW \ - ((R300_PVS_SRC_SELECT_X | (R300_PVS_SRC_SELECT_Y << 3) | \ - (R300_PVS_SRC_SELECT_Z << 6) | (R300_PVS_SRC_SELECT_W << 9)) << 13) -# define R300_PVS_SRC_SWIZZLE_ZERO \ - ((R300_PVS_SRC_SELECT_FORCE_0 | (R300_PVS_SRC_SELECT_FORCE_0 << 3) | \ - (R300_PVS_SRC_SELECT_FORCE_0 << 6) | \ - (R300_PVS_SRC_SELECT_FORCE_0 << 9)) << 13) -# define R300_PVS_SRC_SWIZZLE_ONE \ - ((R300_PVS_SRC_SELECT_FORCE_1 | (R300_PVS_SRC_SELECT_FORCE_1 << 3) | \ - (R300_PVS_SRC_SELECT_FORCE_1 << 6) | \ - (R300_PVS_SRC_SELECT_FORCE_1 << 9)) << 13) -#define R300_PVS_MODIFIER_X (1 << 25) -#define R300_PVS_MODIFIER_Y (1 << 26) -#define R300_PVS_MODIFIER_Z (1 << 27) -#define R300_PVS_MODIFIER_W (1 << 28) -#define R300_PVS_NEGATE_XYZW \ - (R300_PVS_MODIFIER_X | R300_PVS_MODIFIER_Y | \ - R300_PVS_MODIFIER_Z | R300_PVS_MODIFIER_W) - -static const struct tgsi_full_src_register r300_constant_zero = { - .SrcRegister.Extended = TRUE, - .SrcRegister.File = TGSI_FILE_NULL, - .SrcRegisterExtSwz.ExtSwizzleX = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleY = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleZ = TGSI_EXTSWIZZLE_ZERO, - .SrcRegisterExtSwz.ExtSwizzleW = TGSI_EXTSWIZZLE_ZERO, -}; - -/* Temporary struct used to hold assembly state while putting together - * fragment programs. */ -struct r300_vs_asm { - /* Pipe context. */ - struct r300_context* r300; - /* Number of colors. */ - unsigned color_count; - /* Number of texcoords. */ - unsigned tex_count; - /* 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; - /* Number of colors to write. */ - unsigned out_colors; - /* Number of texcoords to write. */ - unsigned out_texcoords; - /* Whether to emit point size. */ - boolean point_size; - /* Tab of declared outputs to OVM outputs. */ - unsigned tab[16]; -}; - -static struct r300_vertex_shader r300_passthrough_vertex_shader = { - /* XXX translate these back into normal instructions */ - .instruction_count = 2, - .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW, - .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW, - .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, - .instructions[0].inst3 = 0x0, - .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW, - .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW, - .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, - .instructions[1].inst3 = 0x0, -}; - -static struct r300_vertex_shader r300_texture_vertex_shader = { - /* XXX translate these back into normal instructions */ - .instruction_count = 2, - .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW, - .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW, - .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, - .instructions[0].inst3 = 0x0, - .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | - R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | - R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW, - .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | - R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW, - .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, - .instructions[1].inst3 = 0x0, -}; - -void r300_translate_vertex_shader(struct r300_context* r300, - struct r300_vertex_shader* vs); - -#endif /* R300_STATE_TCL_H */ diff --git a/src/gallium/drivers/r300/r300_surface.c b/src/gallium/drivers/r300/r300_surface.c index c9e2dff14e..75b5096919 100644 --- a/src/gallium/drivers/r300/r300_surface.c +++ b/src/gallium/drivers/r300/r300_surface.c @@ -151,11 +151,11 @@ validate: /* Fragment shader setup */ if (caps->is_r500) { - r500_emit_fragment_shader(r300, &r500_passthrough_fragment_shader); - r300_emit_rs_block_state(r300, &r500_rs_block_clear_state); + r500_emit_fragment_shader(r300, &r5xx_passthrough_fragment_shader); + r300_emit_rs_block_state(r300, &r5xx_rs_block_clear_state); } else { - r300_emit_fragment_shader(r300, &r300_passthrough_fragment_shader); - r300_emit_rs_block_state(r300, &r300_rs_block_clear_state); + r300_emit_fragment_shader(r300, &r3xx_passthrough_fragment_shader); + r300_emit_rs_block_state(r300, &r3xx_rs_block_clear_state); } BEGIN_CS(26); @@ -291,11 +291,11 @@ validate: /* Fragment shader setup */ if (caps->is_r500) { - r500_emit_fragment_shader(r300, &r500_texture_fragment_shader); - r300_emit_rs_block_state(r300, &r500_rs_block_copy_state); + r500_emit_fragment_shader(r300, &r5xx_texture_fragment_shader); + r300_emit_rs_block_state(r300, &r5xx_rs_block_copy_state); } else { - r300_emit_fragment_shader(r300, &r300_texture_fragment_shader); - r300_emit_rs_block_state(r300, &r300_rs_block_copy_state); + r300_emit_fragment_shader(r300, &r3xx_texture_fragment_shader); + r300_emit_rs_block_state(r300, &r3xx_rs_block_copy_state); } BEGIN_CS(30); diff --git a/src/gallium/drivers/r300/r300_surface.h b/src/gallium/drivers/r300/r300_surface.h index 9a4c39f58b..d01f0b143f 100644 --- a/src/gallium/drivers/r300/r300_surface.h +++ b/src/gallium/drivers/r300/r300_surface.h @@ -31,8 +31,8 @@ #include "r300_context.h" #include "r300_cs.h" #include "r300_emit.h" -#include "r300_state_shader.h" -#include "r300_state_tcl.h" +#include "r300_fs.h" +#include "r300_vs.h" #include "r300_state_inlines.h" static struct r300_blend_state blend_clear_state = { @@ -72,7 +72,7 @@ static struct r300_rs_state rs_clear_state = { .color_control = R300_SHADE_MODEL_FLAT, }; -static struct r300_rs_block r300_rs_block_clear_state = { +static struct r300_rs_block r3xx_rs_block_clear_state = { .ip[0] = R500_RS_SEL_S(R300_RS_SEL_K0) | R500_RS_SEL_T(R300_RS_SEL_K0) | R500_RS_SEL_R(R300_RS_SEL_K0) | @@ -82,7 +82,7 @@ static struct r300_rs_block r300_rs_block_clear_state = { .inst_count = 0, }; -static struct r300_rs_block r500_rs_block_clear_state = { +static struct r300_rs_block r5xx_rs_block_clear_state = { .ip[0] = R500_RS_SEL_S(R500_RS_IP_PTR_K0) | R500_RS_SEL_T(R500_RS_IP_PTR_K0) | R500_RS_SEL_R(R500_RS_IP_PTR_K0) | @@ -94,7 +94,7 @@ static struct r300_rs_block r500_rs_block_clear_state = { /* The following state is used for surface_copy only. */ -static struct r300_rs_block r300_rs_block_copy_state = { +static struct r300_rs_block r3xx_rs_block_copy_state = { .ip[0] = R500_RS_SEL_S(R300_RS_SEL_K0) | R500_RS_SEL_T(R300_RS_SEL_K0) | R500_RS_SEL_R(R300_RS_SEL_K0) | @@ -104,7 +104,7 @@ static struct r300_rs_block r300_rs_block_copy_state = { .inst_count = R300_RS_TX_OFFSET(0), }; -static struct r300_rs_block r500_rs_block_copy_state = { +static struct r300_rs_block r5xx_rs_block_copy_state = { .ip[0] = R500_RS_SEL_S(0) | R500_RS_SEL_T(1) | R500_RS_SEL_R(R500_RS_IP_PTR_K0) | diff --git a/src/gallium/drivers/r300/r300_vs.c b/src/gallium/drivers/r300/r300_vs.c new file mode 100644 index 0000000000..f87435f9f0 --- /dev/null +++ b/src/gallium/drivers/r300/r300_vs.c @@ -0,0 +1,412 @@ +/* + * 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_vs.h" + +static void r300_vs_declare(struct r300_vs_asm* assembler, + struct tgsi_full_declaration* decl) +{ + switch (decl->Declaration.File) { + case TGSI_FILE_INPUT: + break; + case TGSI_FILE_OUTPUT: + switch (decl->Semantic.SemanticName) { + case TGSI_SEMANTIC_POSITION: + assembler->tab[decl->DeclarationRange.First] = 0; + break; + case TGSI_SEMANTIC_COLOR: + assembler->tab[decl->DeclarationRange.First] = + (assembler->point_size ? 1 : 0) + + assembler->out_colors; + break; + case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_GENERIC: + /* XXX multiple? */ + assembler->tab[decl->DeclarationRange.First] = + (assembler->point_size ? 1 : 0) + + assembler->out_colors + + assembler->out_texcoords; + break; + case TGSI_SEMANTIC_PSIZE: + assembler->tab[decl->DeclarationRange.First] = 1; + break; + default: + debug_printf("r300: vs: Bad semantic declaration %d\n", + decl->Semantic.SemanticName); + break; + } + break; + case TGSI_FILE_CONSTANT: + break; + case TGSI_FILE_TEMPORARY: + assembler->temp_count++; + break; + default: + debug_printf("r300: vs: Bad file %d\n", decl->Declaration.File); + break; + } +} + +static INLINE unsigned r300_vs_src_type(struct r300_vs_asm* assembler, + struct tgsi_src_register* src) +{ + switch (src->File) { + case TGSI_FILE_NULL: + case TGSI_FILE_INPUT: + /* Probably a zero or one swizzle */ + return R300_PVS_SRC_REG_INPUT; + case TGSI_FILE_TEMPORARY: + return R300_PVS_SRC_REG_TEMPORARY; + case TGSI_FILE_CONSTANT: + case TGSI_FILE_IMMEDIATE: + return R300_PVS_SRC_REG_CONSTANT; + default: + debug_printf("r300: vs: Unimplemented src type %d\n", src->File); + break; + } + return 0; +} + +static INLINE unsigned r300_vs_src(struct r300_vs_asm* assembler, + struct tgsi_src_register* src) +{ + switch (src->File) { + case TGSI_FILE_NULL: + case TGSI_FILE_INPUT: + case TGSI_FILE_TEMPORARY: + case TGSI_FILE_CONSTANT: + return src->Index; + case TGSI_FILE_IMMEDIATE: + return src->Index + assembler->imm_offset; + default: + debug_printf("r300: vs: Unimplemented src type %d\n", src->File); + break; + } + return 0; +} + +static INLINE unsigned r300_vs_dst_type(struct r300_vs_asm* assembler, + struct tgsi_dst_register* dst) +{ + switch (dst->File) { + case TGSI_FILE_TEMPORARY: + return R300_PVS_DST_REG_TEMPORARY; + case TGSI_FILE_OUTPUT: + return R300_PVS_DST_REG_OUT; + default: + debug_printf("r300: vs: Unimplemented dst type %d\n", dst->File); + break; + } + return 0; +} + +static INLINE unsigned r300_vs_dst(struct r300_vs_asm* assembler, + struct tgsi_dst_register* dst) +{ + switch (dst->File) { + case TGSI_FILE_TEMPORARY: + return dst->Index; + case TGSI_FILE_OUTPUT: + return assembler->tab[dst->Index]; + default: + debug_printf("r300: vs: Unimplemented dst %d\n", dst->File); + break; + } + return 0; +} + +static uint32_t r300_vs_op(unsigned op) +{ + switch (op) { + case TGSI_OPCODE_DP3: + case TGSI_OPCODE_DP4: + return R300_VE_DOT_PRODUCT; + case TGSI_OPCODE_MUL: + return R300_VE_MULTIPLY; + case TGSI_OPCODE_ADD: + case TGSI_OPCODE_MOV: + case TGSI_OPCODE_SUB: + case TGSI_OPCODE_SWZ: + return R300_VE_ADD; + case TGSI_OPCODE_MAX: + return R300_VE_MAXIMUM; + case TGSI_OPCODE_SLT: + return R300_VE_SET_LESS_THAN; + case TGSI_OPCODE_RSQ: + return R300_PVS_DST_MATH_INST | R300_ME_RECIP_DX; + case TGSI_OPCODE_MAD: + return R300_PVS_DST_MACRO_INST | R300_PVS_MACRO_OP_2CLK_MADD; + default: + break; + } + return 0; +} + +static uint32_t r300_vs_swiz(struct tgsi_full_src_register* reg) +{ + if (reg->SrcRegister.Extended) { + return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | + reg->SrcRegisterExtSwz.ExtSwizzleX | + (reg->SrcRegisterExtSwz.ExtSwizzleY << 3) | + (reg->SrcRegisterExtSwz.ExtSwizzleZ << 6) | + (reg->SrcRegisterExtSwz.ExtSwizzleW << 9); + } else { + return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | + reg->SrcRegister.SwizzleX | + (reg->SrcRegister.SwizzleY << 3) | + (reg->SrcRegister.SwizzleZ << 6) | + (reg->SrcRegister.SwizzleW << 9); + } +} + +/* XXX icky icky icky icky */ +static uint32_t r300_vs_scalar_swiz(struct tgsi_full_src_register* reg) +{ + if (reg->SrcRegister.Extended) { + return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | + reg->SrcRegisterExtSwz.ExtSwizzleX | + (reg->SrcRegisterExtSwz.ExtSwizzleX << 3) | + (reg->SrcRegisterExtSwz.ExtSwizzleX << 6) | + (reg->SrcRegisterExtSwz.ExtSwizzleX << 9); + } else { + return (reg->SrcRegister.Negate ? (0xf << 12) : 0) | + reg->SrcRegister.SwizzleX | + (reg->SrcRegister.SwizzleX << 3) | + (reg->SrcRegister.SwizzleX << 6) | + (reg->SrcRegister.SwizzleX << 9); + } +} + +/* XXX scalar stupidity */ +static void r300_vs_emit_inst(struct r300_vertex_shader* vs, + struct r300_vs_asm* assembler, + struct tgsi_full_src_register* src, + struct tgsi_full_dst_register* dst, + unsigned op, + unsigned count, + boolean is_scalar) +{ + int i = vs->instruction_count; + vs->instructions[i].inst0 = R300_PVS_DST_OPCODE(r300_vs_op(op)) | + R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler, &dst->DstRegister)) | + R300_PVS_DST_OFFSET(r300_vs_dst(assembler, &dst->DstRegister)) | + R300_PVS_DST_WE(dst->DstRegister.WriteMask); + switch (count) { + case 3: + vs->instructions[i].inst3 = + R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, + &src[2].SrcRegister)) | + R300_PVS_SRC_OFFSET(r300_vs_src(assembler, + &src[2].SrcRegister)) | + R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[2])); + /* Fall through */ + case 2: + vs->instructions[i].inst2 = + R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, + &src[1].SrcRegister)) | + R300_PVS_SRC_OFFSET(r300_vs_src(assembler, + &src[1].SrcRegister)) | + R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[1])); + /* Fall through */ + case 1: + vs->instructions[i].inst1 = + R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler, + &src[0].SrcRegister)) | + R300_PVS_SRC_OFFSET(r300_vs_src(assembler, + &src[0].SrcRegister)) | + /* XXX the icky, it burns */ + R300_PVS_SRC_SWIZZLE(is_scalar ? r300_vs_scalar_swiz(&src[0]) + : r300_vs_swiz(&src[0])); + break; + } + vs->instruction_count++; +} + +static void r300_vs_instruction(struct r300_vertex_shader* vs, + struct r300_vs_asm* assembler, + struct tgsi_full_instruction* inst) +{ + switch (inst->Instruction.Opcode) { + case TGSI_OPCODE_RSQ: + r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], inst->Instruction.Opcode, + 1, TRUE); + break; + case TGSI_OPCODE_SUB: + inst->FullSrcRegisters[1].SrcRegister.Negate = + !inst->FullSrcRegisters[1].SrcRegister.Negate; + /* Fall through */ + case TGSI_OPCODE_ADD: + case TGSI_OPCODE_MUL: + case TGSI_OPCODE_MAX: + case TGSI_OPCODE_SLT: + r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], inst->Instruction.Opcode, + 2, FALSE); + break; + case TGSI_OPCODE_DP3: + /* Set alpha swizzle to zero for src0 and src1 */ + 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_ZERO; + if (!inst->FullSrcRegisters[1].SrcRegister.Extended) { + inst->FullSrcRegisters[1].SrcRegister.Extended = TRUE; + inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleX = + inst->FullSrcRegisters[1].SrcRegister.SwizzleX; + inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleY = + inst->FullSrcRegisters[1].SrcRegister.SwizzleY; + inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleZ = + inst->FullSrcRegisters[1].SrcRegister.SwizzleZ; + } + inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleW = + TGSI_EXTSWIZZLE_ZERO; + /* Fall through */ + case TGSI_OPCODE_DP4: + r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], inst->Instruction.Opcode, + 2, FALSE); + break; + case TGSI_OPCODE_MOV: + case TGSI_OPCODE_SWZ: + inst->FullSrcRegisters[1] = r300_constant_zero; + r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], inst->Instruction.Opcode, + 2, FALSE); + break; + case TGSI_OPCODE_MAD: + r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters, + &inst->FullDstRegisters[0], inst->Instruction.Opcode, + 3, FALSE); + break; + case TGSI_OPCODE_END: + break; + default: + debug_printf("r300: vs: Bad opcode %d\n", + inst->Instruction.Opcode); + break; + } +} + +static void r300_vs_init(struct r300_vertex_shader* vs, + struct r300_vs_asm* assembler) +{ + struct tgsi_shader_info* info = &vs->info; + int i; + + for (i = 0; i < info->num_outputs; i++) { + switch (info->output_semantic_name[i]) { + case TGSI_SEMANTIC_PSIZE: + assembler->point_size = TRUE; + break; + case TGSI_SEMANTIC_COLOR: + assembler->out_colors++; + break; + case TGSI_SEMANTIC_FOG: + case TGSI_SEMANTIC_GENERIC: + assembler->out_texcoords++; + break; + } + } + + vs->instruction_count = 0; +} + +void r300_translate_vertex_shader(struct r300_context* r300, + struct r300_vertex_shader* vs) +{ + struct tgsi_parse_context parser; + int i; + struct r300_constant_buffer* consts = + &r300->shader_constants[PIPE_SHADER_VERTEX]; + + struct r300_vs_asm* assembler = CALLOC_STRUCT(r300_vs_asm); + if (assembler == NULL) { + return; + } + + /* Init assembler. */ + r300_vs_init(vs, assembler); + + /* Setup starting offset for immediates. */ + assembler->imm_offset = consts->user_count; + + tgsi_parse_init(&parser, vs->state.tokens); + + while (!tgsi_parse_end_of_tokens(&parser)) { + tgsi_parse_token(&parser); + + /* 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_vs_declare(assembler, &parser.FullToken.FullDeclaration); + 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.ImmediateFloat32[i] + .Float; + } + assembler->imm_count++; + break; + case TGSI_TOKEN_TYPE_INSTRUCTION: + r300_vs_instruction(vs, assembler, + &parser.FullToken.FullInstruction); + break; + } + } + + debug_printf("r300: vs: %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; + vs->uses_imms = assembler->imm_count; + debug_printf("r300: vs: %d total constants, " + "%d from user and %d from immediates\n", consts->count, + consts->user_count, assembler->imm_count); + + debug_printf("r300: vs: tab: %d %d %d %d\n", assembler->tab[0], + assembler->tab[1], assembler->tab[2], assembler->tab[3]); + + tgsi_dump(vs->state.tokens, 0); + /* XXX finish r300 vertex shader dumper */ + r300_vs_dump(vs); + + tgsi_parse_free(&parser); + FREE(assembler); +} diff --git a/src/gallium/drivers/r300/r300_vs.h b/src/gallium/drivers/r300/r300_vs.h new file mode 100644 index 0000000000..165d717812 --- /dev/null +++ b/src/gallium/drivers/r300/r300_vs.h @@ -0,0 +1,157 @@ +/* + * 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_VS_H +#define R300_VS_H + +#include "tgsi/tgsi_parse.h" +#include "tgsi/tgsi_dump.h" + +#include "r300_context.h" +#include "r300_debug.h" +#include "r300_reg.h" +#include "r300_screen.h" +#include "r300_shader_inlines.h" + +/* XXX get these to r300_reg */ +#define R300_PVS_DST_OPCODE(x) ((x) << 0) +# define R300_VE_DOT_PRODUCT 1 +# define R300_VE_MULTIPLY 2 +# define R300_VE_ADD 3 +# define R300_VE_MAXIMUM 7 +# define R300_VE_SET_LESS_THAN 10 +#define R300_PVS_DST_MATH_INST (1 << 6) +# define R300_ME_RECIP_DX 6 +#define R300_PVS_DST_MACRO_INST (1 << 7) +# define R300_PVS_MACRO_OP_2CLK_MADD 0 +#define R300_PVS_DST_REG_TYPE(x) ((x) << 8) +# define R300_PVS_DST_REG_TEMPORARY 0 +# define R300_PVS_DST_REG_A0 1 +# define R300_PVS_DST_REG_OUT 2 +# define R300_PVS_DST_REG_OUT_REPL_X 3 +# define R300_PVS_DST_REG_ALT_TEMPORARY 4 +# define R300_PVS_DST_REG_INPUT 5 +#define R300_PVS_DST_OFFSET(x) ((x) << 13) +#define R300_PVS_DST_WE(x) ((x) << 20) +#define R300_PVS_DST_WE_XYZW (0xf << 20) + +#define R300_PVS_SRC_REG_TYPE(x) ((x) << 0) +# define R300_PVS_SRC_REG_TEMPORARY 0 +# define R300_PVS_SRC_REG_INPUT 1 +# define R300_PVS_SRC_REG_CONSTANT 2 +# define R300_PVS_SRC_REG_ALT_TEMPORARY 3 +#define R300_PVS_SRC_OFFSET(x) ((x) << 5) +#define R300_PVS_SRC_SWIZZLE(x) ((x) << 13) +# define R300_PVS_SRC_SELECT_X 0 +# define R300_PVS_SRC_SELECT_Y 1 +# define R300_PVS_SRC_SELECT_Z 2 +# define R300_PVS_SRC_SELECT_W 3 +# define R300_PVS_SRC_SELECT_FORCE_0 4 +# define R300_PVS_SRC_SELECT_FORCE_1 5 +# define R300_PVS_SRC_SWIZZLE_XYZW \ + ((R300_PVS_SRC_SELECT_X | (R300_PVS_SRC_SELECT_Y << 3) | \ + (R300_PVS_SRC_SELECT_Z << 6) | (R300_PVS_SRC_SELECT_W << 9)) << 13) +# define R300_PVS_SRC_SWIZZLE_ZERO \ + ((R300_PVS_SRC_SELECT_FORCE_0 | (R300_PVS_SRC_SELECT_FORCE_0 << 3) | \ + (R300_PVS_SRC_SELECT_FORCE_0 << 6) | \ + (R300_PVS_SRC_SELECT_FORCE_0 << 9)) << 13) +# define R300_PVS_SRC_SWIZZLE_ONE \ + ((R300_PVS_SRC_SELECT_FORCE_1 | (R300_PVS_SRC_SELECT_FORCE_1 << 3) | \ + (R300_PVS_SRC_SELECT_FORCE_1 << 6) | \ + (R300_PVS_SRC_SELECT_FORCE_1 << 9)) << 13) +#define R300_PVS_MODIFIER_X (1 << 25) +#define R300_PVS_MODIFIER_Y (1 << 26) +#define R300_PVS_MODIFIER_Z (1 << 27) +#define R300_PVS_MODIFIER_W (1 << 28) +#define R300_PVS_NEGATE_XYZW \ + (R300_PVS_MODIFIER_X | R300_PVS_MODIFIER_Y | \ + R300_PVS_MODIFIER_Z | R300_PVS_MODIFIER_W) + +/* Temporary struct used to hold assembly state while putting together + * fragment programs. */ +struct r300_vs_asm { + /* Pipe context. */ + struct r300_context* r300; + /* Number of colors. */ + unsigned color_count; + /* Number of texcoords. */ + unsigned tex_count; + /* 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; + /* Number of colors to write. */ + unsigned out_colors; + /* Number of texcoords to write. */ + unsigned out_texcoords; + /* Whether to emit point size. */ + boolean point_size; + /* Tab of declared outputs to OVM outputs. */ + unsigned tab[16]; +}; + +static struct r300_vertex_shader r300_passthrough_vertex_shader = { + /* XXX translate these back into normal instructions */ + .instruction_count = 2, + .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | + R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | + R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW, + .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | + R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW, + .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, + .instructions[0].inst3 = 0x0, + .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | + R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | + R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW, + .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | + R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW, + .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, + .instructions[1].inst3 = 0x0, +}; + +static struct r300_vertex_shader r300_texture_vertex_shader = { + /* XXX translate these back into normal instructions */ + .instruction_count = 2, + .instructions[0].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | + R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | + R300_PVS_DST_OFFSET(0) | R300_PVS_DST_WE_XYZW, + .instructions[0].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | + R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW, + .instructions[0].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, + .instructions[0].inst3 = 0x0, + .instructions[1].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) | + R300_PVS_DST_REG_TYPE(R300_PVS_DST_REG_OUT) | + R300_PVS_DST_OFFSET(1) | R300_PVS_DST_WE_XYZW, + .instructions[1].inst1 = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) | + R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW, + .instructions[1].inst2 = R300_PVS_SRC_SWIZZLE_ZERO, + .instructions[1].inst3 = 0x0, +}; + +void r300_translate_vertex_shader(struct r300_context* r300, + struct r300_vertex_shader* vs); + +#endif /* R300_VS_H */ diff --git a/src/gallium/drivers/r300/r3xx_fs.c b/src/gallium/drivers/r300/r3xx_fs.c new file mode 100644 index 0000000000..6e05d76977 --- /dev/null +++ b/src/gallium/drivers/r300/r3xx_fs.c @@ -0,0 +1,96 @@ +/* + * 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. */ + +#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; + } +} + +static INLINE uint32_t r3xx_alpha_op(unsigned op) +{ + switch (op) { + case TGSI_OPCODE_MOV: + return R300_ALU_OUTA_CMP; + default: + return 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; + + fs->instructions[i].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) | + 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_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; + + fs->alu_instruction_count++; +} + +void r3xx_fs_finalize(struct r300_fragment_shader* fs, + struct r300_fs_asm* assembler) +{ + fs->stack_size = assembler->temp_count + assembler->temp_offset + 1; +} + +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; + } +} diff --git a/src/gallium/drivers/r300/r3xx_fs.h b/src/gallium/drivers/r300/r3xx_fs.h new file mode 100644 index 0000000000..3da39ec252 --- /dev/null +++ b/src/gallium/drivers/r300/r3xx_fs.h @@ -0,0 +1,76 @@ +/* + * 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 R3XX_FS_H +#define R3XX_FS_H + +#include "r300_fs_inlines.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, +}; + +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); + +#endif /* R3XX_FS_H */ diff --git a/src/gallium/drivers/r300/r5xx_fs.c b/src/gallium/drivers/r300/r5xx_fs.c new file mode 100644 index 0000000000..99d826278c --- /dev/null +++ b/src/gallium/drivers/r300/r5xx_fs.c @@ -0,0 +1,467 @@ +/* + * 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. */ + +#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)) | + 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; + } +} diff --git a/src/gallium/drivers/r300/r5xx_fs.h b/src/gallium/drivers/r300/r5xx_fs.h new file mode 100644 index 0000000000..629e587be4 --- /dev/null +++ b/src/gallium/drivers/r300/r5xx_fs.h @@ -0,0 +1,132 @@ +/* + * 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 R5XX_FS_H +#define R5XX_FS_H + +#include "r300_fs_inlines.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, +}; + +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); + +#endif /* R5XX_FS_H */ -- cgit v1.2.3