From 416df17088160477df758708b3bfaa8f78cb2210 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 17 Mar 2014 23:03:04 -0700 Subject: [PATCH 1/2] Inline From/ToRGB(A) to avoid losing SSE. Otherwise it has to store it, which I'd like to avoid. --- GPU/Math3D.cpp | 108 ------------------------------------------------- GPU/Math3D.h | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 108 deletions(-) diff --git a/GPU/Math3D.cpp b/GPU/Math3D.cpp index abacd62f97..a6dd8780fc 100644 --- a/GPU/Math3D.cpp +++ b/GPU/Math3D.cpp @@ -66,59 +66,6 @@ float Vec2::Normalize() return len; } -template<> -Vec3 Vec3::FromRGB(unsigned int rgb) -{ -#if defined(_M_SSE) - __m128i z = _mm_setzero_si128(); - __m128i c = _mm_cvtsi32_si128(rgb); - c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); - return Vec3(_mm_mul_ps(_mm_cvtepi32_ps(c), _mm_set_ps1(1.0f / 255.0f))); -#else - return Vec3((rgb & 0xFF) * (1.0f/255.0f), - ((rgb >> 8) & 0xFF) * (1.0f/255.0f), - ((rgb >> 16) & 0xFF) * (1.0f/255.0f)); -#endif -} - -template<> -Vec3 Vec3::FromRGB(unsigned int rgb) -{ -#if defined(_M_SSE) - __m128i z = _mm_setzero_si128(); - __m128i c = _mm_cvtsi32_si128(rgb); - c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); - return Vec3(c); -#else - return Vec3(rgb & 0xFF, (rgb >> 8) & 0xFF, (rgb >> 16) & 0xFF); -#endif -} - -template<> -unsigned int Vec3::ToRGB() const -{ -#if defined(_M_SSE) - __m128i c = _mm_cvtps_epi32(_mm_mul_ps(vec, _mm_set_ps1(255.0f))); - __m128i c16 = _mm_packs_epi32(c, c); - return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)) & 0x00FFFFFF; -#else - return ((unsigned int)(r()*255.f)) + - ((unsigned int)(g()*255.f*256.f)) + - ((unsigned int)(b()*255.f*256.f*256.f)); -#endif -} - -template<> -unsigned int Vec3::ToRGB() const -{ -#if defined(_M_SSE) - __m128i c16 = _mm_packs_epi32(ivec, ivec); - return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)) & 0x00FFFFFF; -#else - return (r()&0xFF) | ((g()&0xFF)<<8) | ((b()&0xFF)<<16); -#endif -} - template<> float Vec3::Length() const { @@ -233,61 +180,6 @@ float Vec3Packed::Normalize() return len; } -template<> -Vec4 Vec4::FromRGBA(unsigned int rgba) -{ -#if defined(_M_SSE) - __m128i z = _mm_setzero_si128(); - __m128i c = _mm_cvtsi32_si128(rgba); - c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); - return Vec4(_mm_mul_ps(_mm_cvtepi32_ps(c), _mm_set_ps1(1.0f / 255.0f))); -#else - return Vec4((rgba & 0xFF) * (1.0f/255.0f), - ((rgba >> 8) & 0xFF) * (1.0f/255.0f), - ((rgba >> 16) & 0xFF) * (1.0f/255.0f), - ((rgba >> 24) & 0xFF) * (1.0f/255.0f)); -#endif -} - -template<> -Vec4 Vec4::FromRGBA(unsigned int rgba) -{ -#if defined(_M_SSE) - __m128i z = _mm_setzero_si128(); - __m128i c = _mm_cvtsi32_si128(rgba); - c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); - return Vec4(c); -#else - return Vec4(rgba & 0xFF, (rgba >> 8) & 0xFF, (rgba >> 16) & 0xFF, (rgba >> 24) & 0xFF); -#endif -} - -template<> -unsigned int Vec4::ToRGBA() const -{ -#if defined(_M_SSE) - __m128i c = _mm_cvtps_epi32(_mm_mul_ps(vec, _mm_set_ps1(255.0f))); - __m128i c16 = _mm_packs_epi32(c, c); - return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)); -#else - return ((unsigned int)(r()*255.f)) + - ((unsigned int)(g()*255.f*256.f)) + - ((unsigned int)(b()*255.f*256.f*256.f)) + - ((unsigned int)(a()*255.f*256.f*256.f*256.f)); -#endif -} - -template<> -unsigned int Vec4::ToRGBA() const -{ -#if defined(_M_SSE) - __m128i c16 = _mm_packs_epi32(ivec, ivec); - return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)); -#else - return (r()&0xFF) | ((g()&0xFF)<<8) | ((b()&0xFF)<<16) | ((a()&0xFF)<<24); -#endif -} - template<> float Vec4::Length() const { diff --git a/GPU/Math3D.h b/GPU/Math3D.h index 4db25b9171..2b1a5c575d 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -891,6 +891,114 @@ inline Vec3Packed Cross(const Vec3Packed& a, const Vec3Packed& b) return Vec3Packed(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x); } +template<> +inline Vec3 Vec3::FromRGB(unsigned int rgb) +{ +#if defined(_M_SSE) + __m128i z = _mm_setzero_si128(); + __m128i c = _mm_cvtsi32_si128(rgb); + c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); + return Vec3(_mm_mul_ps(_mm_cvtepi32_ps(c), _mm_set_ps1(1.0f / 255.0f))); +#else + return Vec3((rgb & 0xFF) * (1.0f/255.0f), + ((rgb >> 8) & 0xFF) * (1.0f/255.0f), + ((rgb >> 16) & 0xFF) * (1.0f/255.0f)); +#endif +} + +template<> +inline Vec3 Vec3::FromRGB(unsigned int rgb) +{ +#if defined(_M_SSE) + __m128i z = _mm_setzero_si128(); + __m128i c = _mm_cvtsi32_si128(rgb); + c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); + return Vec3(c); +#else + return Vec3(rgb & 0xFF, (rgb >> 8) & 0xFF, (rgb >> 16) & 0xFF); +#endif +} + +template<> +inline unsigned int Vec3::ToRGB() const +{ +#if defined(_M_SSE) + __m128i c = _mm_cvtps_epi32(_mm_mul_ps(vec, _mm_set_ps1(255.0f))); + __m128i c16 = _mm_packs_epi32(c, c); + return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)) & 0x00FFFFFF; +#else + return ((unsigned int)(r()*255.f)) + + ((unsigned int)(g()*255.f*256.f)) + + ((unsigned int)(b()*255.f*256.f*256.f)); +#endif +} + +template<> +inline unsigned int Vec3::ToRGB() const +{ +#if defined(_M_SSE) + __m128i c16 = _mm_packs_epi32(ivec, ivec); + return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)) & 0x00FFFFFF; +#else + return (r()&0xFF) | ((g()&0xFF)<<8) | ((b()&0xFF)<<16); +#endif +} + +template<> +inline Vec4 Vec4::FromRGBA(unsigned int rgba) +{ +#if defined(_M_SSE) + __m128i z = _mm_setzero_si128(); + __m128i c = _mm_cvtsi32_si128(rgba); + c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); + return Vec4(_mm_mul_ps(_mm_cvtepi32_ps(c), _mm_set_ps1(1.0f / 255.0f))); +#else + return Vec4((rgba & 0xFF) * (1.0f/255.0f), + ((rgba >> 8) & 0xFF) * (1.0f/255.0f), + ((rgba >> 16) & 0xFF) * (1.0f/255.0f), + ((rgba >> 24) & 0xFF) * (1.0f/255.0f)); +#endif +} + +template<> +inline Vec4 Vec4::FromRGBA(unsigned int rgba) +{ +#if defined(_M_SSE) + __m128i z = _mm_setzero_si128(); + __m128i c = _mm_cvtsi32_si128(rgba); + c = _mm_unpacklo_epi16(_mm_unpacklo_epi8(c, z), z); + return Vec4(c); +#else + return Vec4(rgba & 0xFF, (rgba >> 8) & 0xFF, (rgba >> 16) & 0xFF, (rgba >> 24) & 0xFF); +#endif +} + +template<> +inline unsigned int Vec4::ToRGBA() const +{ +#if defined(_M_SSE) + __m128i c = _mm_cvtps_epi32(_mm_mul_ps(vec, _mm_set_ps1(255.0f))); + __m128i c16 = _mm_packs_epi32(c, c); + return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)); +#else + return ((unsigned int)(r()*255.f)) + + ((unsigned int)(g()*255.f*256.f)) + + ((unsigned int)(b()*255.f*256.f*256.f)) + + ((unsigned int)(a()*255.f*256.f*256.f*256.f)); +#endif +} + +template<> +inline unsigned int Vec4::ToRGBA() const +{ +#if defined(_M_SSE) + __m128i c16 = _mm_packs_epi32(ivec, ivec); + return _mm_cvtsi128_si32(_mm_packus_epi16(c16, c16)); +#else + return (r()&0xFF) | ((g()&0xFF)<<8) | ((b()&0xFF)<<16) | ((a()&0xFF)<<24); +#endif +} + }; // namespace Math3D // linear interpolation via float: 0.0=begin, 1.0=end From 678237aa6cc52039c69b10eb4068e433d2117fda Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 17 Mar 2014 23:05:48 -0700 Subject: [PATCH 2/2] Improve SSE usage in software transform. It's actually already pretty decent (unlike the softgpu), but there were a few places it could use a bit of help. Speeds up things with hardware transform off, or areas that need to use software transform. --- GPU/Common/VertexDecoderCommon.h | 10 ++++++-- GPU/GLES/SoftwareTransform.cpp | 43 ++++++++++---------------------- GPU/GPUState.h | 1 + 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index f885e1cd0b..07430429e5 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -67,8 +67,14 @@ struct TransformedVertex { float x, y, z, fog; // in case of morph, preblend during decode float u; float v; float w; // scaled by uscale, vscale, if there - u8 color0[4]; // prelit - u8 color1[4]; // prelit + union { + u8 color0[4]; // prelit + u32 color0_32; + }; + union { + u8 color1[4]; // prelit + u32 color1_32; + }; }; void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound); diff --git a/GPU/GLES/SoftwareTransform.cpp b/GPU/GLES/SoftwareTransform.cpp index 2d50734fb2..47eee5e2b0 100644 --- a/GPU/GLES/SoftwareTransform.cpp +++ b/GPU/GLES/SoftwareTransform.cpp @@ -318,8 +318,8 @@ void TransformDrawEngine::SoftwareTransformAndDraw( reader.Goto(index); float v[3] = {0, 0, 0}; - float c0[4] = {1, 1, 1, 1}; - float c1[4] = {0, 0, 0, 0}; + Vec4f c0 = Vec4f(1, 1, 1, 1); + Vec4f c1 = Vec4f(0, 0, 0, 0); float uv[3] = {0, 0, 1}; float fogCoef = 1.0f; @@ -327,15 +327,10 @@ void TransformDrawEngine::SoftwareTransformAndDraw( // Do not touch the coordinates or the colors. No lighting. reader.ReadPos(v); if (reader.hasColor0()) { - reader.ReadColor0(c0); - for (int j = 0; j < 4; j++) { - c1[j] = 0.0f; - } + reader.ReadColor0(&c0.x); + // c1 is already 0. } else { - c0[0] = gstate.getMaterialAmbientR() / 255.f; - c0[1] = gstate.getMaterialAmbientG() / 255.f; - c0[2] = gstate.getMaterialAmbientB() / 255.f; - c0[3] = gstate.getMaterialAmbientA() / 255.f; + c0 = Vec4f::FromRGBA(gstate.getMaterialAmbientRGBA()); } if (reader.hasUV()) { @@ -389,18 +384,15 @@ void TransformDrawEngine::SoftwareTransformAndDraw( } // Perform lighting here if enabled. don't need to check through, it's checked above. - float unlitColor[4] = {1, 1, 1, 1}; + Vec4f unlitColor = Vec4f(1, 1, 1, 1); if (reader.hasColor0()) { - reader.ReadColor0(unlitColor); + reader.ReadColor0(&unlitColor.x); } else { - unlitColor[0] = gstate.getMaterialAmbientR() / 255.f; - unlitColor[1] = gstate.getMaterialAmbientG() / 255.f; - unlitColor[2] = gstate.getMaterialAmbientB() / 255.f; - unlitColor[3] = gstate.getMaterialAmbientA() / 255.f; + unlitColor = Vec4f::FromRGBA(gstate.getMaterialAmbientRGBA()); } float litColor0[4]; float litColor1[4]; - lighter.Light(litColor0, litColor1, unlitColor, out, normal); + lighter.Light(litColor0, litColor1, unlitColor.AsArray(), out, normal); if (gstate.isLightingEnabled()) { // Don't ignore gstate.lmode - we should send two colors in that case @@ -424,15 +416,10 @@ void TransformDrawEngine::SoftwareTransformAndDraw( c0[j] = unlitColor[j]; } } else { - c0[0] = gstate.getMaterialAmbientR() / 255.f; - c0[1] = gstate.getMaterialAmbientG() / 255.f; - c0[2] = gstate.getMaterialAmbientB() / 255.f; - c0[3] = gstate.getMaterialAmbientA() / 255.f; + c0 = Vec4f::FromRGBA(gstate.getMaterialAmbientRGBA()); } if (lmode) { - for (int j = 0; j < 4; j++) { - c1[j] = 0.0f; - } + // c1 is already 0. } } @@ -528,12 +515,8 @@ void TransformDrawEngine::SoftwareTransformAndDraw( if (gstate_c.flipTexture) { transformed[index].v = 1.0f - transformed[index].v; } - for (int i = 0; i < 4; i++) { - transformed[index].color0[i] = c0[i] * 255.0f; - } - for (int i = 0; i < 3; i++) { - transformed[index].color1[i] = c1[i] * 255.0f; - } + transformed[index].color0_32 = c0.ToRGBA(); + transformed[index].color1_32 = c1.ToRGBA(); } // Here's the best opportunity to try to detect rectangles used to clear the screen, and diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 10f003d3fc..691308b38c 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -331,6 +331,7 @@ struct GPUgstate unsigned int getMaterialAmbientG() const { return (materialambient>>8)&0xFF; } unsigned int getMaterialAmbientB() const { return (materialambient>>16)&0xFF; } unsigned int getMaterialAmbientA() const { return materialalpha&0xFF; } + unsigned int getMaterialAmbientRGBA() const { return (materialambient & 0x00FFFFFF) | (materialalpha << 24); } unsigned int getMaterialDiffuseR() const { return materialdiffuse&0xFF; } unsigned int getMaterialDiffuseG() const { return (materialdiffuse>>8)&0xFF; } unsigned int getMaterialDiffuseB() const { return (materialdiffuse>>16)&0xFF; }