Add experimental UV prescaling hack, hidden as it's not finished yet.

Most people should ignore this for now, it's a step towards faster skinning in the future.
This commit is contained in:
Henrik Rydgard 2013-07-27 23:21:48 +02:00
parent 988b5539fa
commit 2eaf581bbe
6 changed files with 85 additions and 29 deletions

View File

@ -172,6 +172,9 @@ void Config::Load(const char *iniFileName)
debugConfig->Get("FontWidth", &iFontWidth, 8);
debugConfig->Get("FontHeight", &iFontHeight, 12);
IniFile::Section *gleshacks = iniFile.GetOrCreateSection("GLESHacks");
gleshacks->Get("PrescaleUV", &bPrescaleUV, false);
KeyMap::LoadFromIni(iniFile);
CleanRecent();

View File

@ -113,6 +113,19 @@ public:
int iTouchButtonOpacity;
float fButtonScale;
// GLES backend-specific hacks. Not saved to the ini file, do not add checkboxes. Will be made into
// proper options when good enough.
// PrescaleUV:
// * Applies UV scale/offset when decoding verts. Get rid of some work in the vertex shader,
// saves a uniform upload and is a prerequisite for future optimized hybrid
// (SW skinning, HW transform) skinning.
// * Still has major problems so off by default - need to store tex scale/offset per DeferredDrawCall,
// which currently isn't done so if texscale/offset isn't static (like in Tekken 6) things go wrong.
bool bPrescaleUV;
// End GLES hacks.
// SystemParam
std::string sNickName;
int ilanguage;

View File

@ -55,11 +55,11 @@ void Jit::Comp_FPU3op(u32 op)
case 1: VSUB(fpr.R(fd), fpr.R(fs), fpr.R(ft)); break; //F(fd) = F(fs) - F(ft); //sub
case 2: { //F(fd) = F(fs) * F(ft); //mul
u32 nextOp = Memory::Read_Instruction(js.compilerPC + 4);
// Optimise possible if destination is the same
if (fd == ((nextOp>>6) & 0x1F)) {
// Optimization possible if destination is the same
if (fd == (int)((nextOp>>6) & 0x1F)) {
// VMUL + VNEG -> VNMUL
if (!strcmp(MIPSGetName(nextOp), "neg.s")) {
if (fd == ((nextOp>>11) & 0x1F)) {
if (fd == (int)((nextOp>>11) & 0x1F)) {
VNMUL(fpr.R(fd), fpr.R(fs), fpr.R(ft));
EatInstruction(nextOp);
}

View File

@ -17,8 +17,9 @@
#include "math/lin/matrix4x4.h"
#include "../../Core/MemMap.h"
#include "../ge_constants.h"
#include "Core/Config.h"
#include "Core/MemMap.h"
#include "GPU/ge_constants.h"
#include "VertexDecoder.h"
#include "VertexShaderGenerator.h"
@ -207,6 +208,27 @@ void VertexDecoder::Step_TcFloatThrough() const
uv[1] = uvdata[1];
}
void VertexDecoder::Step_TcU8Prescale() const {
float *uv = (float *)(decoded_ + decFmt.uvoff);
const u8 *uvdata = (const u8 *)(ptr_ + tcoff);
uv[0] = (float)uvdata[0] * (1.f / 128.f) * gstate_c.uScale + gstate_c.uOff;
uv[1] = (float)uvdata[1] * (1.f / 128.f) * gstate_c.vScale + gstate_c.vOff;
}
void VertexDecoder::Step_TcU16Prescale() const {
float *uv = (float *)(decoded_ + decFmt.uvoff);
const u16 *uvdata = (const u16 *)(ptr_ + tcoff);
uv[0] = (float)uvdata[0] * (1.f / 32768.f) * gstate_c.uScale + gstate_c.uOff;
uv[1] = (float)uvdata[1] * (1.f / 32768.f) * gstate_c.vScale + gstate_c.vOff;
}
void VertexDecoder::Step_TcFloatPrescale() const {
float *uv = (float *)(decoded_ + decFmt.uvoff);
const float *uvdata = (const float*)(ptr_ + tcoff);
uv[0] = uvdata[0] * gstate_c.uScale + gstate_c.uOff;
uv[1] = uvdata[1] * gstate_c.vScale + gstate_c.vOff;
}
void VertexDecoder::Step_Color565() const
{
u8 *c = decoded_ + decFmt.c0off;
@ -496,6 +518,13 @@ static const StepFunction tcstep[4] = {
&VertexDecoder::Step_TcFloat,
};
static const StepFunction tcstep_prescale[4] = {
0,
&VertexDecoder::Step_TcU8Prescale,
&VertexDecoder::Step_TcU16Prescale,
&VertexDecoder::Step_TcFloatPrescale,
};
static const StepFunction tcstep_through[4] = {
0,
&VertexDecoder::Step_TcU8,
@ -638,21 +667,26 @@ void VertexDecoder::SetVertexType(u32 fmt) {
if (tcalign[tc] > biggest)
biggest = tcalign[tc];
if(g_DoubleTextureCoordinates)
steps_[numSteps_++] = throughmode ? tcstep_through_Remaster[tc] : tcstep_Remaster[tc];
else
steps_[numSteps_++] = throughmode ? tcstep_through[tc] : tcstep[tc];
switch (tc) {
case GE_VTYPE_TC_8BIT >> GE_VTYPE_TC_SHIFT:
decFmt.uvfmt = throughmode ? DEC_U8A_2 : DEC_U8_2;
break;
case GE_VTYPE_TC_16BIT >> GE_VTYPE_TC_SHIFT:
decFmt.uvfmt = throughmode ? DEC_U16A_2 : DEC_U16_2;
break;
case GE_VTYPE_TC_FLOAT >> GE_VTYPE_TC_SHIFT:
if (g_Config.bPrescaleUV && !throughmode && gstate.getTextureFunction() == 0) {
steps_[numSteps_++] = tcstep_prescale[tc];
decFmt.uvfmt = DEC_FLOAT_2;
break;
} else {
if (g_DoubleTextureCoordinates)
steps_[numSteps_++] = throughmode ? tcstep_through_Remaster[tc] : tcstep_Remaster[tc];
else
steps_[numSteps_++] = throughmode ? tcstep_through[tc] : tcstep[tc];
switch (tc) {
case GE_VTYPE_TC_8BIT >> GE_VTYPE_TC_SHIFT:
decFmt.uvfmt = throughmode ? DEC_U8A_2 : DEC_U8_2;
break;
case GE_VTYPE_TC_16BIT >> GE_VTYPE_TC_SHIFT:
decFmt.uvfmt = throughmode ? DEC_U16A_2 : DEC_U16_2;
break;
case GE_VTYPE_TC_FLOAT >> GE_VTYPE_TC_SHIFT:
decFmt.uvfmt = DEC_FLOAT_2;
break;
}
}
decFmt.uvoff = decOff;

View File

@ -83,24 +83,19 @@ enum {
};
// Right now
// - only contains computed information
// - does decoding in nasty branchfilled loops
// - compiles into list of called functions
// Future TODO
// - should be cached, not recreated every time
// - will compile into list of called functions
// - will compile into lighting fast specialized x86 and ARM
// - will not bother translating components that can be read directly
// by OpenGL ES. Will still have to translate 565 colors and things
// like that. DecodedVertex will not be a fixed struct. Will have to
// do morphing here.
class VertexDecoder
{
public:
VertexDecoder() : coloff(0), nrmoff(0), posoff(0) {}
~VertexDecoder() {}
// prim is needed knowledge for a performance hack (PrescaleUV)
void SetVertexType(u32 vtype);
u32 VertexType() const { return fmt_; }
const DecVtxFormat &GetDecVtxFmt() { return decFmt; }
void DecodeVerts(u8 *decoded, const void *verts, int indexLowerBound, int indexUpperBound) const;
@ -117,8 +112,13 @@ public:
void Step_TcU8() const;
void Step_TcU16() const;
void Step_TcU16Double() const;
void Step_TcFloat() const;
void Step_TcU8Prescale() const;
void Step_TcU16Prescale() const;
void Step_TcFloatPrescale() const;
void Step_TcU16Double() const;
void Step_TcU16Through() const;
void Step_TcU16ThroughDouble() const;
void Step_TcFloatThrough() const;

View File

@ -514,9 +514,15 @@ void GenerateVertexShader(int prim, char *buffer, bool useHWTransform) {
// Step 3: UV generation
if (doTexture) {
bool prescale = g_Config.bPrescaleUV && !throughmode && gstate.getTextureFunction() == 0;
switch (gstate.getUVGenMode()) {
case 0: // Scale-offset. Easy.
WRITE(p, " v_texcoord = a_texcoord * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n");
if (prescale) {
WRITE(p, " v_texcoord = a_texcoord;\n");
} else {
WRITE(p, " v_texcoord = a_texcoord * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n");
}
break;
case 1: // Projection mapping.