r300g: Use r300compiler for vertex shaders

This commit is contained in:
Nicolai Hähnle
2009-07-27 20:23:49 +02:00
parent cab62aa28f
commit 188f8c6792
16 changed files with 695 additions and 753 deletions

View File

@@ -31,8 +31,8 @@ INCLUDES = \
default: depend lib$(LIBNAME).a
lib$(LIBNAME).a: $(OBJECTS) Makefile $(TOP)/src/gallium/Makefile.template
$(MKLIB) -o $(LIBNAME) -static $(OBJECTS)
lib$(LIBNAME).a: $(OBJECTS) $(EXTRA_OBJECTS) Makefile $(TOP)/src/gallium/Makefile.template
$(MKLIB) -o $(LIBNAME) -static $(OBJECTS) $(EXTRA_OBJECTS)
depend: $(C_SOURCES) $(CPP_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
rm -f depend

View File

@@ -21,6 +21,22 @@ C_SOURCES = \
r300_state_invariant.c \
r300_vs.c \
r300_surface.c \
r300_texture.c
r300_texture.c \
r300_tgsi_to_rc.c
LIBRARY_INCLUDES = \
-I$(TOP)/src/mesa/drivers/dri/r300/compiler \
-I$(TOP)/src/mesa \
-I$(TOP)/include
COMPILER_ARCHIVE = $(TOP)/src/mesa/drivers/dri/r300/compiler/libr300compiler.a
EXTRA_OBJECTS = \
$(COMPILER_ARCHIVE)
include ../../Makefile.template
.PHONY : $(COMPILER_ARCHIVE)
$(COMPILER_ARCHIVE):
cd $(TOP)/src/mesa/drivers/dri/r300/compiler; make

View File

@@ -34,6 +34,8 @@
#include "r300_screen.h"
#include "r300_winsys.h"
struct r300_vertex_shader;
struct r300_blend_state {
uint32_t blend_control; /* R300_RB3D_CBLEND: 0x4e04 */
uint32_t alpha_blend_control; /* R300_RB3D_ABLEND: 0x4e08 */
@@ -242,33 +244,6 @@ struct r300_vertex_format {
int fs_tab[16];
};
struct r300_vertex_shader {
/* Parent class */
struct pipe_shader_state state;
struct tgsi_shader_info info;
/* Fallback shader, because Draw has issues */
struct draw_vertex_shader* draw;
/* Has this shader been translated yet? */
boolean translated;
/* Are there immediates in this shader?
* If not, we can heavily optimize recompilation. */
boolean uses_imms;
/* Number of used instructions */
int instruction_count;
/* Machine instructions */
struct {
uint32_t inst0;
uint32_t inst1;
uint32_t inst2;
uint32_t inst3;
} instructions[128]; /*< XXX magic number */
};
static struct pipe_viewport_state r300_viewport_identity = {
.scale = {1.0, 1.0, 1.0, 1.0},
.translate = {0.0, 0.0, 0.0, 0.0},

View File

@@ -22,6 +22,83 @@
#include "r300_debug.h"
static char* r5xx_fs_swiz[] = {
" R",
" G",
" B",
" A",
" 0",
".5",
" 1",
" U",
};
static char* r5xx_fs_op_rgb[] = {
"MAD",
"DP3",
"DP4",
"D2A",
"MIN",
"MAX",
"---",
"CND",
"CMP",
"FRC",
"SOP",
"MDH",
"MDV",
};
static char* r5xx_fs_op_alpha[] = {
"MAD",
" DP",
"MIN",
"MAX",
"---",
"CND",
"CMP",
"FRC",
"EX2",
"LN2",
"RCP",
"RSQ",
"SIN",
"COS",
"MDH",
"MDV",
};
static char* r5xx_fs_mask[] = {
"NONE",
"R ",
" G ",
"RG ",
" B ",
"R B ",
" GB ",
"RGB ",
" A",
"R A",
" G A",
"RG A",
" BA",
"R BA",
" GBA",
"RGBA",
};
static char* r5xx_fs_tex[] = {
" NOP",
" LD",
"TEXKILL",
" PROJ",
"LODBIAS",
" LOD",
" DXDY",
};
void r3xx_dump_fs(struct r3xx_fragment_shader* fs)
{
int i;
@@ -142,57 +219,10 @@ void r5xx_fs_dump(struct r5xx_fragment_shader* fs)
r5xx_fs_swiz[(inst >> 26) & 0x3],
r5xx_fs_swiz[(inst >> 28) & 0x3],
r5xx_fs_swiz[(inst >> 30) & 0x3]);
inst = fs->instructions[i].inst3;
debug_printf(" 3: TEX_DXDY 0x%08x\n", inst);
break;
}
}
}
static void r300_vs_op_dump(uint32_t op)
{
debug_printf(" dst: %d%s op: ",
(op >> 13) & 0x7f, r300_vs_dst_debug[(op >> 8) & 0x7]);
if (op & 0x80) {
if (op & 0x1) {
debug_printf("PVS_MACRO_OP_2CLK_M2X_ADD\n");
} else {
debug_printf(" PVS_MACRO_OP_2CLK_MADD\n");
}
} else if (op & 0x40) {
debug_printf("%s\n", r300_vs_me_ops[op & 0x1f]);
} else {
debug_printf("%s\n", r300_vs_ve_ops[op & 0x1f]);
}
}
void r300_vs_src_dump(uint32_t src)
{
debug_printf(" reg: %d%s swiz: %s%s/%s%s/%s%s/%s%s\n",
(src >> 5) & 0x7f, r300_vs_src_debug[src & 0x3],
src & (1 << 25) ? "-" : " ",
r300_vs_swiz_debug[(src >> 13) & 0x7],
src & (1 << 26) ? "-" : " ",
r300_vs_swiz_debug[(src >> 16) & 0x7],
src & (1 << 27) ? "-" : " ",
r300_vs_swiz_debug[(src >> 19) & 0x7],
src & (1 << 28) ? "-" : " ",
r300_vs_swiz_debug[(src >> 22) & 0x7]);
}
void r300_vs_dump(struct r300_vertex_shader* vs)
{
int i;
for (i = 0; i < vs->instruction_count; i++) {
debug_printf("%d: op: 0x%08x", i, vs->instructions[i].inst0);
r300_vs_op_dump(vs->instructions[i].inst0);
debug_printf(" src0: 0x%08x", vs->instructions[i].inst1);
r300_vs_src_dump(vs->instructions[i].inst1);
debug_printf(" src1: 0x%08x", vs->instructions[i].inst2);
r300_vs_src_dump(vs->instructions[i].inst2);
debug_printf(" src2: 0x%08x", vs->instructions[i].inst3);
r300_vs_src_dump(vs->instructions[i].inst3);
}
}

View File

@@ -27,182 +27,6 @@
#include "r300_fs.h"
#include "r300_vs.h"
static char* r5xx_fs_swiz[] = {
" R",
" G",
" B",
" A",
" 0",
".5",
" 1",
" U",
};
static char* r5xx_fs_op_rgb[] = {
"MAD",
"DP3",
"DP4",
"D2A",
"MIN",
"MAX",
"---",
"CND",
"CMP",
"FRC",
"SOP",
"MDH",
"MDV",
};
static char* r5xx_fs_op_alpha[] = {
"MAD",
" DP",
"MIN",
"MAX",
"---",
"CND",
"CMP",
"FRC",
"EX2",
"LN2",
"RCP",
"RSQ",
"SIN",
"COS",
"MDH",
"MDV",
};
static char* r5xx_fs_mask[] = {
"NONE",
"R ",
" G ",
"RG ",
" B ",
"R B ",
" GB ",
"RGB ",
" A",
"R A",
" G A",
"RG A",
" BA",
"R BA",
" GBA",
"RGBA",
};
static char* r5xx_fs_tex[] = {
" NOP",
" LD",
"TEXKILL",
" PROJ",
"LODBIAS",
" LOD",
" DXDY",
};
static char* r300_vs_ve_ops[] = {
/* R300 vector ops */
" VE_NO_OP",
" VE_DOT_PRODUCT",
" VE_MULTIPLY",
" VE_ADD",
" VE_MULTIPLY_ADD",
" VE_DISTANCE_FACTOR",
" VE_FRACTION",
" VE_MAXIMUM",
" VE_MINIMUM",
"VE_SET_GREATER_THAN_EQUAL",
" VE_SET_LESS_THAN",
" VE_MULTIPLYX2_ADD",
" VE_MULTIPLY_CLAMP",
" VE_FLT2FIX_DX",
" VE_FLT2FIX_DX_RND",
/* R500 vector ops */
" VE_PRED_SET_EQ_PUSH",
" VE_PRED_SET_GT_PUSH",
" VE_PRED_SET_GTE_PUSH",
" VE_PRED_SET_NEQ_PUSH",
" VE_COND_WRITE_EQ",
" VE_COND_WRITE_GT",
" VE_COND_WRITE_GTE",
" VE_COND_WRITE_NEQ",
" VE_SET_GREATER_THAN",
" VE_SET_EQUAL",
" VE_SET_NOT_EQUAL",
" (reserved)",
" (reserved)",
" (reserved)",
};
static char* r300_vs_me_ops[] = {
/* R300 math ops */
" ME_NO_OP",
" ME_EXP_BASE2_DX",
" ME_LOG_BASE2_DX",
" ME_EXP_BASEE_FF",
" ME_LIGHT_COEFF_DX",
" ME_POWER_FUNC_FF",
" ME_RECIP_DX",
" ME_RECIP_FF",
" ME_RECIP_SQRT_DX",
" ME_RECIP_SQRT_FF",
" ME_MULTIPLY",
" ME_EXP_BASE2_FULL_DX",
" ME_LOG_BASE2_FULL_DX",
" ME_POWER_FUNC_FF_CLAMP_B",
"ME_POWER_FUNC_FF_CLAMP_B1",
"ME_POWER_FUNC_FF_CLAMP_01",
" ME_SIN",
" ME_COS",
/* R500 math ops */
" ME_LOG_BASE2_IEEE",
" ME_RECIP_IEEE",
" ME_RECIP_SQRT_IEEE",
" ME_PRED_SET_EQ",
" ME_PRED_SET_GT",
" ME_PRED_SET_GTE",
" ME_PRED_SET_NEQ",
" ME_PRED_SET_CLR",
" ME_PRED_SET_INV",
" ME_PRED_SET_POP",
" ME_PRED_SET_RESTORE",
" (reserved)",
" (reserved)",
" (reserved)",
};
/* XXX refactor to avoid clashing symbols */
static char* r300_vs_src_debug[] = {
"t",
"i",
"c",
"a",
};
static char* r300_vs_dst_debug[] = {
"t",
"a0",
"o",
"ox",
"a",
"i",
"u",
"u",
};
static char* r300_vs_swiz_debug[] = {
"X",
"Y",
"Z",
"W",
"0",
"1",
"U",
"U",
};
void r5xx_fs_dump(struct r5xx_fragment_shader* fs);
void r3xx_dump_fs(struct r3xx_fragment_shader* fs);

View File

@@ -24,6 +24,8 @@
#include "r300_emit.h"
#include "r300_vs.h"
void r300_emit_blend_state(struct r300_context* r300,
struct r300_blend_state* blend)
{
@@ -380,13 +382,33 @@ void r300_emit_vertex_format_state(struct r300_context* r300)
END_CS;
}
void r300_emit_vertex_shader(struct r300_context* r300,
struct r300_vertex_shader* vs)
static const float * get_shader_constant(
struct r300_context * r300,
struct rc_constant * constant,
struct r300_constant_buffer * externals)
{
static const float zero[4] = { 0.0, 0.0, 0.0, 0.0 };
switch(constant->Type) {
case RC_CONSTANT_EXTERNAL:
return externals->constants[constant->u.External];
case RC_CONSTANT_IMMEDIATE:
return constant->u.Immediate;
default:
debug_printf("r300: Implementation error: Unhandled constant type %i\n",
constant->Type);
return zero;
}
}
void r300_emit_vertex_program_code(struct r300_context* r300,
struct r300_vertex_program_code* code,
struct r300_constant_buffer* constants)
{
int i;
struct r300_screen* r300screen = r300_screen(r300->context.screen);
struct r300_constant_buffer* constants =
&r300->shader_constants[PIPE_SHADER_VERTEX];
unsigned instruction_count = code->length / 4;
CS_LOCALS(r300);
if (!r300screen->caps->has_tcl) {
@@ -395,10 +417,10 @@ void r300_emit_vertex_shader(struct r300_context* r300,
return;
}
if (constants->count) {
BEGIN_CS(14 + (vs->instruction_count * 4) + (constants->count * 4));
if (code->constants.Count) {
BEGIN_CS(14 + code->length + (code->constants.Count * 4));
} else {
BEGIN_CS(11 + (vs->instruction_count * 4));
BEGIN_CS(11 + code->length);
}
/* R300_VAP_PVS_CODE_CNTL_0
@@ -408,30 +430,27 @@ void r300_emit_vertex_shader(struct r300_context* r300,
* XXX these could be optimized to select better values... */
OUT_CS_REG_SEQ(R300_VAP_PVS_CODE_CNTL_0, 3);
OUT_CS(R300_PVS_FIRST_INST(0) |
R300_PVS_XYZW_VALID_INST(vs->instruction_count - 1) |
R300_PVS_LAST_INST(vs->instruction_count - 1));
OUT_CS(R300_PVS_MAX_CONST_ADDR(constants->count - 1));
OUT_CS(vs->instruction_count - 1);
R300_PVS_XYZW_VALID_INST(instruction_count - 1) |
R300_PVS_LAST_INST(instruction_count - 1));
OUT_CS(R300_PVS_MAX_CONST_ADDR(code->constants.Count - 1));
OUT_CS(instruction_count - 1);
OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG, 0);
OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, vs->instruction_count * 4);
for (i = 0; i < vs->instruction_count; i++) {
OUT_CS(vs->instructions[i].inst0);
OUT_CS(vs->instructions[i].inst1);
OUT_CS(vs->instructions[i].inst2);
OUT_CS(vs->instructions[i].inst3);
}
OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->length);
for (i = 0; i < code->length; i++)
OUT_CS(code->body.d[i]);
if (constants->count) {
if (code->constants.Count) {
OUT_CS_REG(R300_VAP_PVS_VECTOR_INDX_REG,
(r300screen->caps->is_r500 ?
R500_PVS_CONST_START : R300_PVS_CONST_START));
OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, constants->count * 4);
for (i = 0; i < constants->count; i++) {
OUT_CS_32F(constants->constants[i][0]);
OUT_CS_32F(constants->constants[i][1]);
OUT_CS_32F(constants->constants[i][2]);
OUT_CS_32F(constants->constants[i][3]);
OUT_CS_ONE_REG(R300_VAP_PVS_UPLOAD_DATA, code->constants.Count * 4);
for (i = 0; i < code->constants.Count; i++) {
const float * data = get_shader_constant(r300, &code->constants.Constants[i], constants);
OUT_CS_32F(data[0]);
OUT_CS_32F(data[1]);
OUT_CS_32F(data[2]);
OUT_CS_32F(data[3]);
}
}
@@ -443,6 +462,12 @@ void r300_emit_vertex_shader(struct r300_context* r300,
END_CS;
}
void r300_emit_vertex_shader(struct r300_context* r300,
struct r300_vertex_shader* vs)
{
r300_emit_vertex_program_code(r300, &vs->code, &r300->shader_constants[PIPE_SHADER_VERTEX]);
}
void r300_emit_viewport_state(struct r300_context* r300,
struct r300_viewport_state* viewport)
{

View File

@@ -30,6 +30,8 @@
#include "r300_screen.h"
#include "r300_state_inlines.h"
struct r300_vertex_program_code;
void r300_emit_blend_state(struct r300_context* r300,
struct r300_blend_state* blend);
@@ -68,6 +70,10 @@ void r300_emit_vertex_buffer(struct r300_context* r300);
void r300_emit_vertex_format_state(struct r300_context* r300);
void r300_emit_vertex_program_code(struct r300_context* r300,
struct r300_vertex_program_code* code,
struct r300_constant_buffer* constants);
void r300_emit_vertex_shader(struct r300_context* r300,
struct r300_vertex_shader* vs);

View File

@@ -688,6 +688,7 @@ static void r300_delete_vs_state(struct pipe_context* pipe, void* shader)
if (r300_screen(pipe->screen)->caps->has_tcl) {
struct r300_vertex_shader* vs = (struct r300_vertex_shader*)shader;
rc_constants_destroy(&vs->code.constants);
draw_delete_vertex_shader(r300->draw, vs->draw);
FREE(vs->state.tokens);
FREE(shader);

View File

@@ -22,6 +22,8 @@
#include "r300_state_derived.h"
#include "r300_vs.h"
/* r300_state_derived: Various bits of state which are dependent upon
* currently bound CSO data. */

View File

@@ -139,7 +139,7 @@ validate:
/* Vertex shader setup */
if (caps->has_tcl) {
r300_emit_vertex_shader(r300, &r300_passthrough_vertex_shader);
r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0);
} else {
BEGIN_CS(4);
OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VAP_TCL_BYPASS);
@@ -277,7 +277,7 @@ validate:
/* Vertex shader setup */
if (caps->has_tcl) {
r300_emit_vertex_shader(r300, &r300_passthrough_vertex_shader);
r300_emit_vertex_program_code(r300, &r300_passthrough_vertex_shader, 0);
} else {
BEGIN_CS(4);
OUT_CS_REG(R300_VAP_CNTL_STATUS, R300_VAP_TCL_BYPASS);

View File

@@ -0,0 +1,299 @@
/*
* Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
*
* 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 COPYRIGHT HOLDER(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_tgsi_to_rc.h"
#include "radeon_compiler.h"
#include "radeon_program.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_scan.h"
#include "tgsi/tgsi_util.h"
static unsigned translate_opcode(unsigned opcode)
{
switch(opcode) {
case TGSI_OPCODE_ARL: return OPCODE_ARL;
case TGSI_OPCODE_MOV: return OPCODE_MOV;
case TGSI_OPCODE_LIT: return OPCODE_LIT;
case TGSI_OPCODE_RCP: return OPCODE_RCP;
case TGSI_OPCODE_RSQ: return OPCODE_RSQ;
case TGSI_OPCODE_EXP: return OPCODE_EXP;
case TGSI_OPCODE_LOG: return OPCODE_LOG;
case TGSI_OPCODE_MUL: return OPCODE_MUL;
case TGSI_OPCODE_ADD: return OPCODE_ADD;
case TGSI_OPCODE_DP3: return OPCODE_DP3;
case TGSI_OPCODE_DP4: return OPCODE_DP4;
case TGSI_OPCODE_DST: return OPCODE_DST;
case TGSI_OPCODE_MIN: return OPCODE_MIN;
case TGSI_OPCODE_MAX: return OPCODE_MAX;
case TGSI_OPCODE_SLT: return OPCODE_SLT;
case TGSI_OPCODE_SGE: return OPCODE_SGE;
case TGSI_OPCODE_MAD: return OPCODE_MAD;
case TGSI_OPCODE_SUB: return OPCODE_SUB;
case TGSI_OPCODE_LRP: return OPCODE_LRP;
/* case TGSI_OPCODE_CND: return OPCODE_CND; */
/* case TGSI_OPCODE_CND0: return OPCODE_CND0; */
case TGSI_OPCODE_DP2A: return OPCODE_DP2A;
/* gap */
case TGSI_OPCODE_FRC: return OPCODE_FRC;
/* case TGSI_OPCODE_CLAMP: return OPCODE_CLAMP; */
case TGSI_OPCODE_FLR: return OPCODE_FLR;
/* case TGSI_OPCODE_ROUND: return OPCODE_ROUND; */
case TGSI_OPCODE_EX2: return OPCODE_EX2;
case TGSI_OPCODE_LG2: return OPCODE_LG2;
case TGSI_OPCODE_POW: return OPCODE_POW;
case TGSI_OPCODE_XPD: return OPCODE_XPD;
/* gap */
case TGSI_OPCODE_ABS: return OPCODE_ABS;
case TGSI_OPCODE_RCC: return OPCODE_RCC;
case TGSI_OPCODE_DPH: return OPCODE_DPH;
case TGSI_OPCODE_COS: return OPCODE_COS;
case TGSI_OPCODE_DDX: return OPCODE_DDX;
case TGSI_OPCODE_DDY: return OPCODE_DDY;
/* case TGSI_OPCODE_KILP: return OPCODE_KILP; */
case TGSI_OPCODE_PK2H: return OPCODE_PK2H;
case TGSI_OPCODE_PK2US: return OPCODE_PK2US;
case TGSI_OPCODE_PK4B: return OPCODE_PK4B;
case TGSI_OPCODE_PK4UB: return OPCODE_PK4UB;
case TGSI_OPCODE_RFL: return OPCODE_RFL;
case TGSI_OPCODE_SEQ: return OPCODE_SEQ;
case TGSI_OPCODE_SFL: return OPCODE_SFL;
case TGSI_OPCODE_SGT: return OPCODE_SGT;
case TGSI_OPCODE_SIN: return OPCODE_SIN;
case TGSI_OPCODE_SLE: return OPCODE_SLE;
case TGSI_OPCODE_SNE: return OPCODE_SNE;
case TGSI_OPCODE_STR: return OPCODE_STR;
case TGSI_OPCODE_TEX: return OPCODE_TEX;
case TGSI_OPCODE_TXD: return OPCODE_TXD;
case TGSI_OPCODE_TXP: return OPCODE_TXP;
case TGSI_OPCODE_UP2H: return OPCODE_UP2H;
case TGSI_OPCODE_UP2US: return OPCODE_UP2US;
case TGSI_OPCODE_UP4B: return OPCODE_UP4B;
case TGSI_OPCODE_UP4UB: return OPCODE_UP4UB;
case TGSI_OPCODE_X2D: return OPCODE_X2D;
case TGSI_OPCODE_ARA: return OPCODE_ARA;
case TGSI_OPCODE_ARR: return OPCODE_ARR;
case TGSI_OPCODE_BRA: return OPCODE_BRA;
case TGSI_OPCODE_CAL: return OPCODE_CAL;
case TGSI_OPCODE_RET: return OPCODE_RET;
case TGSI_OPCODE_SSG: return OPCODE_SSG;
case TGSI_OPCODE_CMP: return OPCODE_CMP;
case TGSI_OPCODE_SCS: return OPCODE_SCS;
case TGSI_OPCODE_TXB: return OPCODE_TXB;
/* case TGSI_OPCODE_NRM: return OPCODE_NRM; */
/* case TGSI_OPCODE_DIV: return OPCODE_DIV; */
case TGSI_OPCODE_DP2: return OPCODE_DP2;
case TGSI_OPCODE_TXL: return OPCODE_TXL;
case TGSI_OPCODE_BRK: return OPCODE_BRK;
case TGSI_OPCODE_IF: return OPCODE_IF;
/* case TGSI_OPCODE_LOOP: return OPCODE_LOOP; */
/* case TGSI_OPCODE_REP: return OPCODE_REP; */
case TGSI_OPCODE_ELSE: return OPCODE_ELSE;
case TGSI_OPCODE_ENDIF: return OPCODE_ENDIF;
case TGSI_OPCODE_ENDLOOP: return OPCODE_ENDLOOP;
/* case TGSI_OPCODE_ENDREP: return OPCODE_ENDREP; */
case TGSI_OPCODE_PUSHA: return OPCODE_PUSHA;
case TGSI_OPCODE_POPA: return OPCODE_POPA;
/* case TGSI_OPCODE_CEIL: return OPCODE_CEIL; */
/* case TGSI_OPCODE_I2F: return OPCODE_I2F; */
case TGSI_OPCODE_NOT: return OPCODE_NOT;
case TGSI_OPCODE_TRUNC: return OPCODE_TRUNC;
/* case TGSI_OPCODE_SHL: return OPCODE_SHL; */
/* case TGSI_OPCODE_SHR: return OPCODE_SHR; */
case TGSI_OPCODE_AND: return OPCODE_AND;
case TGSI_OPCODE_OR: return OPCODE_OR;
/* case TGSI_OPCODE_MOD: return OPCODE_MOD; */
case TGSI_OPCODE_XOR: return OPCODE_XOR;
/* case TGSI_OPCODE_SAD: return OPCODE_SAD; */
/* case TGSI_OPCODE_TXF: return OPCODE_TXF; */
/* case TGSI_OPCODE_TXQ: return OPCODE_TXQ; */
case TGSI_OPCODE_CONT: return OPCODE_CONT;
/* case TGSI_OPCODE_EMIT: return OPCODE_EMIT; */
/* case TGSI_OPCODE_ENDPRIM: return OPCODE_ENDPRIM; */
/* case TGSI_OPCODE_BGNLOOP2: return OPCODE_BGNLOOP2; */
case TGSI_OPCODE_BGNSUB: return OPCODE_BGNSUB;
/* case TGSI_OPCODE_ENDLOOP2: return OPCODE_ENDLOOP2; */
case TGSI_OPCODE_ENDSUB: return OPCODE_ENDSUB;
case TGSI_OPCODE_NOISE1: return OPCODE_NOISE1;
case TGSI_OPCODE_NOISE2: return OPCODE_NOISE2;
case TGSI_OPCODE_NOISE3: return OPCODE_NOISE3;
case TGSI_OPCODE_NOISE4: return OPCODE_NOISE4;
case TGSI_OPCODE_NOP: return OPCODE_NOP;
/* gap */
case TGSI_OPCODE_NRM4: return OPCODE_NRM4;
/* case TGSI_OPCODE_CALLNZ: return OPCODE_CALLNZ; */
/* case TGSI_OPCODE_IFC: return OPCODE_IFC; */
/* case TGSI_OPCODE_BREAKC: return OPCODE_BREAKC; */
case TGSI_OPCODE_KIL: return OPCODE_KIL;
case TGSI_OPCODE_END: return OPCODE_END;
case TGSI_OPCODE_SWZ: return OPCODE_SWZ;
}
fprintf(stderr, "Unknown opcode: %i\n", opcode);
abort();
}
static unsigned translate_saturate(unsigned saturate)
{
switch(saturate) {
case TGSI_SAT_NONE: return SATURATE_OFF;
case TGSI_SAT_ZERO_ONE: return SATURATE_ZERO_ONE;
case TGSI_SAT_MINUS_PLUS_ONE: return SATURATE_PLUS_MINUS_ONE;
}
fprintf(stderr, "Unknown saturate mode: %i\n", saturate);
abort();
}
static unsigned translate_register_file(unsigned file)
{
switch(file) {
case TGSI_FILE_CONSTANT: return PROGRAM_CONSTANT;
case TGSI_FILE_IMMEDIATE: return PROGRAM_CONSTANT;
case TGSI_FILE_INPUT: return PROGRAM_INPUT;
case TGSI_FILE_OUTPUT: return PROGRAM_OUTPUT;
case TGSI_FILE_TEMPORARY: return PROGRAM_TEMPORARY;
case TGSI_FILE_ADDRESS: return PROGRAM_ADDRESS;
}
fprintf(stderr, "Unhandled register file: %i\n", file);
abort();
}
static int translate_register_index(
struct tgsi_to_rc * ttr,
unsigned file,
int index)
{
if (file == TGSI_FILE_IMMEDIATE)
return ttr->immediate_offset + index;
return index;
}
static void transform_dstreg(
struct tgsi_to_rc * ttr,
struct prog_dst_register * dst,
struct tgsi_full_dst_register * src)
{
dst->File = translate_register_file(src->DstRegister.File);
dst->Index = translate_register_index(ttr, src->DstRegister.File, src->DstRegister.Index);
dst->WriteMask = src->DstRegister.WriteMask;
dst->RelAddr = src->DstRegister.Indirect;
}
static void transform_srcreg(
struct tgsi_to_rc * ttr,
struct prog_src_register * dst,
struct tgsi_full_src_register * src)
{
dst->File = translate_register_file(src->SrcRegister.File);
dst->Index = translate_register_index(ttr, src->SrcRegister.File, src->SrcRegister.Index);
dst->RelAddr = src->SrcRegister.Indirect;
dst->Swizzle = tgsi_util_get_full_src_register_extswizzle(src, 0);
dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 1) << 3;
dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 2) << 6;
dst->Swizzle |= tgsi_util_get_full_src_register_extswizzle(src, 3) << 9;
dst->Abs = src->SrcRegisterExtMod.Absolute;
dst->Negate =
src->SrcRegisterExtSwz.NegateX |
(src->SrcRegisterExtSwz.NegateY << 1) |
(src->SrcRegisterExtSwz.NegateZ << 2) |
(src->SrcRegisterExtSwz.NegateW << 3);
dst->Negate ^= src->SrcRegister.Negate ? NEGATE_XYZW : 0;
}
static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_instruction * src)
{
if (src->Instruction.Opcode == TGSI_OPCODE_END)
return;
struct rc_instruction * dst = rc_insert_new_instruction(ttr->compiler, ttr->compiler->Program.Instructions.Prev);
int i;
dst->I.Opcode = translate_opcode(src->Instruction.Opcode);
dst->I.SaturateMode = translate_saturate(src->Instruction.Saturate);
if (src->Instruction.NumDstRegs)
transform_dstreg(ttr, &dst->I.DstReg, &src->FullDstRegisters[0]);
for(i = 0; i < src->Instruction.NumSrcRegs; ++i)
transform_srcreg(ttr, &dst->I.SrcReg[i], &src->FullSrcRegisters[i]);
/* TODO: Textures */
}
static void handle_immediate(struct tgsi_to_rc * ttr, struct tgsi_full_immediate * imm)
{
struct rc_constant constant;
int i;
constant.Type = RC_CONSTANT_IMMEDIATE;
constant.Size = 4;
for(i = 0; i < 4; ++i)
constant.u.Immediate[i] = imm->u[i].Float;
rc_constants_add(&ttr->compiler->Program.Constants, &constant);
}
void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens)
{
struct tgsi_parse_context parser;
int i;
/* Allocate constants placeholders.
*
* Note: What if declared constants are not contiguous? */
for(i = 0; i <= ttr->info->file_max[TGSI_FILE_CONSTANT]; ++i) {
struct rc_constant constant;
memset(&constant, 0, sizeof(constant));
constant.Type = RC_CONSTANT_EXTERNAL;
constant.Size = 4;
constant.u.External = i;
rc_constants_add(&ttr->compiler->Program.Constants, &constant);
}
ttr->immediate_offset = ttr->compiler->Program.Constants.Count;
tgsi_parse_init(&parser, tokens);
while (!tgsi_parse_end_of_tokens(&parser)) {
tgsi_parse_token(&parser);
switch (parser.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_DECLARATION:
break;
case TGSI_TOKEN_TYPE_IMMEDIATE:
handle_immediate(ttr, &parser.FullToken.FullImmediate);
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
transform_instruction(ttr, &parser.FullToken.FullInstruction);
break;
}
}
tgsi_parse_free(&parser);
rc_calculate_inputs_outputs(ttr->compiler);
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2009 Nicolai Hähnle <nhaehnle@gmail.com>
*
* 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 COPYRIGHT HOLDER(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_TGSI_TO_RC_H
#define R300_TGSI_TO_RC_H
struct radeon_compiler;
struct tgsi_full_declaration;
struct tgsi_shader_info;
struct tgsi_token;
struct tgsi_to_rc {
struct radeon_compiler * compiler;
const struct tgsi_shader_info * info;
int immediate_offset;
};
void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens);
#endif /* R300_TGSI_TO_RC_H */

View File

@@ -22,393 +22,215 @@
#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;
}
}
#include "r300_context.h"
#include "r300_tgsi_to_rc.h"
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;
}
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
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;
}
#include "radeon_compiler.h"
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)
static void set_vertex_inputs_outputs(struct r300_vertex_program_compiler * c)
{
struct r300_vertex_shader * vs = c->UserData;
struct tgsi_shader_info* info = &vs->info;
boolean pointsize = false;
int out_colors = 0;
int colors = 0;
int out_generic = 0;
int generic = 0;
int i;
/* Fill in the input mapping */
for (i = 0; i < info->num_inputs; i++)
c->code->inputs[i] = i;
/* Fill in the output mapping */
for (i = 0; i < info->num_outputs; i++) {
switch (info->output_semantic_name[i]) {
case TGSI_SEMANTIC_PSIZE:
assembler->point_size = TRUE;
pointsize = true;
break;
case TGSI_SEMANTIC_COLOR:
assembler->out_colors++;
out_colors++;
break;
case TGSI_SEMANTIC_FOG:
case TGSI_SEMANTIC_GENERIC:
assembler->out_texcoords++;
out_generic++;
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);
if (parser.FullToken.Token.Type != TGSI_TOKEN_TYPE_DECLARATION)
continue;
struct tgsi_full_declaration * decl = &parser.FullToken.FullDeclaration;
if (decl->Declaration.File != TGSI_FILE_OUTPUT)
continue;
switch (decl->Semantic.SemanticName) {
case TGSI_SEMANTIC_POSITION:
c->code->outputs[decl->DeclarationRange.First] = 0;
break;
case TGSI_TOKEN_TYPE_IMMEDIATE:
debug_printf("r300: Emitting immediate to constant buffer, "
"position %d\n",
assembler->imm_offset + assembler->imm_count);
/* I am not amused by the length of these. */
for (i = 0; i < 4; i++) {
consts->constants[assembler->imm_offset +
assembler->imm_count][i] =
parser.FullToken.FullImmediate.u[i].Float;
}
assembler->imm_count++;
case TGSI_SEMANTIC_PSIZE:
c->code->outputs[decl->DeclarationRange.First] = 1;
break;
case TGSI_TOKEN_TYPE_INSTRUCTION:
r300_vs_instruction(vs, assembler,
&parser.FullToken.FullInstruction);
case TGSI_SEMANTIC_COLOR:
c->code->outputs[decl->DeclarationRange.First] = 1 +
(pointsize ? 1 : 0) +
colors++;
break;
case TGSI_SEMANTIC_FOG:
case TGSI_SEMANTIC_GENERIC:
c->code->outputs[decl->DeclarationRange.First] = 1 +
(pointsize ? 1 : 0) +
out_colors +
generic++;
break;
default:
debug_printf("r300: vs: Bad semantic declaration %d\n",
decl->Semantic.SemanticName);
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);
}
void r300_translate_vertex_shader(struct r300_context* r300,
struct r300_vertex_shader* vs)
{
struct r300_vertex_program_compiler compiler;
struct tgsi_to_rc ttr;
printf("translate_vertex_shader\n");
/* Setup the compiler */
rc_init(&compiler.Base);
compiler.Base.Debug = 1;
compiler.code = &vs->code;
compiler.UserData = vs;
if (compiler.Base.Debug) {
debug_printf("r300: Initial vertex program\n");
tgsi_dump(vs->state.tokens, 0);
}
/* Translate TGSI to our internal representation */
ttr.compiler = &compiler.Base;
ttr.info = &vs->info;
r300_tgsi_to_rc(&ttr, vs->state.tokens);
compiler.RequiredOutputs = ~(~0 << vs->info.num_outputs);
compiler.SetHwInputOutput = &set_vertex_inputs_outputs;
/* Invoke the compiler */
r3xx_compile_vertex_program(&compiler);
if (compiler.Base.Error) {
/* Todo: Fail gracefully */
fprintf(stderr, "r300 VP: Compiler error\n");
abort();
}
/* And, finally... */
rc_destroy(&compiler.Base);
vs->translated = TRUE;
}
/* 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)
struct r300_vertex_program_code r300_passthrough_vertex_shader = {
.length = 8, /* two instructions */
/* MOV out[0], in[0] */
.body.d[0] = 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,
.body.d[1] = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
R300_PVS_SRC_OFFSET(0) | R300_PVS_SRC_SWIZZLE_XYZW,
.body.d[2] = R300_PVS_SRC_SWIZZLE_ZERO,
.body.d[3] = 0x0,
/* MOV out[1], in[1] */
.body.d[4] = 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,
.body.d[5] = R300_PVS_SRC_REG_TYPE(R300_PVS_SRC_REG_INPUT) |
R300_PVS_SRC_OFFSET(1) | R300_PVS_SRC_SWIZZLE_XYZW,
.body.d[6] = R300_PVS_SRC_SWIZZLE_ZERO,
.body.d[7] = 0x0,
.inputs[0] = 0,
.inputs[1] = 1,
.outputs[0] = 0,
.outputs[1] = 1,
.InputsRead = 3,
.OutputsWritten = 3
};

View File

@@ -23,133 +23,30 @@
#ifndef R300_VS_H
#define R300_VS_H
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_dump.h"
#include "pipe/p_state.h"
#include "tgsi/tgsi_scan.h"
#include "r300_context.h"
#include "r300_debug.h"
#include "r300_reg.h"
#include "r300_screen.h"
#include "r300_shader_inlines.h"
#include "radeon_code.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)
struct r300_context;
#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)
struct r300_vertex_shader {
/* Parent class */
struct pipe_shader_state state;
struct tgsi_shader_info info;
/* 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];
/* Fallback shader, because Draw has issues */
struct draw_vertex_shader* draw;
/* Has this shader been translated yet? */
boolean translated;
/* Machine code (if translated) */
struct r300_vertex_program_code code;
};
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,
};
extern struct r300_vertex_program_code r300_passthrough_vertex_shader;
void r300_translate_vertex_shader(struct r300_context* r300,
struct r300_vertex_shader* vs);

View File

@@ -66,6 +66,8 @@ static struct r3xx_fragment_shader r3xx_texture_fragment_shader = {
R300_ALPHA_ADDR1(0) | R300_ALPHA_ADDR2(0) | R300_ALU_DSTA_OUTPUT,
};
struct r300_fs_asm;
void r3xx_fs_finalize(struct r300_fragment_shader* fs,
struct r300_fs_asm* assembler);

View File

@@ -122,6 +122,8 @@ static struct r5xx_fragment_shader r5xx_texture_fragment_shader = {
R500_ALU_RGBA_A_SWIZ_0,
};
struct r300_fs_asm;
void r5xx_fs_finalize(struct r5xx_fragment_shader* fs,
struct r300_fs_asm* assembler);