Make the texcoord speedhack a bit less aggressive at eliminating uvscaleoffset uniform updates.
Should fix #4688 and the new problem in #2919 while keeping Frontier Gate Boost working.
This commit is contained in:
parent
04742e00fc
commit
eea8413a82
6 changed files with 72 additions and 44 deletions
|
@ -732,7 +732,7 @@ void DIRECTX9_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GE_CMD_VERTEXTYPE:
|
case GE_CMD_VERTEXTYPE:
|
||||||
if (diff)
|
if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK))
|
||||||
shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET);
|
shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -1080,8 +1080,9 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) {
|
||||||
case GE_CMD_TEXSIZE5:
|
case GE_CMD_TEXSIZE5:
|
||||||
case GE_CMD_TEXSIZE6:
|
case GE_CMD_TEXSIZE6:
|
||||||
case GE_CMD_TEXSIZE7:
|
case GE_CMD_TEXSIZE7:
|
||||||
if (diff)
|
if (diff) {
|
||||||
gstate_c.textureChanged = true;
|
gstate_c.textureChanged = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GE_CMD_ZBUFPTR:
|
case GE_CMD_ZBUFPTR:
|
||||||
|
|
|
@ -391,56 +391,81 @@ void LinkedShader::UpdateUniforms(u32 vertType) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Texturing
|
// Texturing
|
||||||
if (dirty & DIRTY_UVSCALEOFFSET) {
|
|
||||||
float uvscaleoff[4];
|
|
||||||
float invW = 1.0f / (float)gstate_c.curTextureWidth;
|
|
||||||
float invH = 1.0f / (float)gstate_c.curTextureHeight;
|
|
||||||
|
|
||||||
|
// If this dirty check is changed to true, Frontier Gate Boost works in texcoord speedhack mode.
|
||||||
|
// This means that it's not a flushing issue.
|
||||||
|
// It uses GE_TEXMAP_TEXTURE_MATRIX with GE_PROJMAP_UV a lot.
|
||||||
|
// Can't figure out why it doesn't dirty at the right points though...
|
||||||
|
if (dirty & DIRTY_UVSCALEOFFSET) {
|
||||||
|
const float invW = 1.0f / (float)gstate_c.curTextureWidth;
|
||||||
|
const float invH = 1.0f / (float)gstate_c.curTextureHeight;
|
||||||
|
const int w = gstate.getTextureWidth(0);
|
||||||
|
const int h = gstate.getTextureHeight(0);
|
||||||
|
const float widthFactor = (float)w * invW;
|
||||||
|
const float heightFactor = (float)h * invH;
|
||||||
|
|
||||||
|
static const float rescale[4] = {1.0f, 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f};
|
||||||
|
const float factor = rescale[(vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT];
|
||||||
|
|
||||||
|
float uvscaleoff[4];
|
||||||
|
|
||||||
|
switch (gstate.getUVGenMode()) {
|
||||||
|
case GE_TEXMAP_TEXTURE_COORDS:
|
||||||
|
// Not sure what GE_TEXMAP_UNKNOWN is, but seen in Riviera. Treating the same as GE_TEXMAP_TEXTURE_COORDS works.
|
||||||
|
case GE_TEXMAP_UNKNOWN:
|
||||||
if (g_Config.bPrescaleUV) {
|
if (g_Config.bPrescaleUV) {
|
||||||
|
// Shouldn't even get here as we won't use the uniform in the shader.
|
||||||
// We are here but are prescaling UV in the decoder? Let's do the same as in the other case
|
// We are here but are prescaling UV in the decoder? Let's do the same as in the other case
|
||||||
// except consider *Scale and *Off to be 1 and 0.
|
// except consider *Scale and *Off to be 1 and 0.
|
||||||
int w = gstate.getTextureWidth(0);
|
|
||||||
int h = gstate.getTextureHeight(0);
|
|
||||||
float widthFactor = (float)w * invW;
|
|
||||||
float heightFactor = (float)h * invH;
|
|
||||||
// Not sure what GE_TEXMAP_UNKNOWN is, but seen in Riviera. Treating the same as GE_TEXMAP_TEXTURE_COORDS works.
|
|
||||||
if (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN) {
|
|
||||||
static const float rescale[4] = {1.0f, 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f};
|
|
||||||
float factor = rescale[(vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT];
|
|
||||||
uvscaleoff[0] = factor * widthFactor;
|
uvscaleoff[0] = factor * widthFactor;
|
||||||
uvscaleoff[1] = factor * heightFactor;
|
uvscaleoff[1] = factor * heightFactor;
|
||||||
uvscaleoff[2] = 0;
|
|
||||||
uvscaleoff[3] = 0;
|
|
||||||
} else {
|
|
||||||
uvscaleoff[0] = widthFactor;
|
|
||||||
uvscaleoff[1] = heightFactor;
|
|
||||||
uvscaleoff[2] = 0.0f;
|
uvscaleoff[2] = 0.0f;
|
||||||
uvscaleoff[3] = 0.0f;
|
uvscaleoff[3] = 0.0f;
|
||||||
}
|
|
||||||
glUniform4fv(u_uvscaleoffset, 1, uvscaleoff);
|
|
||||||
} else {
|
} else {
|
||||||
int w = gstate.getTextureWidth(0);
|
|
||||||
int h = gstate.getTextureHeight(0);
|
|
||||||
float widthFactor = (float)w * invW;
|
|
||||||
float heightFactor = (float)h * invH;
|
|
||||||
// Not sure what GE_TEXMAP_UNKNOWN is, but seen in Riviera. Treating the same as GE_TEXMAP_TEXTURE_COORDS works.
|
|
||||||
static const float rescale[4] = {1.0f, 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f};
|
|
||||||
float factor = rescale[(vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT];
|
|
||||||
if (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN) {
|
|
||||||
uvscaleoff[0] = gstate_c.uv.uScale * factor * widthFactor;
|
uvscaleoff[0] = gstate_c.uv.uScale * factor * widthFactor;
|
||||||
uvscaleoff[1] = gstate_c.uv.vScale * factor * heightFactor;
|
uvscaleoff[1] = gstate_c.uv.vScale * factor * heightFactor;
|
||||||
uvscaleoff[2] = gstate_c.uv.uOff * widthFactor;
|
uvscaleoff[2] = gstate_c.uv.uOff * widthFactor;
|
||||||
uvscaleoff[3] = gstate_c.uv.vOff * heightFactor;
|
uvscaleoff[3] = gstate_c.uv.vOff * heightFactor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
// These two work the same whether or not we prescale UV.
|
||||||
|
|
||||||
|
case GE_TEXMAP_TEXTURE_MATRIX:
|
||||||
|
// UV coords (that need "factor") are only used here if the getUVProjMode == 1.
|
||||||
|
// Otherwise we just use it to scale the coordinates to the texture.
|
||||||
|
// Factor is used even if prescale is enabled, because prescale doesn't apply if the mode
|
||||||
|
// is texture_matrix.
|
||||||
|
if (gstate.getUVProjMode() == GE_PROJMAP_UV) {
|
||||||
|
uvscaleoff[0] = widthFactor * factor;
|
||||||
|
uvscaleoff[1] = heightFactor * factor;
|
||||||
} else {
|
} else {
|
||||||
uvscaleoff[0] = factor * widthFactor;
|
// In these other modes we only use uvscaleoff to scale to the texture size.
|
||||||
uvscaleoff[1] = factor * heightFactor;
|
uvscaleoff[0] = widthFactor;
|
||||||
|
uvscaleoff[1] = heightFactor;
|
||||||
|
}
|
||||||
uvscaleoff[2] = 0.0f;
|
uvscaleoff[2] = 0.0f;
|
||||||
uvscaleoff[3] = 0.0f;
|
uvscaleoff[3] = 0.0f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GE_TEXMAP_ENVIRONMENT_MAP:
|
||||||
|
// In this mode we only use uvscaleoff to scale to the texture size.
|
||||||
|
uvscaleoff[0] = widthFactor;
|
||||||
|
uvscaleoff[1] = heightFactor;
|
||||||
|
uvscaleoff[2] = 0.0f;
|
||||||
|
uvscaleoff[3] = 0.0f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ERROR_LOG_REPORT(G3D, "Unexpected UV gen mode: %d", gstate.getUVGenMode());
|
||||||
}
|
}
|
||||||
glUniform4fv(u_uvscaleoffset, 1, uvscaleoff);
|
glUniform4fv(u_uvscaleoffset, 1, uvscaleoff);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// Transform
|
||||||
|
if (dirty & DIRTY_WORLDMATRIX) {
|
||||||
|
SetMatrix4x3(u_world, gstate.worldMatrix);
|
||||||
|
}
|
||||||
// Transform
|
// Transform
|
||||||
if (dirty & DIRTY_WORLDMATRIX) {
|
if (dirty & DIRTY_WORLDMATRIX) {
|
||||||
SetMatrix4x3(u_world, gstate.worldMatrix);
|
SetMatrix4x3(u_world, gstate.worldMatrix);
|
||||||
|
@ -581,8 +606,10 @@ void ShaderManager::DirtyLastShader() { // disables vertex arrays
|
||||||
|
|
||||||
|
|
||||||
LinkedShader *ShaderManager::ApplyShader(int prim, u32 vertType) {
|
LinkedShader *ShaderManager::ApplyShader(int prim, u32 vertType) {
|
||||||
if (g_Config.bPrescaleUV)
|
// This doesn't work - we miss some events that really do need to dirty the prescale.
|
||||||
globalDirty_ &= ~DIRTY_UVSCALEOFFSET;
|
// like changing the texmapmode.
|
||||||
|
// if (g_Config.bPrescaleUV)
|
||||||
|
// globalDirty_ &= ~DIRTY_UVSCALEOFFSET;
|
||||||
|
|
||||||
if (globalDirty_) {
|
if (globalDirty_) {
|
||||||
if (lastShader_)
|
if (lastShader_)
|
||||||
|
|
|
@ -300,7 +300,6 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||||
scaleUV = !g_Config.bPrescaleUV;
|
scaleUV = !g_Config.bPrescaleUV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool skinningEnabled = vertTypeIsSkinningEnabled(vertType);
|
bool skinningEnabled = vertTypeIsSkinningEnabled(vertType);
|
||||||
|
|
||||||
int w = gstate.getTextureWidth(0);
|
int w = gstate.getTextureWidth(0);
|
||||||
|
|
|
@ -700,8 +700,8 @@ void VertexDecoder::SetVertexType(u32 fmt, VertexDecoderJitCache *jitCache) {
|
||||||
if (tcalign[tc] > biggest)
|
if (tcalign[tc] > biggest)
|
||||||
biggest = tcalign[tc];
|
biggest = tcalign[tc];
|
||||||
|
|
||||||
// NOTE: That we check getTextureFunction here means that we must include it in the decoder ID!
|
// NOTE: That we check getUVGenMode here means that we must include it in the decoder ID!
|
||||||
if (g_Config.bPrescaleUV && !throughmode && (gstate.getTextureFunction() == 0 || gstate.getTextureFunction() == 3)) {
|
if (g_Config.bPrescaleUV && !throughmode && (gstate.getUVGenMode() == 0 || gstate.getUVGenMode() == 3)) {
|
||||||
steps_[numSteps_++] = tcstep_prescale[tc];
|
steps_[numSteps_++] = tcstep_prescale[tc];
|
||||||
decFmt.uvfmt = DEC_FLOAT_2;
|
decFmt.uvfmt = DEC_FLOAT_2;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -208,7 +208,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf
|
||||||
// Add all the uniforms we'll need to transform properly.
|
// Add all the uniforms we'll need to transform properly.
|
||||||
}
|
}
|
||||||
|
|
||||||
bool prescale = g_Config.bPrescaleUV && !throughmode && gstate.getTextureFunction() == 0;
|
bool prescale = g_Config.bPrescaleUV && !throughmode && (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN);
|
||||||
|
|
||||||
if (useHWTransform) {
|
if (useHWTransform) {
|
||||||
// When transforming by hardware, we need a great deal more uniforms...
|
// When transforming by hardware, we need a great deal more uniforms...
|
||||||
|
@ -553,6 +553,7 @@ void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransf
|
||||||
break;
|
break;
|
||||||
case GE_PROJMAP_UV: // Use unscaled UV as source
|
case GE_PROJMAP_UV: // Use unscaled UV as source
|
||||||
{
|
{
|
||||||
|
// prescale is false here.
|
||||||
static const char *rescaleuv[4] = {"", " * 1.9921875", " * 1.999969482421875", ""}; // 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f};
|
static const char *rescaleuv[4] = {"", " * 1.9921875", " * 1.999969482421875", ""}; // 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f};
|
||||||
const char *factor = rescaleuv[(vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT];
|
const char *factor = rescaleuv[(vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT];
|
||||||
temp_tc = StringFromFormat("vec4(texcoord.xy %s, 0.0, 1.0)", factor);
|
temp_tc = StringFromFormat("vec4(texcoord.xy %s, 0.0, 1.0)", factor);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue