Merge pull request #9176 from hrydgard/always-prescale-uv

Always prescale uv ("texcoord speedhack")
This commit is contained in:
Henrik Rydgård 2016-12-20 16:03:51 +01:00 committed by GitHub
commit e9bea75a07
32 changed files with 117 additions and 580 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

@ -27,7 +27,7 @@
#define QUAD_INDICES_MAX 65536
DrawEngineCommon::DrawEngineCommon() : dec_(nullptr) {
DrawEngineCommon::DrawEngineCommon() : dec_(nullptr), decOptions_{} {
quadIndices_ = new u16[6 * QUAD_INDICES_MAX];
decJitCache_ = new VertexDecoderJitCache();
}

View file

@ -42,7 +42,6 @@ std::string VertexShaderDesc(const ShaderID &id) {
}
if (id.Bits(VS_BIT_MATERIAL_UPDATE, 3)) desc << "MatUp:" << id.Bits(VS_BIT_MATERIAL_UPDATE, 3) << " ";
if (id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2)) desc << "WScale " << id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2) << " ";
if (id.Bits(VS_BIT_TEXCOORD_FMTSCALE, 2)) desc << "TCScale " << id.Bits(VS_BIT_TEXCOORD_FMTSCALE, 2) << " ";
if (id.Bit(VS_BIT_FLATSHADE)) desc << "Flat ";
// TODO: More...
@ -119,11 +118,6 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform)
id.SetBit(VS_BIT_NORM_REVERSE, gstate.areNormalsReversed());
id.SetBit(VS_BIT_HAS_TEXCOORD, hasTexcoord);
if (doTextureProjection && gstate.getUVProjMode() == GE_PROJMAP_UV) {
id.SetBits(VS_BIT_TEXCOORD_FMTSCALE, 2, (vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT); // two bits
} else {
id.SetBits(VS_BIT_TEXCOORD_FMTSCALE, 2, 3); // float - no scaling
}
}
id.SetBit(VS_BIT_FLATSHADE, doFlatShading);

View file

@ -37,7 +37,6 @@ enum {
VS_BIT_LIGHT3_ENABLE = 55,
VS_BIT_LIGHTING_ENABLE = 56,
VS_BIT_WEIGHT_FMTSCALE = 57, // only two bits, 1 free after
VS_BIT_TEXCOORD_FMTSCALE = 60,
VS_BIT_FLATSHADE = 62, // 1 free after
};

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

@ -119,8 +119,6 @@ static const JitLookup jitLookup[] = {
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
{&VertexDecoder::Step_TcU8, &VertexDecoderJitCache::Jit_TcU8},
{&VertexDecoder::Step_TcU16, &VertexDecoderJitCache::Jit_TcU16},
{&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat},
{&VertexDecoder::Step_TcU16Double, &VertexDecoderJitCache::Jit_TcU16Double},
@ -563,21 +561,6 @@ void VertexDecoderJitCache::Jit_WeightsFloatSkin() {
Jit_ApplyWeights();
}
// Fill last two bytes with zeroes to align to 4 bytes. LDRH does it for us, handy.
void VertexDecoderJitCache::Jit_TcU8() {
LDRB(tempReg1, srcReg, dec_->tcoff);
LDRB(tempReg2, srcReg, dec_->tcoff + 1);
ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 8));
STR(tempReg1, dstReg, dec_->decFmt.uvoff);
}
void VertexDecoderJitCache::Jit_TcU16() {
LDRH(tempReg1, srcReg, dec_->tcoff);
LDRH(tempReg2, srcReg, dec_->tcoff + 2);
ORR(tempReg1, tempReg1, Operand2(tempReg2, ST_LSL, 16));
STR(tempReg1, dstReg, dec_->decFmt.uvoff);
}
void VertexDecoderJitCache::Jit_TcFloat() {
LDR(tempReg1, srcReg, dec_->tcoff);
LDR(tempReg2, srcReg, dec_->tcoff + 4);

View file

@ -92,8 +92,6 @@ static const JitLookup jitLookup[] = {
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
{&VertexDecoder::Step_TcU8, &VertexDecoderJitCache::Jit_TcU8},
{&VertexDecoder::Step_TcU16, &VertexDecoderJitCache::Jit_TcU16},
{&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat},
{&VertexDecoder::Step_TcU16Double, &VertexDecoderJitCache::Jit_TcU16Double},
{&VertexDecoder::Step_TcU8Prescale, &VertexDecoderJitCache::Jit_TcU8Prescale},
@ -578,16 +576,6 @@ void VertexDecoderJitCache::Jit_Color5551() {
CSEL(fullAlphaReg, fullAlphaReg, WZR, CC_EQ);
}
void VertexDecoderJitCache::Jit_TcU8() {
LDURH(tempReg1, srcReg, dec_->tcoff);
STR(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.uvoff);
}
void VertexDecoderJitCache::Jit_TcU16() {
LDUR(tempReg1, srcReg, dec_->tcoff);
STR(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.uvoff);
}
void VertexDecoderJitCache::Jit_TcU16Through() {
LDRH(INDEX_UNSIGNED, tempReg1, srcReg, dec_->tcoff);
LDRH(INDEX_UNSIGNED, tempReg2, srcReg, dec_->tcoff + 2);

View file

@ -264,14 +264,6 @@ void VertexDecoder::Step_WeightsFloatSkin() const
}
}
void VertexDecoder::Step_TcU8() const
{
// u32 to write two bytes of zeroes for free.
u32 *uv = (u32*)(decoded_ + decFmt.uvoff);
const u16 *uvdata = (const u16*)(ptr_ + tcoff);
*uv = *uvdata;
}
void VertexDecoder::Step_TcU8ToFloat() const
{
// u32 to write two bytes of zeroes for free.
@ -281,14 +273,6 @@ void VertexDecoder::Step_TcU8ToFloat() const
uv[1] = uvdata[1] * (1.0f / 128.0f);
}
void VertexDecoder::Step_TcU16() const
{
u32 *uv = (u32 *)(decoded_ + decFmt.uvoff);
// TODO: Fix big-endian without losing the optimization
const u32 *uvdata = (const u32*)(ptr_ + tcoff);
*uv = *uvdata;
}
void VertexDecoder::Step_TcU16ToFloat() const
{
float *uv = (float *)(decoded_ + decFmt.uvoff);
@ -903,13 +887,6 @@ static const StepFunction wtstep_skin[4] = {
&VertexDecoder::Step_WeightsFloatSkin,
};
static const StepFunction tcstep[4] = {
0,
&VertexDecoder::Step_TcU8,
&VertexDecoder::Step_TcU16,
&VertexDecoder::Step_TcFloat,
};
static const StepFunction tcstepToFloat[4] = {
0,
&VertexDecoder::Step_TcU8ToFloat,
@ -973,13 +950,6 @@ static const StepFunction tcstep_morph_remasterToFloat[4] = {
&VertexDecoder::Step_TcFloatMorph,
};
static const StepFunction tcstep_through[4] = {
0,
&VertexDecoder::Step_TcU8,
&VertexDecoder::Step_TcU16Through,
&VertexDecoder::Step_TcFloatThrough,
};
static const StepFunction tcstep_throughToFloat[4] = {
0,
&VertexDecoder::Step_TcU8ToFloat,
@ -987,14 +957,6 @@ static const StepFunction tcstep_throughToFloat[4] = {
&VertexDecoder::Step_TcFloatThrough,
};
// Some HD Remaster games double the u16 texture coordinates.
static const StepFunction tcstep_remaster[4] = {
0,
&VertexDecoder::Step_TcU8,
&VertexDecoder::Step_TcU16Double,
&VertexDecoder::Step_TcFloat,
};
static const StepFunction tcstep_remasterToFloat[4] = {
0,
&VertexDecoder::Step_TcU8ToFloat,
@ -1002,13 +964,6 @@ static const StepFunction tcstep_remasterToFloat[4] = {
&VertexDecoder::Step_TcFloat,
};
static const StepFunction tcstep_through_remaster[4] = {
0,
&VertexDecoder::Step_TcU8,
&VertexDecoder::Step_TcU16ThroughDouble,
&VertexDecoder::Step_TcFloatThrough,
};
static const StepFunction tcstep_through_remasterToFloat[4] = {
0,
&VertexDecoder::Step_TcU8ToFloat,
@ -1173,41 +1128,21 @@ 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
steps_[numSteps_++] = morphcount == 1 ? tcstep_prescale[tc] : tcstep_prescale_morph[tc];
decFmt.uvfmt = DEC_FLOAT_2;
} else {
if (options.expandAllUVtoFloat) {
if (morphcount != 1 && !throughmode)
steps_[numSteps_++] = g_DoubleTextureCoordinates ? tcstep_morph_remasterToFloat[tc] : tcstep_morphToFloat[tc];
else if (g_DoubleTextureCoordinates)
steps_[numSteps_++] = throughmode ? tcstep_through_remasterToFloat[tc] : tcstep_remasterToFloat[tc];
else
steps_[numSteps_++] = throughmode ? tcstep_throughToFloat[tc] : tcstepToFloat[tc];
decFmt.uvfmt = DEC_FLOAT_2;
} else {
if (morphcount != 1 && !throughmode)
steps_[numSteps_++] = g_DoubleTextureCoordinates ? tcstep_morph_remaster[tc] : tcstep_morph[tc];
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;
}
}
// We now always expand UV to float.
if (morphcount != 1 && !throughmode)
steps_[numSteps_++] = g_DoubleTextureCoordinates ? tcstep_morph_remasterToFloat[tc] : tcstep_morphToFloat[tc];
else if (g_DoubleTextureCoordinates)
steps_[numSteps_++] = throughmode ? tcstep_through_remasterToFloat[tc] : tcstep_remasterToFloat[tc];
else
steps_[numSteps_++] = throughmode ? tcstep_throughToFloat[tc] : tcstepToFloat[tc];
decFmt.uvfmt = DEC_FLOAT_2;
}
decFmt.uvoff = decOff;

View file

@ -443,7 +443,6 @@ int TranslateNumBones(int bones);
typedef void(*JittedVertexDecoder)(const u8 *src, u8 *dst, int count);
struct VertexDecoderOptions {
bool expandAllUVtoFloat;
bool expandAllWeightsToFloat;
bool expand8BitNormalsToFloat;
};
@ -477,8 +476,6 @@ public:
void Step_WeightsU16Skin() const;
void Step_WeightsFloatSkin() const;
void Step_TcU8() const;
void Step_TcU16() const;
void Step_TcU8ToFloat() const;
void Step_TcU16ToFloat() const;
void Step_TcFloat() const;
@ -633,9 +630,7 @@ public:
void Jit_WeightsU16Skin();
void Jit_WeightsFloatSkin();
void Jit_TcU8();
void Jit_TcU8ToFloat();
void Jit_TcU16();
void Jit_TcU16ToFloat();
void Jit_TcFloat();

View file

@ -97,8 +97,6 @@ static const JitLookup jitLookup[] = {
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
{&VertexDecoder::Step_TcU8, &VertexDecoderJitCache::Jit_TcU8},
{&VertexDecoder::Step_TcU16, &VertexDecoderJitCache::Jit_TcU16},
{&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat},
{&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat},
{&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat},
@ -687,17 +685,6 @@ void VertexDecoderJitCache::Jit_WeightsFloatSkin() {
}
}
// Fill last two bytes with zeroes to align to 4 bytes. MOVZX does it for us, handy.
void VertexDecoderJitCache::Jit_TcU8() {
MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->tcoff));
MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1));
}
void VertexDecoderJitCache::Jit_TcU16() {
MOV(32, R(tempReg1), MDisp(srcReg, dec_->tcoff));
MOV(32, MDisp(dstReg, dec_->decFmt.uvoff), R(tempReg1));
}
void VertexDecoderJitCache::Jit_TcU8ToFloat() {
Jit_AnyU8ToFloat(dec_->tcoff, 16);
MOVQ_xmm(MDisp(dstReg, dec_->decFmt.uvoff), XMM3);

View file

@ -89,12 +89,8 @@ DrawEngineDX9::DrawEngineDX9()
vertexCountInDrawCalls(0),
decodeCounter_(0),
dcid_(0),
uvScale(0),
fboTexNeedBind_(false),
fboTexBound_(false) {
memset(&decOptions_, 0, sizeof(decOptions_));
decOptions_.expandAllUVtoFloat = true;
decOptions_.expandAllWeightsToFloat = true;
decOptions_.expand8BitNormalsToFloat = true;
@ -108,9 +104,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 +121,6 @@ DrawEngineDX9::~DrawEngineDX9() {
decl->second->Release();
}
}
delete [] uvScale;
}
void DrawEngineDX9::InitDeviceObjects() {
@ -305,9 +296,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 +316,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 +357,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 +891,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,13 +126,10 @@ DrawEngineGLES::DrawEngineGLES()
vertexCountInDrawCalls(0),
decodeCounter_(0),
dcid_(0),
uvScale(nullptr),
fboTexNeedBind_(false),
fboTexBound_(false) {
decimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL;
bufferDecimationCounter_ = VERTEXCACHE_NAME_DECIMATION_INTERVAL;
memset(&decOptions_, 0, sizeof(decOptions_));
decOptions_.expandAllUVtoFloat = false;
// Allocate nicely aligned memory. Maybe graphics drivers will
// appreciate it.
// All this is a LOT of memory, need to see if we can cut down somehow.
@ -142,9 +139,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 +154,6 @@ DrawEngineGLES::~DrawEngineGLES() {
FreeMemoryPages(transformedExpanded, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
unregister_gl_resource_holder(this);
delete [] uvScale;
}
void DrawEngineGLES::RestoreVAO() {
@ -327,9 +320,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 +340,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 +381,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 +517,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 +1003,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

@ -536,55 +536,11 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) {
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) {
// 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

@ -192,7 +192,6 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
numBoneWeights = 1 + id.Bits(VS_BIT_BONES, 3);
WRITE(p, "%s", boneWeightDecl[numBoneWeights]);
}
int texFmtScale = id.Bits(VS_BIT_TEXCOORD_FMTSCALE, 2);
if (useHWTransform)
WRITE(p, "%s vec3 position;\n", attribute);
@ -221,7 +220,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 +583,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 {
@ -610,9 +609,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
{
// prescale 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];
temp_tc = StringFromFormat("vec4(texcoord.xy %s, 0.0, 1.0)", factor);
temp_tc = "vec4(texcoord.xy, 0.0, 1.0)";
} else {
temp_tc = "vec4(0.0, 0.0, 0.0, 1.0)";
}

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

@ -217,9 +217,7 @@ int TransformUnit::patchBufferSize_ = 0;
void TransformUnit::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type) {
VertexDecoder vdecoder;
VertexDecoderOptions options;
memset(&options, 0, sizeof(options));
options.expandAllUVtoFloat = false;
VertexDecoderOptions options{};
vdecoder.SetVertexType(vertex_type, options);
const DecVtxFormat& vtxfmt = vdecoder.GetDecVtxFmt();
@ -310,9 +308,7 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type
{
// TODO: Cache VertexDecoder objects
VertexDecoder vdecoder;
VertexDecoderOptions options;
memset(&options, 0, sizeof(options));
options.expandAllUVtoFloat = false;
VertexDecoderOptions options{};
vdecoder.SetVertexType(vertex_type, options);
const DecVtxFormat& vtxfmt = vdecoder.GetDecVtxFmt();
@ -569,9 +565,7 @@ bool TransformUnit::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVert
simpleVertices.resize(indexUpperBound + 1);
VertexDecoder vdecoder;
VertexDecoderOptions options;
memset(&options, 0, sizeof(options));
options.expandAllUVtoFloat = false; // TODO: True should be fine here
VertexDecoderOptions options{};
vdecoder.SetVertexType(gstate.vertType, options);
DrawEngineCommon::NormalizeVertices((u8 *)(&simpleVertices[0]), (u8 *)(&temp_buffer[0]), Memory::GetPointer(gstate_c.vertexAddr), &vdecoder, indexLowerBound, indexUpperBound, gstate.vertType);

View file

@ -71,16 +71,12 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan)
framebufferManager_(nullptr),
numDrawCalls(0),
vertexCountInDrawCalls(0),
uvScale(nullptr),
fboTexNeedBind_(false),
fboTexBound_(false),
curFrame_(0),
nullTexture_(nullptr) {
nullTexture_(nullptr),
stats_{} {
memset(&stats_, 0, sizeof(stats_));
memset(&decOptions_, 0, sizeof(decOptions_));
decOptions_.expandAllUVtoFloat = false; // this may be a good idea though.
decOptions_.expandAllWeightsToFloat = false;
decOptions_.expand8BitNormalsToFloat = false;
@ -95,10 +91,6 @@ DrawEngineVulkan::DrawEngineVulkan(VulkanContext *vulkan)
indexGen.Setup(decIndex);
if (g_Config.bPrescaleUV) {
uvScale = new UVScale[MAX_DEFERRED_DRAW_CALLS];
}
InitDeviceObjects();
}
@ -202,7 +194,6 @@ DrawEngineVulkan::~DrawEngineVulkan() {
FreeMemoryPages(transformedExpanded, 3 * TRANSFORMED_VERTEX_BUFFER_SIZE);
DestroyDeviceObjects();
delete[] uvScale;
}
void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) {
@ -358,9 +349,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 +469,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) {
@ -300,56 +294,10 @@ void ShaderManagerVulkan::BaseUpdateUniforms(int dirtyUniforms) {
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[(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 +325,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

@ -163,7 +163,6 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses
numBoneWeights = 1 + id.Bits(VS_BIT_BONES, 3);
WRITE(p, "%s", boneWeightDecl[numBoneWeights]);
}
int texFmtScale = id.Bits(VS_BIT_TEXCOORD_FMTSCALE, 2);
if (useHWTransform)
WRITE(p, "layout (location = %d) in vec3 position;\n", PspAttributeLocation::POSITION);
@ -186,8 +185,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 +428,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,11 +459,9 @@ 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];
temp_tc = StringFromFormat("vec4(texcoord.xy %s, 0.0, 1.0)", factor);
temp_tc = "vec4(texcoord.xy, 0.0, 1.0)";
} else {
temp_tc = "vec4(0.0, 0.0, 0.0, 1.0)";
}

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);

View file

@ -288,9 +288,7 @@ int CtrlVertexList::GetRowCount() {
if (!gpuDebug->GetCurrentSimpleVertices(rowCount_, vertices, indices)) {
rowCount_ = 0;
}
VertexDecoderOptions options;
memset(&options, 0, sizeof(options));
options.expandAllUVtoFloat = false;
VertexDecoderOptions options{};
decoder->SetVertexType(state.vertType, options);
return rowCount_;
}