#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
-#include "pipe/tgsi/util/tgsi_parse.h"
-#include "pipe/tgsi/util/tgsi_build.h"
-#include "pipe/tgsi/util/tgsi_util.h"
+#include "tgsi/util/tgsi_parse.h"
+#include "tgsi/util/tgsi_build.h"
+#include "tgsi/util/tgsi_util.h"
#include "st_mesa_to_tgsi.h"
#include "shader/prog_instruction.h"
#include "shader/prog_parameter.h"
-#define TGSI_DEBUG 0
-
/*
* Map mesa register file to TGSI register file.
*/
static GLuint
map_register_file(
- enum register_file file )
+ enum register_file file,
+ GLuint index,
+ const GLuint immediateMapping[] )
{
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
+ * bundled together as PROGRAM_STATE_VAR, we can't tell from the
+ * mesa register file whether this is a CONSTANT or an
+ * IMMEDIATE, hence we need all the other information.
+ */
case PROGRAM_STATE_VAR:
case PROGRAM_NAMED_PARAM:
case PROGRAM_UNIFORM:
- return TGSI_FILE_CONSTANT;
+ if (immediateMapping && immediateMapping[index] != ~0)
+ return TGSI_FILE_IMMEDIATE;
+ else
+ return TGSI_FILE_CONSTANT;
case PROGRAM_CONSTANT:
return TGSI_FILE_IMMEDIATE;
case PROGRAM_INPUT:
const GLuint outputMapping[],
const GLuint immediateMapping[],
GLuint preamble_size,
- GLuint processor )
+ GLuint processor,
+ GLboolean *insideSubroutine)
{
GLuint i;
struct tgsi_full_dst_register *fulldst;
fullinst->Instruction.NumSrcRegs = _mesa_num_inst_src_regs( inst->Opcode );
fulldst = &fullinst->FullDstRegisters[0];
- fulldst->DstRegister.File = map_register_file( inst->DstReg.File );
+ fulldst->DstRegister.File = map_register_file( inst->DstReg.File, 0, NULL );
fulldst->DstRegister.Index = map_register_file_index(
fulldst->DstRegister.File,
inst->DstReg.Index,
GLuint j;
fullsrc = &fullinst->FullSrcRegisters[i];
- fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File );
+ fullsrc->SrcRegister.File = map_register_file( inst->SrcReg[i].File,
+ inst->SrcReg[i].Index,
+ immediateMapping );
fullsrc->SrcRegister.Index = map_register_file_index(
fullsrc->SrcRegister.File,
inst->SrcReg[i].Index,
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 );
+ /* 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);
+ }
}
}
break;
case OPCODE_BGNSUB:
fullinst->Instruction.Opcode = TGSI_OPCODE_BGNSUB;
+ *insideSubroutine = GL_TRUE;
break;
case OPCODE_BRA:
fullinst->Instruction.Opcode = TGSI_OPCODE_BRA;
break;
case OPCODE_ENDSUB:
fullinst->Instruction.Opcode = TGSI_OPCODE_ENDSUB;
+ *insideSubroutine = GL_FALSE;
break;
case OPCODE_EX2:
fullinst->Instruction.Opcode = TGSI_OPCODE_EX2;
fullinst->Instruction.Opcode = TGSI_OPCODE_RCP;
break;
case OPCODE_RET:
- fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
+ /* If RET is used inside main (not a real subroutine) we may want
+ * to execute END instead of RET. TBD...
+ */
+ if (1 /* *insideSubroutine */) {
+ fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
+ }
+ else {
+ /* inside main() pseudo-function */
+ fullinst->Instruction.Opcode = TGSI_OPCODE_END;
+ }
break;
case OPCODE_RSQ:
fullinst->Instruction.Opcode = TGSI_OPCODE_RSQ;
case OPCODE_TXP:
/* texture lookup with divide by Q component */
/* convert to TEX w/ special flag for division */
- fullinst->Instruction.Opcode = TGSI_OPCODE_TEX;
+ fullinst->Instruction.Opcode = TGSI_OPCODE_TXP;
fullinst->Instruction.NumSrcRegs = 2;
fullinst->InstructionExtTexture.Texture = map_texture_target( inst->TexSrcTarget );
- fullinst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide = TGSI_EXTSWIZZLE_W;
fullinst->FullSrcRegisters[1].SrcRegister.File = TGSI_FILE_SAMPLER;
fullinst->FullSrcRegisters[1].SrcRegister.Index = inst->TexSrcUnit;
break;
fulldst->DstRegister.WriteMask &= TGSI_WRITEMASK_XYZ;
break;
case OPCODE_END:
- fullinst->Instruction.Opcode = TGSI_OPCODE_RET;
+ fullinst->Instruction.Opcode = TGSI_OPCODE_END;
break;
default:
assert( 0 );
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_sampler_decl(GLuint index)
+{
+ struct tgsi_full_declaration decl;
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_SAMPLER;
+ decl.DeclarationRange.First = index;
+ decl.DeclarationRange.Last = index;
+ return decl;
+}
+
+/** Reference into a constant buffer */
+static struct tgsi_full_declaration
+make_constant_decl(GLuint first, GLuint last)
+{
+ struct tgsi_full_declaration decl;
+ decl = tgsi_default_full_declaration();
+ decl.Declaration.File = TGSI_FILE_CONSTANT;
+ decl.DeclarationRange.First = first;
+ decl.DeclarationRange.Last = last;
return decl;
}
+
/**
* Find the temporaries which are used in the given program.
*/
* \param tokens array to store translated tokens in
* \param maxTokens size of the tokens array
*
+ * \return number of tokens placed in 'tokens' buffer, or zero if error
*/
-GLboolean
+GLuint
tgsi_translate_mesa_program(
uint procType,
const struct gl_program *program,
GLuint preamble_size = 0;
GLuint immediates[1000];
GLuint numImmediates = 0;
+ GLboolean insideSubroutine = 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;
}
/* immediates/literals */
+ memset(immediates, ~0, sizeof(immediates));
+
for (i = 0; program->Parameters && i < program->Parameters->NumParameters;
- i++) {
+ i++) {
if (program->Parameters->Parameters[i].Type == PROGRAM_CONSTANT) {
struct tgsi_full_immediate fullimm
- = make_immediate(program->Parameters->ParameterValues[i],
- program->Parameters->Parameters[i].Size);
+ = make_immediate(program->Parameters->ParameterValues[i], 4);
ti += tgsi_build_full_immediate(&fullimm,
&tokens[ti],
header,
}
}
+ /* constant buffer refs */
+ {
+ GLint start = -1, end = -1;
+
+ for (i = 0;
+ program->Parameters && i < program->Parameters->NumParameters;
+ i++) {
+ GLboolean emit = (i == program->Parameters->NumParameters - 1);
+
+ switch (program->Parameters->Parameters[i].Type) {
+ case PROGRAM_ENV_PARAM:
+ case PROGRAM_STATE_VAR:
+ case PROGRAM_NAMED_PARAM:
+ case PROGRAM_UNIFORM:
+ if (start == -1) {
+ /* begin a sequence */
+ start = i;
+ end = i;
+ }
+ else {
+ /* continue sequence */
+ end = i;
+ }
+ break;
+ default:
+ 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);
+ start = end = -1;
+ }
+ }
+ }
+
+ /* texture samplers */
+ 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 );
+ }
+ }
+
+
for( i = 0; i < program->NumInstructions; i++ ) {
compile_instruction(
&program->Instructions[i],
outputMapping,
immediates,
preamble_size,
- procType );
+ procType,
+ &insideSubroutine);
ti += tgsi_build_full_instruction(
&fullinst,
maxTokens - ti );
}
- return GL_TRUE;
+ return ti;
}