diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9736b0347b..402a7900f8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2087,6 +2087,7 @@ set(GPU_SOURCES
GPU/GPUCommonHW.h
GPU/GPUState.cpp
GPU/GPUState.h
+ GPU/GPUStateSIMDUtil.h
GPU/Math3D.cpp
GPU/Math3D.h
GPU/Software/BinManager.cpp
diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp
index cbfe5b7c66..930eaf5c16 100644
--- a/GPU/Common/SoftwareTransformCommon.cpp
+++ b/GPU/Common/SoftwareTransformCommon.cpp
@@ -21,10 +21,12 @@
#include "Common/CPUDetect.h"
#include "Common/Math/math_util.h"
#include "Common/GPU/OpenGL/GLFeatures.h"
+#include "Common/Math/CrossSIMD.h"
#include "Core/Config.h"
#include "Core/System.h"
#include "GPU/GPUState.h"
#include "GPU/Math3D.h"
+#include "GPU/GPUStateSIMDUtil.h"
#include "GPU/Common/FramebufferManagerCommon.h"
#include "GPU/Common/GPUStateUtils.h"
#include "GPU/Common/SoftwareTransformCommon.h"
@@ -398,6 +400,7 @@ SoftwareTransformAction SoftwareTransform::Transform(const float projMtx[16], Li
// Modifies the vertices in-place. Applies viewport and projection.
// TODO: SIMD.
void SoftwareTransform::ProjectVertices(TransformedVertex *transformed, int vertexCount) {
+#if 0
Lin::Vec3 vpOffset(gstate.getViewportXCenter(), gstate.getViewportYCenter(), gstate.getViewportZCenter());
Lin::Vec3 vpScale(gstate.getViewportXScale(), gstate.getViewportYScale(), gstate.getViewportZScale());
@@ -411,6 +414,18 @@ void SoftwareTransform::ProjectVertices(TransformedVertex *transformed, int vert
transformed[i].y = xyz.y;
transformed[i].z = xyz.z;
}
+#else
+ const Vec4F32 vpOffset = GetViewportOffsetVec(gstate);
+ const Vec4F32 vpScale = GetViewportScaleVec(gstate);
+ // CrossSIMD implementation.
+ for (int i = 0; i < vertexCount; i++) {
+ Vec4F32 xyzw = Vec4F32::Load(&transformed[i].x);
+ Vec4F32 wRecip = Vec4F32::Splat(1.0f / transformed[i].pos_w);
+ Vec4F32 projected = xyzw * wRecip * vpScale + vpOffset;
+ // Now, we need to restore the W value as we'll still need it later.
+ projected.WithLane3From(xyzw).Store(&transformed[i].x);
+ }
+#endif
}
SoftwareTransformAction SoftwareTransform::ProjectClipAndExpand(int prim, int vertexCount, u32 vertType, u16 *&inds, int indsSize, int &numDecodedVerts, int vertsSize, SoftwareTransformResult *result) {
@@ -1065,7 +1080,7 @@ u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int low
}
// clip space to screen space
-Vec3f ClipToScreen(const Vec4f& coords) {
+static Vec3f ClipToScreen(const Vec4f& coords) {
float xScale = gstate.getViewportXScale();
float xCenter = gstate.getViewportXCenter();
float yScale = gstate.getViewportYScale();
diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj
index 1ae4f38491..41f1384e4a 100644
--- a/GPU/GPU.vcxproj
+++ b/GPU/GPU.vcxproj
@@ -333,6 +333,7 @@
+
diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters
index 389b88b0b5..585a95dfde 100644
--- a/GPU/GPU.vcxproj.filters
+++ b/GPU/GPU.vcxproj.filters
@@ -264,6 +264,9 @@
Common
+
+ Common
+
diff --git a/GPU/GPUStateSIMDUtil.h b/GPU/GPUStateSIMDUtil.h
new file mode 100644
index 0000000000..6dfd110b0b
--- /dev/null
+++ b/GPU/GPUStateSIMDUtil.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "Common/Math/CrossSIMD.h"
+#include "GPU/GPUState.h"
+
+inline Vec4F32 GetViewportOffsetVec(const GPUgstate &gstate) {
+ return Vec4F32::LoadF24x3_DontCare(&gstate.viewportxcenter);
+}
+inline Vec4F32 GetViewportScaleVec(const GPUgstate &gstate) {
+ return Vec4F32::LoadF24x3_DontCare(&gstate.viewportxscale);
+}