From 8369ee58035ca98f776428f6cccbcf987fee3bc9 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Tue, 23 Dec 2014 13:05:51 -0200 Subject: Rasterizer: Pre-divide vertex attributes by W Execute the division-by-W for perspective-correct interpolation of values in the clipper, moving them out of the rasterization inner loop. --- src/video_core/clipper.cpp | 13 ++++++++++--- src/video_core/pica.h | 20 ++++++++++++++++++++ src/video_core/rasterizer.cpp | 7 ++----- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp index 0521ef86..1744066b 100644 --- a/src/video_core/clipper.cpp +++ b/src/video_core/clipper.cpp @@ -91,10 +91,17 @@ static void InitScreenCoordinates(OutputVertex& vtx) viewport.zscale = float24::FromRawFloat24(registers.viewport_depth_range); viewport.offset_z = float24::FromRawFloat24(registers.viewport_depth_far_plane); + float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w; + vtx.color *= inv_w; + vtx.tc0 *= inv_w; + vtx.tc1 *= inv_w; + vtx.tc2 *= inv_w; + vtx.pos.w = inv_w; + // TODO: Not sure why the viewport width needs to be divided by 2 but the viewport height does not - vtx.screenpos[0] = (vtx.pos.x / vtx.pos.w + float24::FromFloat32(1.0)) * viewport.halfsize_x + viewport.offset_x; - vtx.screenpos[1] = (vtx.pos.y / vtx.pos.w + float24::FromFloat32(1.0)) * viewport.halfsize_y + viewport.offset_y; - vtx.screenpos[2] = viewport.offset_z - vtx.pos.z / vtx.pos.w * viewport.zscale; + vtx.screenpos[0] = (vtx.pos.x * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_x + viewport.offset_x; + vtx.screenpos[1] = (vtx.pos.y * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_y + viewport.offset_y; + vtx.screenpos[2] = viewport.offset_z - vtx.pos.z * inv_w * viewport.zscale; } void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) { diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 89d97e4e..38bac748 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -757,6 +757,26 @@ struct float24 { return float24::FromFloat32(ToFloat32() - flt.ToFloat32()); } + float24& operator *= (const float24& flt) { + value *= flt.ToFloat32(); + return *this; + } + + float24& operator /= (const float24& flt) { + value /= flt.ToFloat32(); + return *this; + } + + float24& operator += (const float24& flt) { + value += flt.ToFloat32(); + return *this; + } + + float24& operator -= (const float24& flt) { + value -= flt.ToFloat32(); + return *this; + } + float24 operator - () const { return float24::FromFloat32(-ToFloat32()); } diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp index 63da7104..a8014887 100644 --- a/src/video_core/rasterizer.cpp +++ b/src/video_core/rasterizer.cpp @@ -106,10 +106,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, int bias1 = IsRightSideOrFlatBottomEdge(vtxpos[1].xy(), vtxpos[2].xy(), vtxpos[0].xy()) ? -1 : 0; int bias2 = IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0; - const Math::Vec3 w_inverse = Math::MakeVec( - float24::FromFloat32(1.0f) / v0.pos.w, - float24::FromFloat32(1.0f) / v1.pos.w, - float24::FromFloat32(1.0f) / v2.pos.w); + auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w); auto textures = registers.GetTextures(); auto tev_stages = registers.GetTevStages(); @@ -158,7 +155,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0, // // The generalization to three vertices is straightforward in baricentric coordinates. auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) { - auto attr_over_w = Math::MakeVec(attr0, attr1, attr2) * w_inverse; + auto attr_over_w = Math::MakeVec(attr0, attr1, attr2); float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates); return interpolated_attr_over_w * interpolated_w_inverse; }; -- cgit v1.2.3