softgpu: Expand texture coords to include q.

We'll need this to correctly project.
This commit is contained in:
Unknown W. Brackets 2022-09-26 17:13:14 -07:00
parent 8376176b2f
commit 6282f8b05f
4 changed files with 19 additions and 10 deletions

View File

@ -233,6 +233,7 @@ static inline void GetTextureCoordinates(const VertexData& v0, const VertexData&
float wq1 = (1.0f - p) * q1;
float q_recip = 1.0f / (wq0 + wq1);
// TODO: Handle projection.
s = (v0.texturecoords.s() * wq0 + v1.texturecoords.s() * wq1) * q_recip;
t = (v0.texturecoords.t() * wq0 + v1.texturecoords.t() * wq1) * q_recip;
}
@ -249,6 +250,7 @@ static inline void GetTextureCoordinates(const VertexData &v0, const VertexData
Vec4<float> wq2 = w2.Cast<float>() * q2;
Vec4<float> q_recip = (wq0 + wq1 + wq2).Reciprocal();
// TODO: Handle projection.
s = Interpolate(v0.texturecoords.s(), v1.texturecoords.s(), v2.texturecoords.s(), wq0, wq1, wq2, q_recip);
t = Interpolate(v0.texturecoords.t(), v1.texturecoords.t(), v2.texturecoords.t(), wq0, wq1, wq2, q_recip);
}
@ -770,8 +772,9 @@ void DrawRectangle(const VertexData &v0, const VertexData &v1, const BinCoords &
Vec2f stx(0.0f, 0.0f);
Vec2f sty(0.0f, 0.0f);
if (state.enableTextures) {
Vec2f tc0 = v0.texturecoords;
Vec2f tc1 = v1.texturecoords;
// TODO: Handle projection.
Vec2f tc0 = v0.texturecoords.uv();
Vec2f tc1 = v1.texturecoords.uv();
if (state.throughMode) {
// For levels > 0, mipmapping is always based on level 0. Simpler to scale first.
tc0.s() *= 1.0f / (float)(1 << state.samplerID.width0Shift);
@ -1268,8 +1271,8 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const BinCoords &range
float s, s1;
float t, t1;
if (state.throughMode) {
Vec2<float> tc = (v0.texturecoords * (float)(steps - i) + v1.texturecoords * (float)i) / steps1;
Vec2<float> tc1 = (v0.texturecoords * (float)(steps - i - 1) + v1.texturecoords * (float)(i + 1)) / steps1;
Vec2<float> tc = (v0.texturecoords.uv() * (float)(steps - i) + v1.texturecoords.uv() * (float)i) / steps1;
Vec2<float> tc1 = (v0.texturecoords.uv() * (float)(steps - i - 1) + v1.texturecoords.uv() * (float)(i + 1)) / steps1;
s = tc.s() * (1.0f / (float)(1 << state.samplerID.width0Shift));
s1 = tc1.s() * (1.0f / (float)(1 << state.samplerID.width0Shift));

View File

@ -356,7 +356,7 @@ bool RectangleFastPath(const VertexData &v0, const VertexData &v1, BinManager &b
// Currently only works for TL/BR, which is the most common but not required.
bool orient_check = xdiff >= 0 && ydiff >= 0;
// We already have a fast path for clear in ClearRectangle.
bool state_check = state.throughMode && !state.pixelID.clearMode && !state.samplerID.hasAnyMips && NoClampOrWrap(state, v0.texturecoords) && NoClampOrWrap(state, v1.texturecoords);
bool state_check = state.throughMode && !state.pixelID.clearMode && !state.samplerID.hasAnyMips && NoClampOrWrap(state, v0.texturecoords.uv()) && NoClampOrWrap(state, v1.texturecoords.uv());
// This doesn't work well with offset drawing, see #15876. Through never has a subpixel offset.
bool subpixel_check = ((v0.screenpos.x | v0.screenpos.y | v1.screenpos.x | v1.screenpos.y) & 0xF) == 0;
if ((coord_check || !state.enableTextures) && orient_check && state_check && subpixel_check) {
@ -414,6 +414,9 @@ static bool AreCoordsRectangleCompatible(const RasterizerState &state, const Cli
if (data1.clippos.w - halftexel > data0.clippos.w || data1.clippos.w + halftexel < data0.clippos.w)
return false;
}
// If we're projecting textures, only allow an exact match for simplicity.
if (state.enableTextures && data1.v.texturecoords.q() != data0.v.texturecoords.q())
return false;
if (state.pixelID.applyFog && data1.v.fogdepth != data0.v.fogdepth) {
// Similar to w, this only matters if they're farther apart than 1/255.
static constexpr float foghalfstep = 0.5f / 255.0f;

View File

@ -106,12 +106,14 @@ void SoftwareDrawEngine::DispatchSubmitImm(GEPrimitiveType prim, TransformedVert
vert.clippos = ClipCoords(buffer[i].pos);
vert.v.texturecoords.x = buffer[i].u;
vert.v.texturecoords.y = buffer[i].v;
vert.v.texturecoords.z = buffer[i].uv_w;
if (gstate.isModeThrough()) {
vert.v.texturecoords.x *= gstate.getTextureWidth(0);
vert.v.texturecoords.y *= gstate.getTextureHeight(0);
} else {
vert.clippos.z *= 1.0f / 65535.0f;
}
vert.v.clipw = buffer[i].pos_w;
vert.v.color0 = buffer[i].color0_32;
vert.v.color1 = gstate.isUsingSecondaryColor() && !gstate.isModeThrough() ? buffer[i].color1_32 : 0;
vert.v.fogdepth = buffer[i].fog;
@ -324,9 +326,10 @@ ClipVertexData TransformUnit::ReadVertex(VertexReader &vreader, const TransformS
// VertexDecoder normally scales z, but we want it unscaled.
vreader.ReadPosThroughZ16(pos.AsArray());
static Vec2f lastTC;
static Vec3Packedf lastTC;
if (state.readUV) {
vreader.ReadUV(vertex.v.texturecoords.AsArray());
vertex.v.texturecoords.q() = 0.0f;
lastTC = vertex.v.texturecoords;
} else {
vertex.v.texturecoords = lastTC;
@ -427,7 +430,7 @@ ClipVertexData TransformUnit::ReadVertex(VertexReader &vreader, const TransformS
break;
case GE_PROJMAP_UV:
source = Vec3f(vertex.v.texturecoords, 0.0f);
source = Vec3f(vertex.v.texturecoords.uv(), 0.0f);
break;
case GE_PROJMAP_NORMALIZED_NORMAL:
@ -448,7 +451,7 @@ ClipVertexData TransformUnit::ReadVertex(VertexReader &vreader, const TransformS
// Note that UV scale/offset are not used in this mode.
Vec3<float> stq = Vec3ByMatrix43(source, gstate.tgenMatrix);
float z_recip = 1.0f / stq.z;
vertex.v.texturecoords = Vec2f(stq.x * z_recip, stq.y * z_recip);
vertex.v.texturecoords = Vec3Packedf(stq.x * z_recip, stq.y * z_recip, 1.0f);
} else if (state.uvGenMode == GE_TEXMAP_ENVIRONMENT_MAP) {
Lighting::GenerateLightST(vertex.v, worldnormal);
}

View File

@ -79,12 +79,12 @@ struct DrawingCoords {
};
struct alignas(16) VertexData {
Vec2<float> texturecoords;
Vec3Packedf texturecoords;
float clipw;
uint32_t color0;
uint32_t color1;
ScreenCoords screenpos;
float fogdepth;
float clipw;
};
struct ClipVertexData {