Remove the ability to turn off prescaleUV entirely. It's simply better to do it in the vertex decoder.

This commit is contained in:
Henrik Rydgard 2016-12-20 13:27:44 +01:00
parent 80af358eea
commit 9d7983eee8
23 changed files with 100 additions and 413 deletions

View File

@ -730,7 +730,6 @@ static ConfigSetting debuggerSettings[] = {
};
static ConfigSetting speedHackSettings[] = {
ReportedConfigSetting("PrescaleUVCoords", &g_Config.bPrescaleUV, true, true, true),
ReportedConfigSetting("DisableAlphaTest", &g_Config.bDisableAlphaTest, false, true, true),
ConfigSetting(false),

View File

@ -360,14 +360,7 @@ public:
float fAnalogLimiterDeadzone;
// 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;
bool bDisableAlphaTest; // Helps PowerVR immensely, breaks some graphics
bool bDisableAlphaTest; // Helps PowerVR performance immensely, breaks some graphics
// End GLES hacks.
// Use the hardware scaler to scale up the image to save fillrate. Similar to Windows' window size, really.

View File

@ -146,12 +146,9 @@ void SoftwareTransform(
float uscale = 1.0f;
float vscale = 1.0f;
bool scaleUV = false;
if (throughmode) {
uscale /= gstate_c.curTextureWidth;
vscale /= gstate_c.curTextureHeight;
} else {
scaleUV = !g_Config.bPrescaleUV;
}
bool skinningEnabled = vertTypeIsSkinningEnabled(vertType);
@ -317,14 +314,9 @@ void SoftwareTransform(
switch (gstate.getUVGenMode()) {
case GE_TEXMAP_TEXTURE_COORDS: // UV mapping
case GE_TEXMAP_UNKNOWN: // Seen in Riviera. Unsure of meaning, but this works.
// Texture scale/offset is only performed in this mode.
if (scaleUV) {
uv[0] = ruv[0]*gstate_c.uv.uScale + gstate_c.uv.uOff;
uv[1] = ruv[1]*gstate_c.uv.vScale + gstate_c.uv.vOff;
} else {
uv[0] = ruv[0];
uv[1] = ruv[1];
}
// We always prescale in the vertex decoder now.
uv[0] = ruv[0];
uv[1] = ruv[1];
uv[2] = 1.0f;
break;

View File

@ -864,13 +864,13 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV && (origVertType & GE_VTYPE_TC_MASK) != 0) {
if ((origVertType & GE_VTYPE_TC_MASK) != 0) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0;
gstate_c.uv.vOff = 0;
gstate_c.uv.uOff = 0.0f;
gstate_c.uv.vOff = 0.0f;
}
int generatedBytesRead;
@ -878,7 +878,7 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
DispatchFlush();
if (g_Config.bPrescaleUV && (origVertType & GE_VTYPE_TC_MASK) != 0) {
if ((origVertType & GE_VTYPE_TC_MASK) != 0) {
gstate_c.uv = prevUVScale;
}
}
@ -979,7 +979,7 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if (g_Config.bPrescaleUV && (origVertType & GE_VTYPE_TC_MASK) != 0) {
if (origVertType & GE_VTYPE_TC_MASK) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
@ -993,7 +993,7 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
DispatchFlush();
if (g_Config.bPrescaleUV && (origVertType & GE_VTYPE_TC_MASK) != 0) {
if (origVertType & GE_VTYPE_TC_MASK) {
gstate_c.uv = prevUVScale;
}
}

View File

@ -1173,7 +1173,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options,
biggest = tcalign[tc];
// NOTE: That we check getUVGenMode here means that we must include it in the decoder ID!
if (g_Config.bPrescaleUV && !throughmode && (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN)) {
if (!throughmode && (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN)) {
if (g_DoubleTextureCoordinates)
steps_[numSteps_++] = morphcount == 1 ? tcstep_prescale_remaster[tc] : tcstep_prescale_morph_remaster[tc];
else

View File

@ -89,7 +89,6 @@ DrawEngineDX9::DrawEngineDX9()
vertexCountInDrawCalls(0),
decodeCounter_(0),
dcid_(0),
uvScale(0),
fboTexNeedBind_(false),
fboTexBound_(false) {
@ -108,9 +107,6 @@ DrawEngineDX9::DrawEngineDX9()
transformed = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
transformedExpanded = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
if (g_Config.bPrescaleUV) {
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
}
indexGen.Setup(decIndex);
InitDeviceObjects();
@ -128,8 +124,6 @@ DrawEngineDX9::~DrawEngineDX9() {
decl->second->Release();
}
}
delete [] uvScale;
}
void DrawEngineDX9::InitDeviceObjects() {
@ -305,9 +299,7 @@ void DrawEngineDX9::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, in
dc.indexUpperBound = vertexCount - 1;
}
if (uvScale) {
uvScale[numDrawCalls] = gstate_c.uv;
}
uvScale[numDrawCalls] = gstate_c.uv;
numDrawCalls++;
vertexCountInDrawCalls += vertexCount;
@ -327,18 +319,13 @@ void DrawEngineDX9::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, in
}
void DrawEngineDX9::DecodeVerts() {
if (uvScale) {
const UVScale origUV = gstate_c.uv;
for (; decodeCounter_ < numDrawCalls; decodeCounter_++) {
gstate_c.uv = uvScale[decodeCounter_];
DecodeVertsStep();
}
gstate_c.uv = origUV;
} else {
for (; decodeCounter_ < numDrawCalls; decodeCounter_++) {
DecodeVertsStep();
}
const UVScale origUV = gstate_c.uv;
for (; decodeCounter_ < numDrawCalls; decodeCounter_++) {
gstate_c.uv = uvScale[decodeCounter_];
DecodeVertsStep();
}
gstate_c.uv = origUV;
// Sanity check
if (indexGen.Prim() < 0) {
ERROR_LOG_REPORT(G3D, "DecodeVerts: Failed to deduce prim: %i", indexGen.Prim());
@ -373,26 +360,15 @@ void DrawEngineDX9::DecodeVertsStep() {
// Expand the lower and upper bounds as we go.
int lastMatch = i;
const int total = numDrawCalls;
if (uvScale) {
for (int j = i + 1; j < total; ++j) {
if (drawCalls[j].verts != dc.verts)
break;
if (memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0)
break;
for (int j = i + 1; j < total; ++j) {
if (drawCalls[j].verts != dc.verts)
break;
if (memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0)
break;
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
lastMatch = j;
}
} else {
for (int j = i + 1; j < total; ++j) {
if (drawCalls[j].verts != dc.verts)
break;
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
lastMatch = j;
}
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
lastMatch = j;
}
// 2. Loop through the drawcalls, translating indices as we go.
@ -918,13 +894,6 @@ void DrawEngineDX9::Resized() {
delete iter->second;
}
decoderMap_.clear();
if (g_Config.bPrescaleUV && !uvScale) {
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
} else if (!g_Config.bPrescaleUV && uvScale) {
delete uvScale;
uvScale = 0;
}
}
bool DrawEngineDX9::IsCodePtrVertexDecoder(const u8 *ptr) const {

View File

@ -242,7 +242,7 @@ private:
int decodeCounter_;
u32 dcid_;
UVScale *uvScale;
UVScale uvScale[MAX_DEFERRED_DRAW_CALLS];
bool fboTexNeedBind_;
bool fboTexBound_;

View File

@ -85,10 +85,11 @@ static const CommandTableEntry commandTable[] = {
// Changes that dirty texture scaling.
{ GE_CMD_TEXMAPMODE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &GPU_DX9::Execute_TexMapMode },
{ GE_CMD_TEXSCALEU, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &GPU_DX9::Execute_TexScaleU },
{ GE_CMD_TEXSCALEV, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &GPU_DX9::Execute_TexScaleV },
{ GE_CMD_TEXOFFSETU, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &GPU_DX9::Execute_TexOffsetU },
{ GE_CMD_TEXOFFSETV, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &GPU_DX9::Execute_TexOffsetV },
{ GE_CMD_TEXSCALEU, FLAG_EXECUTEONCHANGE, &GPU_DX9::Execute_TexScaleU },
{ GE_CMD_TEXSCALEV, FLAG_EXECUTEONCHANGE, &GPU_DX9::Execute_TexScaleV },
{ GE_CMD_TEXOFFSETU, FLAG_EXECUTEONCHANGE, &GPU_DX9::Execute_TexOffsetU },
{ GE_CMD_TEXOFFSETV, FLAG_EXECUTEONCHANGE, &GPU_DX9::Execute_TexOffsetV },
// Changes that dirty the current texture. Really should be possible to avoid executing these if we compile
// by adding some more flags.
@ -450,18 +451,6 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx)
}
void GPU_DX9::UpdateCmdInfo() {
if (g_Config.bPrescaleUV) {
cmdInfo_[GE_CMD_TEXSCALEU].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXSCALEV].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETU].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETV].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
} else {
cmdInfo_[GE_CMD_TEXSCALEU].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXSCALEV].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETU].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETV].flags |= FLAG_FLUSHBEFOREONCHANGE;
}
if (g_Config.bSoftwareSkinning) {
cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPU_DX9::Execute_VertexTypeSkinning;

View File

@ -431,52 +431,11 @@ void ShaderManagerDX9::VSUpdateUniforms(int dirtyUniforms) {
const int h = gstate.getTextureHeight(0);
const float widthFactor = (float)w * invW;
const float heightFactor = (float)h * invH;
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) {
// 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.
uvscaleoff[0] = widthFactor;
uvscaleoff[1] = heightFactor;
uvscaleoff[2] = 0.0f;
uvscaleoff[3] = 0.0f;
} else {
uvscaleoff[0] = gstate_c.uv.uScale * widthFactor;
uvscaleoff[1] = gstate_c.uv.vScale * heightFactor;
uvscaleoff[2] = gstate_c.uv.uOff * widthFactor;
uvscaleoff[3] = gstate_c.uv.vOff * heightFactor;
}
break;
// These two work the same whether or not we prescale UV.
case GE_TEXMAP_TEXTURE_MATRIX:
// We cannot bake the UV coord scale factor in here, as we apply a matrix multiplication
// before this is applied, and the matrix multiplication may contain translation. In this case
// the translation will be scaled which breaks faces in Hexyz Force for example.
// So I've gone back to applying the scale factor in the shader.
uvscaleoff[0] = widthFactor;
uvscaleoff[1] = heightFactor;
uvscaleoff[2] = 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());
}
uvscaleoff[0] = widthFactor;
uvscaleoff[1] = heightFactor;
uvscaleoff[2] = 0.0f;
uvscaleoff[3] = 0.0f;
VSSetFloatArray(CONST_VS_UVSCALEOFFSET, uvscaleoff, 4);
}

View File

@ -83,7 +83,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
bool enableLighting = id.Bit(VS_BIT_LIGHTING_ENABLE);
int matUpdate = id.Bits(VS_BIT_MATERIAL_UPDATE, 3);
bool prescale = g_Config.bPrescaleUV && !throughmode && (uvGenMode == GE_TEXMAP_TEXTURE_COORDS || uvGenMode == GE_TEXMAP_UNKNOWN);
bool scaleUV = !throughmode && (uvGenMode == GE_TEXMAP_TEXTURE_COORDS || uvGenMode == GE_TEXMAP_UNKNOWN);
DoLightComputation doLight[4] = { LIGHT_OFF, LIGHT_OFF, LIGHT_OFF, LIGHT_OFF };
if (useHWTransform) {
@ -503,7 +503,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) {
switch (uvGenMode) {
case GE_TEXMAP_TEXTURE_COORDS: // Scale-offset. Easy.
case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works.
if (prescale) {
if (scaleUV) {
if (hasTexcoord) {
WRITE(p, " Out.v_texcoord = In.texcoord * u_uvscaleoffset.xy;\n");
} else {

View File

@ -126,7 +126,6 @@ DrawEngineGLES::DrawEngineGLES()
vertexCountInDrawCalls(0),
decodeCounter_(0),
dcid_(0),
uvScale(nullptr),
fboTexNeedBind_(false),
fboTexBound_(false) {
decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL;
@ -142,9 +141,6 @@ DrawEngineGLES::DrawEngineGLES()
transformed = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
transformedExpanded = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
if (g_Config.bPrescaleUV) {
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
}
indexGen.Setup(decIndex);
InitDeviceObjects();
@ -160,7 +156,6 @@ DrawEngineGLES::~DrawEngineGLES() {
FreeMemoryPages(transformedExpanded, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
unregister_gl_resource_holder(this);
delete [] uvScale;
}
void DrawEngineGLES::RestoreVAO() {
@ -327,9 +322,7 @@ void DrawEngineGLES::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, i
dc.indexUpperBound = vertexCount - 1;
}
if (uvScale) {
uvScale[numDrawCalls] = gstate_c.uv;
}
uvScale[numDrawCalls] = gstate_c.uv;
numDrawCalls++;
vertexCountInDrawCalls += vertexCount;
@ -349,18 +342,12 @@ void DrawEngineGLES::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, i
}
void DrawEngineGLES::DecodeVerts() {
if (uvScale) {
const UVScale origUV = gstate_c.uv;
for (; decodeCounter_ < numDrawCalls; decodeCounter_++) {
gstate_c.uv = uvScale[decodeCounter_];
DecodeVertsStep();
}
gstate_c.uv = origUV;
} else {
for (; decodeCounter_ < numDrawCalls; decodeCounter_++) {
DecodeVertsStep();
}
const UVScale origUV = gstate_c.uv;
for (; decodeCounter_ < numDrawCalls; decodeCounter_++) {
gstate_c.uv = uvScale[decodeCounter_];
DecodeVertsStep();
}
gstate_c.uv = origUV;
// Sanity check
if (indexGen.Prim() < 0) {
ERROR_LOG_REPORT(G3D, "DecodeVerts: Failed to deduce prim: %i", indexGen.Prim());
@ -396,26 +383,15 @@ void DrawEngineGLES::DecodeVertsStep() {
// Expand the lower and upper bounds as we go.
int lastMatch = i;
const int total = numDrawCalls;
if (uvScale) {
for (int j = i + 1; j < total; ++j) {
if (drawCalls[j].verts != dc.verts)
break;
if (memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0)
break;
for (int j = i + 1; j < total; ++j) {
if (drawCalls[j].verts != dc.verts)
break;
if (memcmp(&uvScale[j], &uvScale[i], sizeof(uvScale[0])) != 0)
break;
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
lastMatch = j;
}
} else {
for (int j = i + 1; j < total; ++j) {
if (drawCalls[j].verts != dc.verts)
break;
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
lastMatch = j;
}
indexLowerBound = std::min(indexLowerBound, (int)drawCalls[j].indexLowerBound);
indexUpperBound = std::max(indexUpperBound, (int)drawCalls[j].indexUpperBound);
lastMatch = j;
}
// 2. Loop through the drawcalls, translating indices as we go.
@ -543,9 +519,7 @@ ReliableHashType DrawEngineGLES::ComputeHash() {
i = lastMatch;
}
}
if (uvScale) {
fullhash += DoReliableHash(&uvScale[0], sizeof(uvScale[0]) * numDrawCalls, 0x0123e658);
}
fullhash += DoReliableHash(&uvScale[0], sizeof(uvScale[0]) * numDrawCalls, 0x0123e658);
return fullhash;
}
@ -1031,13 +1005,6 @@ void DrawEngineGLES::Resized() {
delete iter->second;
}
decoderMap_.clear();
if (g_Config.bPrescaleUV && !uvScale) {
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
} else if (!g_Config.bPrescaleUV && uvScale) {
delete uvScale;
uvScale = 0;
}
}
GLuint DrawEngineGLES::BindBuffer(const void *p, size_t sz) {

View File

@ -268,7 +268,7 @@ private:
int decodeCounter_;
u32 dcid_;
UVScale *uvScale;
UVScale uvScale[MAX_DEFERRED_DRAW_CALLS];
bool fboTexNeedBind_;
bool fboTexBound_;

View File

@ -722,18 +722,6 @@ inline void GPU_GLES::UpdateVsyncInterval(bool force) {
}
void GPU_GLES::UpdateCmdInfo() {
if (g_Config.bPrescaleUV) {
cmdInfo_[GE_CMD_TEXSCALEU].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXSCALEV].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETU].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETV].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
} else {
cmdInfo_[GE_CMD_TEXSCALEU].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXSCALEV].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETU].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETV].flags |= FLAG_FLUSHBEFOREONCHANGE;
}
if (g_Config.bSoftwareSkinning) {
cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPU_GLES::Execute_VertexTypeSkinning;

View File

@ -541,50 +541,10 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) {
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) {
// 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.
uvscaleoff[0] = widthFactor;
uvscaleoff[1] = heightFactor;
uvscaleoff[2] = 0.0f;
uvscaleoff[3] = 0.0f;
} else {
uvscaleoff[0] = gstate_c.uv.uScale * factor * widthFactor;
uvscaleoff[1] = gstate_c.uv.vScale * factor * heightFactor;
uvscaleoff[2] = gstate_c.uv.uOff * widthFactor;
uvscaleoff[3] = gstate_c.uv.vOff * heightFactor;
}
break;
// These two work the same whether or not we prescale UV.
case GE_TEXMAP_TEXTURE_MATRIX:
// We cannot bake the UV coord scale factor in here, as we apply a matrix multiplication
// before this is applied, and the matrix multiplication may contain translation. In this case
// the translation will be scaled which breaks faces in Hexyz Force for example.
// So I've gone back to applying the scale factor in the shader.
uvscaleoff[0] = widthFactor;
uvscaleoff[1] = heightFactor;
uvscaleoff[2] = 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());
}
uvscaleoff[0] = widthFactor;
uvscaleoff[1] = heightFactor;
uvscaleoff[2] = 0.0f;
uvscaleoff[3] = 0.0f;
glUniform4fv(u_uvscaleoffset, 1, uvscaleoff);
}

View File

@ -221,7 +221,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
// Add all the uniforms we'll need to transform properly.
}
bool prescale = g_Config.bPrescaleUV && !throughmode && (uvGenMode == GE_TEXMAP_TEXTURE_COORDS || uvGenMode == GE_TEXMAP_UNKNOWN);
bool scaleUV = !throughmode && (uvGenMode == GE_TEXMAP_TEXTURE_COORDS || uvGenMode == GE_TEXMAP_UNKNOWN);
if (useHWTransform) {
// When transforming by hardware, we need a great deal more uniforms...
@ -584,7 +584,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
switch (uvGenMode) {
case GE_TEXMAP_TEXTURE_COORDS: // Scale-offset. Easy.
case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works.
if (prescale) {
if (scaleUV) {
if (hasTexcoord) {
WRITE(p, " v_texcoord = texcoord * u_uvscaleoffset.xy;\n");
} else {

View File

@ -1189,18 +1189,6 @@ void DrawTriangleSlice(
Vec2<int> d01((int)v0.screenpos.x - (int)v1.screenpos.x, (int)v0.screenpos.y - (int)v1.screenpos.y);
Vec2<int> d02((int)v0.screenpos.x - (int)v2.screenpos.x, (int)v0.screenpos.y - (int)v2.screenpos.y);
Vec2<int> d12((int)v1.screenpos.x - (int)v2.screenpos.x, (int)v1.screenpos.y - (int)v2.screenpos.y);
float texScaleU = gstate_c.uv.uScale;
float texScaleV = gstate_c.uv.vScale;
float texOffsetU = gstate_c.uv.uOff;
float texOffsetV = gstate_c.uv.vOff;
if (g_Config.bPrescaleUV) {
// Already applied during vertex decode.
texScaleU = 1.0f;
texScaleV = 1.0f;
texOffsetU = 0.0f;
texOffsetV = 0.0f;
}
int bias0 = IsRightSideOrFlatBottomLine(v0.screenpos.xy(), v1.screenpos.xy(), v2.screenpos.xy()) ? -1 : 0;
int bias1 = IsRightSideOrFlatBottomLine(v1.screenpos.xy(), v2.screenpos.xy(), v0.screenpos.xy()) ? -1 : 0;
@ -1294,8 +1282,6 @@ void DrawTriangleSlice(
// Texture coordinate interpolation must definitely be perspective-correct.
float s = 0, t = 0;
GetTextureCoordinates(v0, v1, v2, w0, w1, w2, s, t);
s = s * texScaleU + texOffsetU;
t = t * texScaleV + texOffsetV;
ApplyTexturing(prim_color, s, t, maxTexLevel, magFilt, texptr, texbufwidthbits);
}
}
@ -1421,27 +1407,7 @@ void DrawPoint(const VertexData &v0)
}
}
if (gstate.isModeThrough()) {
// TODO: Is it really this simple?
ApplyTexturing(prim_color, s, t, maxTexLevel, magFilt, texptr, texbufwidthbits);
} else {
float texScaleU = gstate_c.uv.uScale;
float texScaleV = gstate_c.uv.vScale;
float texOffsetU = gstate_c.uv.uOff;
float texOffsetV = gstate_c.uv.vOff;
if (g_Config.bPrescaleUV) {
// Already applied during vertex decode.
texScaleU = 1.0f;
texScaleV = 1.0f;
texOffsetU = 0.0f;
texOffsetV = 0.0f;
}
s = s * texScaleU + texOffsetU;
t = t * texScaleV + texOffsetV;
ApplyTexturing(prim_color, s, t, maxTexLevel, magFilt, texptr, texbufwidthbits);
}
ApplyTexturing(prim_color, s, t, maxTexLevel, magFilt, texptr, texbufwidthbits);
}
if (!clearMode)
@ -1516,19 +1482,6 @@ void DrawLine(const VertexData &v0, const VertexData &v1)
}
}
float texScaleU = gstate_c.uv.uScale;
float texScaleV = gstate_c.uv.vScale;
float texOffsetU = gstate_c.uv.uOff;
float texOffsetV = gstate_c.uv.vOff;
if (g_Config.bPrescaleUV) {
// Already applied during vertex decode.
texScaleU = 1.0f;
texScaleV = 1.0f;
texOffsetU = 0.0f;
texOffsetV = 0.0f;
}
float x = a.x;
float y = a.y;
float z = a.z;
@ -1553,14 +1506,7 @@ void DrawLine(const VertexData &v0, const VertexData &v1)
float t = tc.t();
if (gstate.isTextureMapEnabled() && !clearMode) {
if (gstate.isModeThrough()) {
// TODO: Is it really this simple?
ApplyTexturing(prim_color, s, t, maxTexLevel, magFilt, texptr, texbufwidthbits);
} else {
s = s * texScaleU + texOffsetU;
t = t * texScaleV + texOffsetV;
ApplyTexturing(prim_color, s, t, maxTexLevel, magFilt, texptr, texbufwidthbits);
}
ApplyTexturing(prim_color, s, t, maxTexLevel, magFilt, texptr, texbufwidthbits);
}
if (!clearMode)

View File

@ -71,7 +71,6 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan)
framebufferManager_(nullptr),
numDrawCalls(0),
vertexCountInDrawCalls(0),
uvScale(nullptr),
fboTexNeedBind_(false),
fboTexBound_(false),
curFrame_(0),
@ -95,10 +94,6 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan)
indexGen.Setup(decIndex);
if (g_Config.bPrescaleUV) {
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
}
InitDeviceObjects();
}
@ -202,7 +197,6 @@ DrawEngineVulkan::~DrawEngineVulkan() {
FreeMemoryPages(transformedExpanded, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
DestroyDeviceObjects();
delete[] uvScale;
}
void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) {
@ -358,9 +352,7 @@ void DrawEngineVulkan::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim,
dc.indexUpperBound = vertexCount - 1;
}
if (uvScale) {
uvScale[numDrawCalls] = gstate_c.uv;
}
uvScale[numDrawCalls] = gstate_c.uv;
numDrawCalls++;
vertexCountInDrawCalls += vertexCount;
@ -480,18 +472,12 @@ void DrawEngineVulkan::DecodeVerts(VulkanPushBuffer *push, uint32_t *bindOffset,
dest = (u8 *)push->Push(vertsToDecode * dec_->GetDecVtxFmt().stride, bindOffset, vkbuf);
}
if (uvScale) {
const UVScale origUV = gstate_c.uv;
for (int i = 0; i < numDrawCalls; i++) {
gstate_c.uv = uvScale[i];
DecodeVertsStep(dest, i, decodedVerts); // Note that this can modify i
}
gstate_c.uv = origUV;
} else {
for (int i = 0; i < numDrawCalls; i++) {
DecodeVertsStep(dest, i, decodedVerts); // Note that this can modify i
}
const UVScale origUV = gstate_c.uv;
for (int i = 0; i < numDrawCalls; i++) {
gstate_c.uv = uvScale[i];
DecodeVertsStep(dest, i, decodedVerts); // Note that this can modify i
}
gstate_c.uv = origUV;
// Sanity check
if (indexGen.Prim() < 0) {

View File

@ -265,7 +265,7 @@ private:
DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS];
int numDrawCalls;
int vertexCountInDrawCalls;
UVScale *uvScale;
UVScale uvScale[MAX_DEFERRED_DRAW_CALLS];
bool fboTexNeedBind_;
bool fboTexBound_;

View File

@ -1148,7 +1148,7 @@ bool FramebufferManagerVulkan::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb
}
void FramebufferManagerVulkan::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) {
_assert_msg_(G3D, nvfb->fbo, "Expecting a valid nvfb in UpdateDownloadTempBuffer");
// _assert_msg_(G3D, nvfb->fbo, "Expecting a valid nvfb in UpdateDownloadTempBuffer");
// Discard the previous contents of this buffer where possible.
/*

View File

@ -86,10 +86,10 @@ static const CommandTableEntry commandTable[] = {
// Changes that dirty texture scaling.
{ GE_CMD_TEXMAPMODE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_UVSCALEOFFSET, &GPU_Vulkan::Execute_TexMapMode },
{ GE_CMD_TEXSCALEU, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_UVSCALEOFFSET, &GPU_Vulkan::Execute_TexScaleU },
{ GE_CMD_TEXSCALEV, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_UVSCALEOFFSET, &GPU_Vulkan::Execute_TexScaleV },
{ GE_CMD_TEXOFFSETU, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_UVSCALEOFFSET, &GPU_Vulkan::Execute_TexOffsetU },
{ GE_CMD_TEXOFFSETV, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, DIRTY_UVSCALEOFFSET, &GPU_Vulkan::Execute_TexOffsetV },
{ GE_CMD_TEXSCALEU, FLAG_EXECUTEONCHANGE, DIRTY_UVSCALEOFFSET, &GPU_Vulkan::Execute_TexScaleU },
{ GE_CMD_TEXSCALEV, FLAG_EXECUTEONCHANGE, DIRTY_UVSCALEOFFSET, &GPU_Vulkan::Execute_TexScaleV },
{ GE_CMD_TEXOFFSETU, FLAG_EXECUTEONCHANGE, DIRTY_UVSCALEOFFSET, &GPU_Vulkan::Execute_TexOffsetU },
{ GE_CMD_TEXOFFSETV, FLAG_EXECUTEONCHANGE, DIRTY_UVSCALEOFFSET, &GPU_Vulkan::Execute_TexOffsetV },
// Changes that dirty the current texture. Really should be possible to avoid executing these if we compile
// by adding some more flags.
@ -442,9 +442,6 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx)
}
}
// No need to flush before the tex scale/offset commands if we are baking
// the tex scale/offset into the vertices anyway.
UpdateCmdInfo();
BuildReportingInfo();
@ -644,20 +641,14 @@ void GPU_Vulkan::UpdateVsyncInterval(bool force) {
}
void GPU_Vulkan::UpdateCmdInfo() {
if (g_Config.bPrescaleUV) {
cmdInfo_[GE_CMD_TEXSCALEU].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXSCALEV].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETU].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETV].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
} else {
cmdInfo_[GE_CMD_TEXSCALEU].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXSCALEV].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETU].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_TEXOFFSETV].flags |= FLAG_FLUSHBEFOREONCHANGE;
}
cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPU_Vulkan::Execute_VertexType;
/*
if (g_Config.bSoftwareSkinning) {
cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPU_Vulkan::Execute_VertexTypeSkinning;
} else {*/
cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE;
cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPU_Vulkan::Execute_VertexType;
// }
}
void GPU_Vulkan::ReapplyGfxStateInternal() {

View File

@ -213,18 +213,12 @@ void ShaderManagerVulkan::BaseUpdateUniforms(int dirtyUniforms) {
const float heightFactor = (float)h * invH;
// First wrap xy, then half texel xy (for clamp.)
const float texclamp[4] = {
widthFactor,
heightFactor,
invW * 0.5f,
invH * 0.5f,
};
const float texclampoff[2] = {
gstate_c.curTextureXOffset * invW,
gstate_c.curTextureYOffset * invH,
};
CopyFloat4(ub_base.texClamp, texclamp);
CopyFloat2(ub_base.texClampOffset, texclampoff);
ub_base.texClamp[0] = widthFactor;
ub_base.texClamp[1] = heightFactor;
ub_base.texClamp[2] = invW * 0.5f;
ub_base.texClamp[3] = invH * 0.5f;
ub_base.texClampOffset[0] = gstate_c.curTextureXOffset * invW;
ub_base.texClampOffset[1] = gstate_c.curTextureYOffset * invH;
}
if (dirtyUniforms & DIRTY_PROJMATRIX) {
@ -305,51 +299,10 @@ void ShaderManagerVulkan::BaseUpdateUniforms(int dirtyUniforms) {
const float factor = rescale[(gstate.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) {
// 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.
uvscaleoff[0] = widthFactor;
uvscaleoff[1] = heightFactor;
uvscaleoff[2] = 0.0f;
uvscaleoff[3] = 0.0f;
} else {
uvscaleoff[0] = gstate_c.uv.uScale * factor * widthFactor;
uvscaleoff[1] = gstate_c.uv.vScale * factor * heightFactor;
uvscaleoff[2] = gstate_c.uv.uOff * widthFactor;
uvscaleoff[3] = gstate_c.uv.vOff * heightFactor;
}
break;
// These two work the same whether or not we prescale UV.
case GE_TEXMAP_TEXTURE_MATRIX:
// We cannot bake the UV coord scale factor in here, as we apply a matrix multiplication
// before this is applied, and the matrix multiplication may contain translation. In this case
// the translation will be scaled which breaks faces in Hexyz Force for example.
// So I've gone back to applying the scale factor in the shader.
uvscaleoff[0] = widthFactor;
uvscaleoff[1] = heightFactor;
uvscaleoff[2] = 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());
}
CopyFloat4(ub_base.uvScaleOffset, uvscaleoff);
ub_base.uvScaleOffset[0] = widthFactor;
ub_base.uvScaleOffset[1] = heightFactor;
ub_base.uvScaleOffset[2] = 0.0f;
ub_base.uvScaleOffset[3] = 0.0f;
}
if (dirtyUniforms & DIRTY_DEPTHRANGE) {
@ -377,8 +330,10 @@ void ShaderManagerVulkan::BaseUpdateUniforms(int dirtyUniforms) {
viewZInvScale = 0.0;
}
float data[4] = { viewZScale, viewZCenter, viewZCenter, viewZInvScale };
CopyFloat4(ub_base.depthRange, data);
ub_base.depthRange[0] = viewZScale;
ub_base.depthRange[1] = viewZCenter;
ub_base.depthRange[2] = viewZCenter;
ub_base.depthRange[3] = viewZInvScale;
}
}

View File

@ -186,8 +186,6 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
WRITE(p, "layout (location = %d) in vec3 color1;\n", PspAttributeLocation::COLOR1);
}
bool prescale = g_Config.bPrescaleUV && !throughmode && (uvGenMode == GE_TEXMAP_TEXTURE_COORDS || uvGenMode == GE_TEXMAP_UNKNOWN);
WRITE(p, "layout (location = 1) %sout vec4 v_color0;\n", shading);
if (lmode) {
WRITE(p, "layout (location = 2) %sout vec3 v_color1;\n", shading);
@ -431,12 +429,14 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
}
}
bool scaleUV = !throughmode && (uvGenMode == GE_TEXMAP_TEXTURE_COORDS || uvGenMode == GE_TEXMAP_UNKNOWN);
// Step 3: UV generation
if (doTexture) {
switch (uvGenMode) {
case GE_TEXMAP_TEXTURE_COORDS: // Scale-offset. Easy.
case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works.
if (prescale) {
if (scaleUV) {
if (hasTexcoord) {
WRITE(p, " v_texcoord = texcoord;\n");
} else {
@ -460,7 +460,7 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
break;
case GE_PROJMAP_UV: // Use unscaled UV as source
{
// prescale is false here.
// scaleUV is false here.
if (hasTexcoord) {
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[texFmtScale];

View File

@ -361,13 +361,6 @@ void GameSettingsScreen::CreateViews() {
CheckBox *depthWrite = graphicsSettings->Add(new CheckBox(&g_Config.bAlwaysDepthWrite, gr->T("Always Depth Write")));
depthWrite->SetDisabledPtr(&g_Config.bSoftwareRendering);
CheckBox *textureHack = graphicsSettings->Add(new CheckBox(&g_Config.bPrescaleUV, gr->T("Texture Coord Speedhack")));
textureHack->OnClick.Add([=](EventParams &e) {
settingInfo_->Show(gr->T("TextureCoordSpeedhack Tip", "Faster some games that benefit from software skinning further by reducing the number of draw calls"), e.v);
return UI::EVENT_CONTINUE;
});
textureHack->SetDisabledPtr(&g_Config.bSoftwareRendering);
static const char *bloomHackOptions[] = { "Off", "Safe", "Balanced", "Aggressive" };
PopupMultiChoice *bloomHack = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iBloomHack, gr->T("Lower resolution for effects (reduces artifacts)"), bloomHackOptions, 0, ARRAY_SIZE(bloomHackOptions), gr->GetName(), screenManager()));
bloomHackEnable_ = !g_Config.bSoftwareRendering && (g_Config.iInternalResolution != 1);