summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2014-12-23 13:05:51 -0200
committerGravatar Yuri Kunde Schlesner2014-12-29 02:08:11 -0200
commit8369ee58035ca98f776428f6cccbcf987fee3bc9 (patch)
tree3c1800823ffe55529ba6dbcba0c4407d2da625f2
parentGPU: Bitwise texture swizzling (diff)
downloadyuzu-8369ee58035ca98f776428f6cccbcf987fee3bc9.tar.gz
yuzu-8369ee58035ca98f776428f6cccbcf987fee3bc9.tar.xz
yuzu-8369ee58035ca98f776428f6cccbcf987fee3bc9.zip
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.
-rw-r--r--src/video_core/clipper.cpp13
-rw-r--r--src/video_core/pica.h20
-rw-r--r--src/video_core/rasterizer.cpp7
3 files changed, 32 insertions, 8 deletions
diff --git a/src/video_core/clipper.cpp b/src/video_core/clipper.cpp
index 0521ef866..1744066ba 100644
--- a/src/video_core/clipper.cpp
+++ b/src/video_core/clipper.cpp
@@ -91,10 +91,17 @@ static void InitScreenCoordinates(OutputVertex& vtx)
91 viewport.zscale = float24::FromRawFloat24(registers.viewport_depth_range); 91 viewport.zscale = float24::FromRawFloat24(registers.viewport_depth_range);
92 viewport.offset_z = float24::FromRawFloat24(registers.viewport_depth_far_plane); 92 viewport.offset_z = float24::FromRawFloat24(registers.viewport_depth_far_plane);
93 93
94 float24 inv_w = float24::FromFloat32(1.f) / vtx.pos.w;
95 vtx.color *= inv_w;
96 vtx.tc0 *= inv_w;
97 vtx.tc1 *= inv_w;
98 vtx.tc2 *= inv_w;
99 vtx.pos.w = inv_w;
100
94 // TODO: Not sure why the viewport width needs to be divided by 2 but the viewport height does not 101 // TODO: Not sure why the viewport width needs to be divided by 2 but the viewport height does not
95 vtx.screenpos[0] = (vtx.pos.x / vtx.pos.w + float24::FromFloat32(1.0)) * viewport.halfsize_x + viewport.offset_x; 102 vtx.screenpos[0] = (vtx.pos.x * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_x + viewport.offset_x;
96 vtx.screenpos[1] = (vtx.pos.y / vtx.pos.w + float24::FromFloat32(1.0)) * viewport.halfsize_y + viewport.offset_y; 103 vtx.screenpos[1] = (vtx.pos.y * inv_w + float24::FromFloat32(1.0)) * viewport.halfsize_y + viewport.offset_y;
97 vtx.screenpos[2] = viewport.offset_z - vtx.pos.z / vtx.pos.w * viewport.zscale; 104 vtx.screenpos[2] = viewport.offset_z - vtx.pos.z * inv_w * viewport.zscale;
98} 105}
99 106
100void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) { 107void ProcessTriangle(OutputVertex &v0, OutputVertex &v1, OutputVertex &v2) {
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index 89d97e4e9..38bac748c 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -757,6 +757,26 @@ struct float24 {
757 return float24::FromFloat32(ToFloat32() - flt.ToFloat32()); 757 return float24::FromFloat32(ToFloat32() - flt.ToFloat32());
758 } 758 }
759 759
760 float24& operator *= (const float24& flt) {
761 value *= flt.ToFloat32();
762 return *this;
763 }
764
765 float24& operator /= (const float24& flt) {
766 value /= flt.ToFloat32();
767 return *this;
768 }
769
770 float24& operator += (const float24& flt) {
771 value += flt.ToFloat32();
772 return *this;
773 }
774
775 float24& operator -= (const float24& flt) {
776 value -= flt.ToFloat32();
777 return *this;
778 }
779
760 float24 operator - () const { 780 float24 operator - () const {
761 return float24::FromFloat32(-ToFloat32()); 781 return float24::FromFloat32(-ToFloat32());
762 } 782 }
diff --git a/src/video_core/rasterizer.cpp b/src/video_core/rasterizer.cpp
index 63da7104d..a80148872 100644
--- a/src/video_core/rasterizer.cpp
+++ b/src/video_core/rasterizer.cpp
@@ -106,10 +106,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
106 int bias1 = IsRightSideOrFlatBottomEdge(vtxpos[1].xy(), vtxpos[2].xy(), vtxpos[0].xy()) ? -1 : 0; 106 int bias1 = IsRightSideOrFlatBottomEdge(vtxpos[1].xy(), vtxpos[2].xy(), vtxpos[0].xy()) ? -1 : 0;
107 int bias2 = IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0; 107 int bias2 = IsRightSideOrFlatBottomEdge(vtxpos[2].xy(), vtxpos[0].xy(), vtxpos[1].xy()) ? -1 : 0;
108 108
109 const Math::Vec3<float24> w_inverse = Math::MakeVec( 109 auto w_inverse = Math::MakeVec(v0.pos.w, v1.pos.w, v2.pos.w);
110 float24::FromFloat32(1.0f) / v0.pos.w,
111 float24::FromFloat32(1.0f) / v1.pos.w,
112 float24::FromFloat32(1.0f) / v2.pos.w);
113 110
114 auto textures = registers.GetTextures(); 111 auto textures = registers.GetTextures();
115 auto tev_stages = registers.GetTevStages(); 112 auto tev_stages = registers.GetTevStages();
@@ -158,7 +155,7 @@ void ProcessTriangle(const VertexShader::OutputVertex& v0,
158 // 155 //
159 // The generalization to three vertices is straightforward in baricentric coordinates. 156 // The generalization to three vertices is straightforward in baricentric coordinates.
160 auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) { 157 auto GetInterpolatedAttribute = [&](float24 attr0, float24 attr1, float24 attr2) {
161 auto attr_over_w = Math::MakeVec(attr0, attr1, attr2) * w_inverse; 158 auto attr_over_w = Math::MakeVec(attr0, attr1, attr2);
162 float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates); 159 float24 interpolated_attr_over_w = Math::Dot(attr_over_w, baricentric_coordinates);
163 return interpolated_attr_over_w * interpolated_w_inverse; 160 return interpolated_attr_over_w * interpolated_w_inverse;
164 }; 161 };