nouveau: add result scaling to shader backend, use it in RSQ emul for NV40.
This commit is contained in:
@@ -179,7 +179,7 @@ nvsBuildTextShader(GLcontext *ctx, GLenum target, const char *text)
|
||||
strlen(text),
|
||||
&nvs->mesa.vp);
|
||||
} else if (target == GL_FRAGMENT_PROGRAM_ARB) {
|
||||
_mesa_init_fragment_program(ctx, &nvs->mesa.fp, GL_VERTEX_PROGRAM_ARB, 0);
|
||||
_mesa_init_fragment_program(ctx, &nvs->mesa.fp, GL_FRAGMENT_PROGRAM_ARB, 0);
|
||||
_mesa_parse_arb_fragment_program(ctx,
|
||||
GL_FRAGMENT_PROGRAM_ARB,
|
||||
text,
|
||||
|
||||
@@ -194,6 +194,16 @@ typedef enum {
|
||||
NVS_TEX_TARGET_UNKNOWN = 0
|
||||
} nvsTexTarget;
|
||||
|
||||
typedef enum {
|
||||
NVS_SCALE_1X = 0,
|
||||
NVS_SCALE_2X = 1,
|
||||
NVS_SCALE_4X = 2,
|
||||
NVS_SCALE_8X = 3,
|
||||
NVS_SCALE_INV_2X = 5,
|
||||
NVS_SCALE_INV_4X = 6,
|
||||
NVS_SCALE_INV_8X = 7,
|
||||
} nvsScale;
|
||||
|
||||
/* Arith/TEX instructions */
|
||||
typedef struct nvs_instruction {
|
||||
nvsFragmentHeader header;
|
||||
@@ -203,6 +213,7 @@ typedef struct nvs_instruction {
|
||||
|
||||
nvsRegister dest;
|
||||
unsigned int mask;
|
||||
nvsScale dest_scale;
|
||||
|
||||
nvsRegister src[3];
|
||||
|
||||
@@ -307,6 +318,7 @@ struct _nvsFunc {
|
||||
|
||||
void (*InitInstruction) (nvsFunc *);
|
||||
int (*SupportsOpcode) (nvsFunc *, nvsOpcode);
|
||||
int (*SupportsResultScale) (nvsFunc *, nvsScale);
|
||||
void (*SetOpcode) (nvsFunc *, unsigned int opcode,
|
||||
int slot);
|
||||
void (*SetCCUpdate) (nvsFunc *);
|
||||
@@ -314,6 +326,7 @@ struct _nvsFunc {
|
||||
nvsSwzComp *swizzle);
|
||||
void (*SetResult) (nvsFunc *, nvsRegister *,
|
||||
unsigned int mask, int slot);
|
||||
void (*SetResultScale) (nvsFunc *, nvsScale);
|
||||
void (*SetSource) (nvsFunc *, nvsRegister *, int pos);
|
||||
void (*SetTexImageUnit) (nvsFunc *, int unit);
|
||||
void (*SetSaturate) (nvsFunc *);
|
||||
|
||||
@@ -402,6 +402,7 @@ pass0_emit(nouveauShader *nvs, nvsFragmentHeader *parent, int fpos,
|
||||
sif->saturate = saturate;
|
||||
sif->dest = dst;
|
||||
sif->mask = mask;
|
||||
sif->dest_scale = NVS_SCALE_1X;
|
||||
sif->src[0] = src0;
|
||||
sif->src[1] = src1;
|
||||
sif->src[2] = src2;
|
||||
@@ -667,25 +668,13 @@ pass0_emulate_instruction(nouveauShader *nvs,
|
||||
}
|
||||
break;
|
||||
case OPCODE_RSQ:
|
||||
if (rec->const_half.file != NVS_FILE_CONST) {
|
||||
GLfloat const_half[4] = { 0.5, 0.0, 0.0, 0.0 };
|
||||
pass0_make_reg(nvs, &rec->const_half, NVS_FILE_CONST,
|
||||
_mesa_add_unnamed_constant(
|
||||
nvs->mesa.vp.Base.Parameters,
|
||||
const_half, 4));
|
||||
COPY_4V(nvs->params[rec->const_half.index].val,
|
||||
const_half);
|
||||
}
|
||||
pass0_make_reg(nvs, &temp, NVS_FILE_TEMP, -1);
|
||||
ARITHu(NVS_OP_LG2, temp, SMASK_X, 0,
|
||||
nvsAbs(nvsSwizzle(src[0], X, X, X, X)),
|
||||
nvr_unused, nvr_unused);
|
||||
ARITHu(NVS_OP_MUL, temp, SMASK_X, 0,
|
||||
nvsSwizzle(temp, X, X, X, X),
|
||||
nvsNegate(rec->const_half),
|
||||
nvr_unused);
|
||||
nvsinst->dest_scale = NVS_SCALE_INV_2X;
|
||||
ARITH (NVS_OP_EX2, dest, mask, sat,
|
||||
nvsSwizzle(temp, X, X, X, X),
|
||||
nvsNegate(nvsSwizzle(temp, X, X, X, X)),
|
||||
nvr_unused, nvr_unused);
|
||||
break;
|
||||
case OPCODE_SCS:
|
||||
|
||||
@@ -135,6 +135,10 @@ pass2_add_instruction(nvsPtr nvs, nvsInstruction *inst,
|
||||
|
||||
reg = pass2_mangle_reg(nvs, inst, inst->dest);
|
||||
shader->SetResult(shader, ®, inst->mask, slot);
|
||||
|
||||
if (inst->dest_scale != NVS_SCALE_1X) {
|
||||
shader->SetResultScale(shader, inst->dest_scale);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
||||
@@ -11,6 +11,30 @@ struct _op_xlat NVFP_TX_BOP[64];
|
||||
* - These extend the NV30 routines, which are almost identical. NV40
|
||||
* just has branching hacked into the instruction set.
|
||||
*/
|
||||
static int
|
||||
NV40FPSupportsResultScale(nvsFunc *shader, nvsScale scale)
|
||||
{
|
||||
switch (scale) {
|
||||
case NVS_SCALE_1X:
|
||||
case NVS_SCALE_2X:
|
||||
case NVS_SCALE_4X:
|
||||
case NVS_SCALE_8X:
|
||||
case NVS_SCALE_INV_2X:
|
||||
case NVS_SCALE_INV_4X:
|
||||
case NVS_SCALE_INV_8X:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
NV40FPSetResultScale(nvsFunc *shader, nvsScale scale)
|
||||
{
|
||||
shader->inst[2] &= ~NV40_FP_OP_DST_SCALE_MASK;
|
||||
shader->inst[2] |= ((unsigned int)scale << NV40_FP_OP_DST_SCALE_SHIFT);
|
||||
}
|
||||
|
||||
static void
|
||||
NV40FPSetBranchTarget(nvsFunc *shader, int addr)
|
||||
{
|
||||
@@ -179,6 +203,9 @@ NV40FPInitShaderFuncs(nvsFunc * shader)
|
||||
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_REP , NVS_OP_REP , -1, -1, -1);
|
||||
MOD_OPCODE(NVFP_TX_BOP, NV40_FP_OP_BRA_OPCODE_RET , NVS_OP_RET , -1, -1, -1);
|
||||
|
||||
shader->SupportsResultScale = NV40FPSupportsResultScale;
|
||||
shader->SetResultScale = NV40FPSetResultScale;
|
||||
|
||||
/* fragment.facing */
|
||||
shader->GetSourceID = NV40FPGetSourceID;
|
||||
|
||||
|
||||
@@ -399,8 +399,8 @@
|
||||
|
||||
/* high order bits of SRC1 */
|
||||
#define NV40_FP_OP_OPCODE_IS_BRANCH (1<<31)
|
||||
#define NV40_FP_OP_SRC_SCALE_SHIFT 28
|
||||
#define NV40_FP_OP_SRC_SCALE_MASK (3 << 28)
|
||||
#define NV40_FP_OP_DST_SCALE_SHIFT 28
|
||||
#define NV40_FP_OP_DST_SCALE_MASK (3 << 28)
|
||||
|
||||
/* SRC1 LOOP */
|
||||
#define NV40_FP_OP_LOOP_INCR_SHIFT 19
|
||||
|
||||
Reference in New Issue
Block a user