void
_mesa_emit_nv_temp_initialization(struct gl_context *ctx,
				  struct gl_program *program)
{
   struct prog_instruction *inst;
   GLuint i;
   struct gl_shader_compiler_options* options =
         &ctx->ShaderCompilerOptions[_mesa_program_target_to_index(program->Target)];

   if (!options->EmitNVTempInitialization)
      return;

   /* We'll swizzle up a zero temporary so we can use it for the
    * ARL.
    */
   if (program->NumTemporaries == 0)
      program->NumTemporaries = 1;

   _mesa_insert_instructions(program, 0, program->NumTemporaries + 1);

   for (i = 0; i < program->NumTemporaries; i++) {
      struct prog_instruction *inst = &program->Instructions[i];

      inst->Opcode = OPCODE_SWZ;
      inst->DstReg.File = PROGRAM_TEMPORARY;
      inst->DstReg.Index = i;
      inst->DstReg.WriteMask = WRITEMASK_XYZW;
      inst->SrcReg[0].File = PROGRAM_TEMPORARY;
      inst->SrcReg[0].Index = 0;
      inst->SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO,
					      SWIZZLE_ZERO,
					      SWIZZLE_ZERO,
					      SWIZZLE_ZERO);
   }

   inst = &program->Instructions[i];
   inst->Opcode = OPCODE_ARL;
   inst->DstReg.File = PROGRAM_ADDRESS;
   inst->DstReg.Index = 0;
   inst->DstReg.WriteMask = WRITEMASK_XYZW;
   inst->SrcReg[0].File = PROGRAM_TEMPORARY;
   inst->SrcReg[0].Index = 0;
   inst->SrcReg[0].Swizzle = SWIZZLE_XXXX;

   if (program->NumAddressRegs == 0)
      program->NumAddressRegs = 1;
}
Beispiel #2
0
void insert_wpos_code(GLcontext *ctx, struct gl_fragment_program *fprog)
{
    static const gl_state_index winstate[STATE_LENGTH]
         = { STATE_INTERNAL, STATE_FB_SIZE, 0, 0, 0};
    struct prog_instruction *newInst, *inst;
    GLint  win_size;  /* state reference */
    GLuint wpos_temp; /* temp register */
    int i, j;

    /* PARAM win_size = STATE_FB_SIZE */
    win_size = _mesa_add_state_reference(fprog->Base.Parameters, winstate);

    wpos_temp = fprog->Base.NumTemporaries++;

    /* scan program where WPOS is used and replace with wpos_temp */
    inst = fprog->Base.Instructions;
    for (i = 0; i < fprog->Base.NumInstructions; i++) {
        for (j=0; j < 3; j++) {
            if(inst->SrcReg[j].File == PROGRAM_INPUT && 
               inst->SrcReg[j].Index == FRAG_ATTRIB_WPOS) {
                inst->SrcReg[j].File = PROGRAM_TEMPORARY;
                inst->SrcReg[j].Index = wpos_temp;
            }
        }
        inst++;
    }

    _mesa_insert_instructions(&(fprog->Base), 0, 1);

    newInst = fprog->Base.Instructions;
    /* invert wpos.y
     * wpos_temp.xyzw = wpos.x-yzw + winsize.0y00 */
    newInst[0].Opcode = OPCODE_ADD;
    newInst[0].DstReg.File = PROGRAM_TEMPORARY;
    newInst[0].DstReg.Index = wpos_temp;
    newInst[0].DstReg.WriteMask = WRITEMASK_XYZW;

    newInst[0].SrcReg[0].File = PROGRAM_INPUT;
    newInst[0].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
    newInst[0].SrcReg[0].Swizzle = SWIZZLE_XYZW;
    newInst[0].SrcReg[0].Negate = NEGATE_Y;

    newInst[0].SrcReg[1].File = PROGRAM_STATE_VAR;
    newInst[0].SrcReg[1].Index = win_size;
    newInst[0].SrcReg[1].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ZERO);

}
/**
 * Transform the program to support fragment.position.
 *
 * Introduce a small fragment at the start of the program that will be
 * the only code that directly reads the FRAG_ATTRIB_WPOS input.
 * All other code pieces that reference that input will be rewritten
 * to read from a newly allocated temporary.
 *
 * \todo if/when r5xx supports the radeon_program architecture, this is a
 * likely candidate for code sharing.
 */
static void insert_WPOS_trailer(struct r300_fragment_program_compiler *compiler)
{
	GLuint InputsRead = compiler->fp->mesa_program.Base.InputsRead;

	if (!(InputsRead & FRAG_BIT_WPOS))
		return;

	static gl_state_index tokens[STATE_LENGTH] = {
		STATE_INTERNAL, STATE_R300_WINDOW_DIMENSION, 0, 0, 0
	};
	struct prog_instruction *fpi;
	GLuint window_index;
	int i = 0;
	GLuint tempregi = _mesa_find_free_register(compiler->program, PROGRAM_TEMPORARY);

	_mesa_insert_instructions(compiler->program, 0, 3);
	fpi = compiler->program->Instructions;

	/* perspective divide */
	fpi[i].Opcode = OPCODE_RCP;

	fpi[i].DstReg.File = PROGRAM_TEMPORARY;
	fpi[i].DstReg.Index = tempregi;
	fpi[i].DstReg.WriteMask = WRITEMASK_W;
	fpi[i].DstReg.CondMask = COND_TR;

	fpi[i].SrcReg[0].File = PROGRAM_INPUT;
	fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
	fpi[i].SrcReg[0].Swizzle = SWIZZLE_WWWW;
	i++;

	fpi[i].Opcode = OPCODE_MUL;

	fpi[i].DstReg.File = PROGRAM_TEMPORARY;
	fpi[i].DstReg.Index = tempregi;
	fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
	fpi[i].DstReg.CondMask = COND_TR;

	fpi[i].SrcReg[0].File = PROGRAM_INPUT;
	fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
	fpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;

	fpi[i].SrcReg[1].File = PROGRAM_TEMPORARY;
	fpi[i].SrcReg[1].Index = tempregi;
	fpi[i].SrcReg[1].Swizzle = SWIZZLE_WWWW;
	i++;

	/* viewport transformation */
	window_index = _mesa_add_state_reference(compiler->program->Parameters, tokens);

	fpi[i].Opcode = OPCODE_MAD;

	fpi[i].DstReg.File = PROGRAM_TEMPORARY;
	fpi[i].DstReg.Index = tempregi;
	fpi[i].DstReg.WriteMask = WRITEMASK_XYZ;
	fpi[i].DstReg.CondMask = COND_TR;

	fpi[i].SrcReg[0].File = PROGRAM_TEMPORARY;
	fpi[i].SrcReg[0].Index = tempregi;
	fpi[i].SrcReg[0].Swizzle =
	    MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);

	fpi[i].SrcReg[1].File = PROGRAM_STATE_VAR;
	fpi[i].SrcReg[1].Index = window_index;
	fpi[i].SrcReg[1].Swizzle =
	    MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);

	fpi[i].SrcReg[2].File = PROGRAM_STATE_VAR;
	fpi[i].SrcReg[2].Index = window_index;
	fpi[i].SrcReg[2].Swizzle =
	    MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ZERO);
	i++;

	for (; i < compiler->program->NumInstructions; ++i) {
		int reg;
		for (reg = 0; reg < 3; reg++) {
			if (fpi[i].SrcReg[reg].File == PROGRAM_INPUT &&
			    fpi[i].SrcReg[reg].Index == FRAG_ATTRIB_WPOS) {
				fpi[i].SrcReg[reg].File = PROGRAM_TEMPORARY;
				fpi[i].SrcReg[reg].Index = tempregi;
			}
		}
	}
}
Beispiel #4
0
/**
 * Scan/rewrite program to remove reads of custom (output) registers.
 * The passed type has to be PROGRAM_OUTPUT.
 * On some hardware, trying to read an output register causes trouble.
 * So, rewrite the program to use a temporary register in this case.
 */
void
_mesa_remove_output_reads(struct gl_program *prog, gl_register_file type)
{
    GLuint i;
    GLint outputMap[VARYING_SLOT_MAX];
    GLuint numVaryingReads = 0;
    GLboolean usedTemps[MAX_PROGRAM_TEMPS];
    GLuint firstTemp = 0;

    _mesa_find_used_registers(prog, PROGRAM_TEMPORARY,
                              usedTemps, MAX_PROGRAM_TEMPS);

    assert(type == PROGRAM_OUTPUT);

    for (i = 0; i < VARYING_SLOT_MAX; i++)
        outputMap[i] = -1;

    /* look for instructions which read from varying vars */
    for (i = 0; i < prog->NumInstructions; i++) {
        struct prog_instruction *inst = prog->Instructions + i;
        const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);
        GLuint j;
        for (j = 0; j < numSrc; j++) {
            if (inst->SrcReg[j].File == type) {
                /* replace the read with a temp reg */
                const GLuint var = inst->SrcReg[j].Index;
                if (outputMap[var] == -1) {
                    numVaryingReads++;
                    outputMap[var] = _mesa_find_free_register(usedTemps,
                                     MAX_PROGRAM_TEMPS,
                                     firstTemp);
                    firstTemp = outputMap[var] + 1;
                }
                inst->SrcReg[j].File = PROGRAM_TEMPORARY;
                inst->SrcReg[j].Index = outputMap[var];
            }
        }
    }

    if (numVaryingReads == 0)
        return; /* nothing to be done */

    /* look for instructions which write to the varying vars identified above */
    for (i = 0; i < prog->NumInstructions; i++) {
        struct prog_instruction *inst = prog->Instructions + i;
        if (inst->DstReg.File == type &&
                outputMap[inst->DstReg.Index] >= 0) {
            /* change inst to write to the temp reg, instead of the varying */
            inst->DstReg.File = PROGRAM_TEMPORARY;
            inst->DstReg.Index = outputMap[inst->DstReg.Index];
        }
    }

    /* insert new instructions to copy the temp vars to the varying vars */
    {
        struct prog_instruction *inst;
        GLint endPos, var;

        /* Look for END instruction and insert the new varying writes */
        endPos = -1;
        for (i = 0; i < prog->NumInstructions; i++) {
            struct prog_instruction *inst = prog->Instructions + i;
            if (inst->Opcode == OPCODE_END) {
                endPos = i;
                _mesa_insert_instructions(prog, i, numVaryingReads);
                break;
            }
        }

        assert(endPos >= 0);

        /* insert new MOV instructions here */
        inst = prog->Instructions + endPos;
        for (var = 0; var < VARYING_SLOT_MAX; var++) {
            if (outputMap[var] >= 0) {
                /* MOV VAR[var], TEMP[tmp]; */
                inst->Opcode = OPCODE_MOV;
                inst->DstReg.File = type;
                inst->DstReg.Index = var;
                inst->SrcReg[0].File = PROGRAM_TEMPORARY;
                inst->SrcReg[0].Index = outputMap[var];
                inst++;
            }
        }
    }
}