diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index 2da86fb45b..8101e63f00 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -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 wq2 = w2.Cast() * q2; Vec4 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 tc = (v0.texturecoords * (float)(steps - i) + v1.texturecoords * (float)i) / steps1; - Vec2 tc1 = (v0.texturecoords * (float)(steps - i - 1) + v1.texturecoords * (float)(i + 1)) / steps1; + Vec2 tc = (v0.texturecoords.uv() * (float)(steps - i) + v1.texturecoords.uv() * (float)i) / steps1; + Vec2 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)); diff --git a/GPU/Software/RasterizerRectangle.cpp b/GPU/Software/RasterizerRectangle.cpp index 3703678169..5cc40566d6 100644 --- a/GPU/Software/RasterizerRectangle.cpp +++ b/GPU/Software/RasterizerRectangle.cpp @@ -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; diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 10a31c8bfb..9fd3540cf9 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -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 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); } diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index 9983bae101..b3d2e9b06d 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -79,12 +79,12 @@ struct DrawingCoords { }; struct alignas(16) VertexData { - Vec2 texturecoords; + Vec3Packedf texturecoords; + float clipw; uint32_t color0; uint32_t color1; ScreenCoords screenpos; float fogdepth; - float clipw; }; struct ClipVertexData {