From 8b212503052b767561d85108c435f375e0228f44 Mon Sep 17 00:00:00 2001 From: Corbin Simpson Date: Tue, 10 Mar 2009 15:40:41 -0700 Subject: [PATCH] r300-gallium: Begin R500 fragment shader assembler. I love it so much. I also hate it a lot. --- src/gallium/drivers/r300/r300_state_shader.c | 132 ++++++++++++++++++- src/gallium/drivers/r300/r300_state_shader.h | 15 +++ 2 files changed, 144 insertions(+), 3 deletions(-) diff --git a/src/gallium/drivers/r300/r300_state_shader.c b/src/gallium/drivers/r300/r300_state_shader.c index d10ac55580a..7165efdc19b 100644 --- a/src/gallium/drivers/r300/r300_state_shader.c +++ b/src/gallium/drivers/r300/r300_state_shader.c @@ -40,14 +40,140 @@ static void r500_copy_passthrough_shader(struct r500_fragment_shader* fs) fs->instructions[0] = pt->instructions[0]; } +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_GENERIC: + assembler->tex_count++; + break; + default: + debug_printf("r300: fs: Bad semantic declaration %d\n", + decl->Semantic.SemanticName); + break; + } + break; + case TGSI_FILE_OUTPUT: + 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 void r500_emit_mov(struct r500_fragment_shader* fs, + struct r300_fs_asm* assembler, + struct tgsi_full_src_register* src, + struct tgsi_full_dst_register* dst) +{ + int i = fs->instruction_count; + fs->instructions[i].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; + fs->instructions[i].inst1 = + R500_RGB_ADDR0(0) | R500_RGB_ADDR1(0) | R500_RGB_ADDR1_CONST | + R500_RGB_ADDR2(0) | R500_RGB_ADDR2_CONST; + fs->instructions[i].inst2 = + R500_ALPHA_ADDR0(0) | R500_ALPHA_ADDR1(0) | R500_ALPHA_ADDR1_CONST | + R500_ALPHA_ADDR2(0) | R500_ALPHA_ADDR2_CONST; + fs->instructions[i].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, + fs->instructions[i].inst4 = + R500_ALPHA_OP_CMP | R500_ALPHA_SWIZ_A_A | R500_ALPHA_SWIZ_B_A; + fs->instructions[i].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; + + fs->instruction_count++; +} + +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) { + case TGSI_OPCODE_MOV: + r500_emit_mov(fs, assembler, &inst->FullSrcRegisters[0], + &inst->FullDstRegisters[0]); + break; + case TGSI_OPCODE_END: + break; + default: + debug_printf("r300: fs: Bad opcode %d\n", + inst->Instruction.Opcode); + break; + } +} + void r300_translate_fragment_shader(struct r300_context* r300, - struct r300_fragment_shader* fs) + struct r300_fragment_shader* fs) { + struct tgsi_parse_context parser; + + tgsi_parse_init(&parser, fs->shader.state.tokens); + + while (!tgsi_parse_end_of_tokens(&parser)) { + tgsi_parse_token(&parser); + } + r300_copy_passthrough_shader(fs); } void r500_translate_fragment_shader(struct r300_context* r300, - struct r500_fragment_shader* fs) + struct r500_fragment_shader* fs) { - r500_copy_passthrough_shader(fs); + struct r300_fs_asm* assembler = CALLOC_STRUCT(r300_fs_asm); + if (assembler == NULL) { + return; + } + struct tgsi_parse_context parser; + + tgsi_parse_init(&parser, fs->shader.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_INSTRUCTION: + r500_fs_instruction(fs, assembler, + &parser.FullToken.FullInstruction); + } + + } + + debug_printf("%d texs and %d colors, first free reg is %d\n", + assembler->tex_count, assembler->color_count, + assembler->tex_count + assembler->color_count); + + /* XXX subtly wrong */ + fs->shader.stack_size = assembler->temp_offset; + + tgsi_dump(fs->shader.state.tokens); + + //r500_copy_passthrough_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 index 73025b2dcc4..333f0f5d050 100644 --- a/src/gallium/drivers/r300/r300_state_shader.h +++ b/src/gallium/drivers/r300/r300_state_shader.h @@ -23,10 +23,25 @@ #ifndef R300_STATE_SHADER_H #define R300_STATE_SHADER_H +#include "tgsi/tgsi_parse.h" + #include "r300_context.h" #include "r300_reg.h" #include "r300_screen.h" +/* Temporary struct used to hold assembly state while putting together + * fragment programs. */ +struct r300_fs_asm { + /* 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; +}; + void r300_translate_fragment_shader(struct r300_context* r300, struct r300_fragment_shader* fs); -- 2.30.2