summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r300
diff options
context:
space:
mode:
authorCorbin Simpson <[email protected]>2009-03-10 15:40:41 -0700
committerCorbin Simpson <[email protected]>2009-03-11 15:23:08 -0700
commit8b212503052b767561d85108c435f375e0228f44 (patch)
tree364f0ea255dfd6d4ba470c1773c70f214b2d9573 /src/gallium/drivers/r300
parent04465bb6df5a9845425a9c163ef3869019376374 (diff)
r300-gallium: Begin R500 fragment shader assembler.
I love it so much. I also hate it a lot.
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r--src/gallium/drivers/r300/r300_state_shader.c132
-rw-r--r--src/gallium/drivers/r300/r300_state_shader.h15
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);