r300-gallium: Begin R500 fragment shader assembler.
authorCorbin Simpson <MostAwesomeDude@gmail.com>
Tue, 10 Mar 2009 22:40:41 +0000 (15:40 -0700)
committerCorbin Simpson <MostAwesomeDude@gmail.com>
Wed, 11 Mar 2009 22:23:08 +0000 (15:23 -0700)
I love it so much. I also hate it a lot.

src/gallium/drivers/r300/r300_state_shader.c
src/gallium/drivers/r300/r300_state_shader.h

index d10ac55580afc5287deb23ab270ef337005b20ef..7165efdc19b1f06585823379d6c92f13ffa21875 100644 (file)
@@ -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);
 }
index 73025b2dcc4b9ffeeb656cf9a0df45663fb4a221..333f0f5d050058cfa4d6d23998ed77c06537539c 100644 (file)
 #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);