/**************************************************************************
*
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
-#include "tgsi/util/tgsi_parse.h"
-#include "tgsi/util/tgsi_build.h"
-#include "tgsi/util/tgsi_util.h"
+#include "tgsi/tgsi_parse.h"
+#include "tgsi/tgsi_build.h"
+#include "tgsi/tgsi_util.h"
+#include "tgsi/tgsi_dump.h"
+#include "tgsi/tgsi_sanity.h"
#include "st_mesa_to_tgsi.h"
#include "shader/prog_instruction.h"
#include "shader/prog_parameter.h"
-
-#define TGSI_DEBUG 0
-
+#include "shader/prog_print.h"
+#include "pipe/p_debug.h"
/*
* Map mesa register file to TGSI register file.
map_register_file(
enum register_file file,
GLuint index,
- const GLuint immediateMapping[] )
+ const GLuint immediateMapping[],
+ GLboolean indirectAccess )
{
switch( file ) {
case PROGRAM_UNDEFINED:
return TGSI_FILE_NULL;
case PROGRAM_TEMPORARY:
return TGSI_FILE_TEMPORARY;
- //case PROGRAM_LOCAL_PARAM:
- //case PROGRAM_ENV_PARAM:
+ /*case PROGRAM_LOCAL_PARAM:*/
+ /*case PROGRAM_ENV_PARAM:*/
/* Because of the longstanding problem with mesa arb shaders
* where constants, immediates and state variables are all
case PROGRAM_STATE_VAR:
case PROGRAM_NAMED_PARAM:
case PROGRAM_UNIFORM:
- if (immediateMapping[index] != ~0)
- return TGSI_FILE_IMMEDIATE;
+ if (!indirectAccess && immediateMapping && immediateMapping[index] != ~0)
+ return TGSI_FILE_IMMEDIATE;
else
return TGSI_FILE_CONSTANT;
case PROGRAM_CONSTANT:
+ if (indirectAccess)
+ return TGSI_FILE_CONSTANT;
+ assert(immediateMapping[index] != ~0);
return TGSI_FILE_IMMEDIATE;
case PROGRAM_INPUT:
return TGSI_FILE_INPUT;
GLuint index,
const GLuint inputMapping[],
const GLuint outputMapping[],
- const GLuint immediateMapping[])
+ const GLuint immediateMapping[],
+ GLboolean indirectAccess )
{
switch( file ) {
case TGSI_FILE_INPUT:
return outputMapping[index];
case TGSI_FILE_IMMEDIATE:
+ if (indirectAccess)
+ return index;
+ assert(immediateMapping[index] != ~0);
return immediateMapping[index];
default:
make_immediate(const float *value, uint size)
{
struct tgsi_full_immediate imm;
- imm.Immediate.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
- imm.Immediate.Size = 1 + size; /* one for the token itself */
+
+ imm = tgsi_default_full_immediate();
+ imm.Immediate.Size += size;
imm.Immediate.DataType = TGSI_IMM_FLOAT32;
- imm.u.ImmediateFloat32 = (struct tgsi_immediate_float32 *) value;
+ imm.u.Pointer = value;
return imm;
}
const GLuint inputMapping[],
const GLuint outputMapping[],
const GLuint immediateMapping[],
+ GLboolean indirectAccess,
GLuint preamble_size,
GLuint processor,
GLboolean *insideSubroutine)
fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
fulldst = &fullinst->FullDstRegisters[0];
- fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL );
+ fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL, GL_FALSE );
fulldst->DstRegister.Index = map_register_file_index(
fulldst->DstRegister.File,
inst->DstReg.Index,
inputMapping,
outputMapping,
- NULL
- );
+ NULL,
+ GL_FALSE );
fulldst->DstRegister.WriteMask = convert_writemask( inst->DstReg.WriteMask );
- for( i = 0; i < fullinst->Instruction.NumSrcRegs; i++ ) {
+ for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
GLuint j;
fullsrc = &fullinst->FullSrcRegisters[i];
- fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File,
- inst->SrcReg[i].Index,
- immediateMapping );
+ fullsrc->SrcRegister.File = map_register_file(
+ inst->SrcReg[i].File,
+ inst->SrcReg[i].Index,
+ immediateMapping,
+ indirectAccess );
fullsrc->SrcRegister.Index = map_register_file_index(
fullsrc->SrcRegister.File,
inst->SrcReg[i].Index,
inputMapping,
outputMapping,
- immediateMapping);
-
- for( j = 0; j < 4; j++ ) {
- GLuint swz;
-
- swz = GET_SWZ( inst->SrcReg[i].Swizzle, j );
- if( swz > SWIZZLE_W ) {
- tgsi_util_set_src_register_extswizzle(
- &fullsrc->SrcRegisterExtSwz,
- swz,
- j );
+ immediateMapping,
+ indirectAccess );
+
+
+ /* swizzle (ext swizzle also depends on negation) */
+ {
+ GLuint swz[4];
+ GLboolean extended = (inst->SrcReg[i].NegateBase != NEGATE_NONE &&
+ inst->SrcReg[i].NegateBase != NEGATE_XYZW);
+ for( j = 0; j < 4; j++ ) {
+ swz[j] = GET_SWZ( inst->SrcReg[i].Swizzle, j );
+ if (swz[j] > SWIZZLE_W)
+ extended = GL_TRUE;
+ }
+ if (extended) {
+ for (j = 0; j < 4; j++) {
+ tgsi_util_set_src_register_extswizzle(&fullsrc->SrcRegisterExtSwz,
+ swz[j], j);
+ }
}
else {
- tgsi_util_set_src_register_swizzle(
- &fullsrc->SrcRegister,
- swz,
- j );
+ for (j = 0; j < 4; j++) {
+ tgsi_util_set_src_register_swizzle(&fullsrc->SrcRegister,
+ swz[j], j);
+ }
}
}
fullinst->Instruction.Opcode = TGSI_OPCODE_INT;
break;
case OPCODE_KIL:
- /* predicated w/ a register */
- fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
+ /* conditional */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
break;
case OPCODE_KIL_NV:
- /* unpredicated */
+ /* predicated */
assert(inst->DstReg.CondMask == COND_TR);
- fullinst->Instruction.Opcode = TGSI_OPCODE_KIL;
+ fullinst->Instruction.Opcode = TGSI_OPCODE_KILP;
break;
case OPCODE_LG2:
fullinst->Instruction.Opcode = TGSI_OPCODE_LG2;
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
- decl.Declaration.Declare = TGSI_DECLARE_RANGE;
decl.Declaration.UsageMask = usage_mask;
decl.Declaration.Semantic = semantic_info;
- decl.u.DeclarationRange.First = index;
- decl.u.DeclarationRange.Last = index;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
if (semantic_info) {
decl.Semantic.SemanticName = semantic_name;
decl.Semantic.SemanticIndex = semantic_index;
}
if (interpolate_info) {
- decl.Declaration.Interpolate = 1;
- decl.Interpolation.Interpolate = interpolate;
+ decl.Declaration.Interpolate = interpolate;
}
return decl;
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_OUTPUT;
- decl.Declaration.Declare = TGSI_DECLARE_RANGE;
decl.Declaration.UsageMask = usage_mask;
decl.Declaration.Semantic = 1;
- decl.u.DeclarationRange.First = index;
- decl.u.DeclarationRange.Last = index;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
decl.Semantic.SemanticName = semantic_name;
decl.Semantic.SemanticIndex = semantic_index;
struct tgsi_full_declaration decl;
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
- decl.Declaration.Declare = TGSI_DECLARE_RANGE;
- decl.u.DeclarationRange.First = start_index;
- decl.u.DeclarationRange.Last = end_index;
+ decl.DeclarationRange.First = start_index;
+ decl.DeclarationRange.Last = end_index;
return decl;
}
+static struct tgsi_full_declaration
+make_addr_decl(
+ GLuint start_index,
+ GLuint end_index )
+{
+ struct tgsi_full_declaration decl;
+
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_ADDRESS;
+ decl.DeclarationRange.First = start_index;
+ decl.DeclarationRange.Last = end_index;
+ return decl;
+}
static struct tgsi_full_declaration
make_sampler_decl(GLuint index)
struct tgsi_full_declaration decl;
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_SAMPLER;
- decl.Declaration.Declare = TGSI_DECLARE_RANGE;
- decl.u.DeclarationRange.First = index;
- decl.u.DeclarationRange.Last = index;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
return decl;
}
struct tgsi_full_declaration decl;
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_CONSTANT;
- decl.Declaration.Declare = TGSI_DECLARE_RANGE;
- decl.u.DeclarationRange.First = first;
- decl.u.DeclarationRange.Last = last;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
return decl;
}
* \return number of tokens placed in 'tokens' buffer, or zero if error
*/
GLuint
-tgsi_translate_mesa_program(
+st_translate_mesa_program(
uint procType,
const struct gl_program *program,
GLuint numInputs,
GLuint immediates[1000];
GLuint numImmediates = 0;
GLboolean insideSubroutine = GL_FALSE;
+ GLboolean indirectAccess = GL_FALSE;
assert(procType == TGSI_PROCESSOR_FRAGMENT ||
procType == TGSI_PROCESSOR_VERTEX);
switch (outputSemanticName[i]) {
case TGSI_SEMANTIC_POSITION:
fulldecl = make_output_decl(i,
- TGSI_SEMANTIC_POSITION, 0, /* Z / Depth */
+ TGSI_SEMANTIC_POSITION, /* Z / Depth */
+ outputSemanticIndex[i],
TGSI_WRITEMASK_Z );
break;
case TGSI_SEMANTIC_COLOR:
fulldecl = make_output_decl(i,
- TGSI_SEMANTIC_COLOR, 0,
+ TGSI_SEMANTIC_COLOR,
+ outputSemanticIndex[i],
TGSI_WRITEMASK_XYZW );
break;
default:
- abort();
+ assert(0);
+ return 0;
}
ti += tgsi_build_full_declaration(&fulldecl,
&tokens[ti],
{
GLboolean tempsUsed[MAX_PROGRAM_TEMPS + 1];
GLboolean inside_range = GL_FALSE;
- GLuint start_range;
+ GLuint start_range = 0;
find_temporaries(program, tempsUsed);
tempsUsed[MAX_PROGRAM_TEMPS] = GL_FALSE;
inside_range = GL_FALSE;
fulldecl = make_temp_decl( start_range, i - 1 );
ti += tgsi_build_full_declaration(
- &fulldecl,
- &tokens[ti],
- header,
- maxTokens - ti );
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
}
}
}
+ /* Declare address register.
+ */
+ if (program->NumAddressRegs > 0) {
+ struct tgsi_full_declaration fulldecl;
+
+ assert( program->NumAddressRegs == 1 );
+
+ fulldecl = make_addr_decl( 0, 0 );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+
+ indirectAccess = GL_TRUE;
+ }
+
/* immediates/literals */
memset(immediates, ~0, sizeof(immediates));
- for (i = 0; program->Parameters && i < program->Parameters->NumParameters;
- i++) {
- if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
- struct tgsi_full_immediate fullimm
- = make_immediate(program->Parameters->ParameterValues[i], 4);
- ti += tgsi_build_full_immediate(&fullimm,
- &tokens[ti],
- header,
- maxTokens - ti);
- immediates[i] = numImmediates;
- numImmediates++;
+ /* Emit immediates only when there is no address register in use.
+ * FIXME: Be smarter and recognize param arrays -- indirect addressing is
+ * only valid within the referenced array.
+ */
+ if (program->Parameters && !indirectAccess) {
+ for (i = 0; i < program->Parameters->NumParameters; i++) {
+ if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
+ struct tgsi_full_immediate fullimm;
+
+ fullimm = make_immediate( program->Parameters->ParameterValues[i], 4 );
+ ti += tgsi_build_full_immediate(
+ &fullimm,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
+ immediates[i] = numImmediates;
+ numImmediates++;
+ }
}
}
/* constant buffer refs */
- {
+ if (program->Parameters) {
GLint start = -1, end = -1;
- for (i = 0;
- program->Parameters && i < program->Parameters->NumParameters;
- i++) {
+ for (i = 0; i < program->Parameters->NumParameters; i++) {
GLboolean emit = (i == program->Parameters->NumParameters - 1);
+ GLboolean matches;
switch (program->Parameters->Parameters[i].Type) {
case PROGRAM_ENV_PARAM:
case PROGRAM_STATE_VAR:
case PROGRAM_NAMED_PARAM:
case PROGRAM_UNIFORM:
+ matches = GL_TRUE;
+ break;
+ case PROGRAM_CONSTANT:
+ matches = indirectAccess;
+ break;
+ default:
+ matches = GL_FALSE;
+ }
+
+ if (matches) {
if (start == -1) {
/* begin a sequence */
start = i;
/* continue sequence */
end = i;
}
- break;
- default:
+ }
+ else {
if (start != -1) {
/* end of sequence */
emit = GL_TRUE;
if (emit && start >= 0) {
struct tgsi_full_declaration fulldecl;
+
fulldecl = make_constant_decl( start, end );
- ti += tgsi_build_full_declaration(&fulldecl,
- &tokens[ti],
- header,
- maxTokens - ti);
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
start = end = -1;
}
}
for (i = 0; i < 8; i++) {
if (program->SamplersUsed & (1 << i)) {
struct tgsi_full_declaration fulldecl;
+
fulldecl = make_sampler_decl( i );
- ti += tgsi_build_full_declaration(&fulldecl,
- &tokens[ti],
- header,
- maxTokens - ti );
+ ti += tgsi_build_full_declaration(
+ &fulldecl,
+ &tokens[ti],
+ header,
+ maxTokens - ti );
}
}
-
- for( i = 0; i < program->NumInstructions; i++ ) {
+ for (i = 0; i < program->NumInstructions; i++) {
compile_instruction(
- &program->Instructions[i],
- &fullinst,
- inputMapping,
- outputMapping,
- immediates,
- preamble_size,
- procType,
- &insideSubroutine);
+ &program->Instructions[i],
+ &fullinst,
+ inputMapping,
+ outputMapping,
+ immediates,
+ indirectAccess,
+ preamble_size,
+ procType,
+ &insideSubroutine );
ti += tgsi_build_full_instruction(
&fullinst,
maxTokens - ti );
}
+#if DEBUG
+ if(!tgsi_sanity_check(tokens)) {
+ debug_printf("Due to sanity check failure(s) above the following shader program is invalid:\n");
+ debug_printf("\nOriginal program:\n%s", program->String);
+ debug_printf("\nMesa program:\n");
+ _mesa_print_program(program);
+ debug_printf("\nTGSI program:\n");
+ tgsi_dump(tokens, 0);
+ assert(0);
+ }
+#endif
+
return ti;
}
-