Merge pull request #17295 from unknownbrackets/softgpu-opt

Optimize lighting for softgpu a bit
This commit is contained in:
Henrik Rydgård authored and GitHub committed 2023-04-16 23:05:04 +02:00
commit f363d2e79f
5 files changed
+88 -25

No files matched your search

+3 -2
View File
@@ -368,8 +368,9 @@ void BinManager::UpdateClut(const void *src) {
PROFILE_THIS_SCOPE("bin_clut");
if (cluts_.Full())
Flush("cluts");
clutIndex_ = (uint16_t)cluts_.Push(BinClut());
memcpy(cluts_[clutIndex_].readable, src, sizeof(BinClut));
BinClut &clut = cluts_.PeekPush();
memcpy(clut.readable, src, sizeof(BinClut));
clutIndex_ = (uint16_t)cluts_.PushPeeked();
}
void BinManager::AddTriangle(const VertexData &v0, const VertexData &v1, const VertexData &v2) {
+2 -1
View File
@@ -117,11 +117,12 @@ struct BinQueue {
return items_[tail_];
}
void PushPeeked() {
size_t PushPeeked() {
size_t i = tail_++;
if (i + 1 == N)
tail_ -= N;
size_++;
return i;
}
size_t Size() const {
+77 -15
View File
@@ -86,6 +86,7 @@ void ComputeState(State *state, bool hasColor0) {
bool anyAmbient = false;
bool anyDiffuse = false;
bool anySpecular = false;
bool anyDirectional = false;
for (int light = 0; light < 4; ++light) {
auto &lstate = state->lights[light];
lstate.enabled = gstate.isLightChanEnabled(light);
@@ -112,10 +113,12 @@ void ComputeState(State *state, bool hasColor0) {
}
lstate.pos = GetLightVec(gstate.lpos, light);
if (lstate.directional)
if (lstate.directional) {
lstate.pos.NormalizeOr001();
else
anyDirectional = true;
} else {
lstate.att = GetLightVec(gstate.latt, light);
}
if (lstate.spot) {
lstate.spotDir = GetLightVec(gstate.ldir, light);
@@ -174,6 +177,8 @@ void ComputeState(State *state, bool hasColor0) {
state->baseAmbientColorFactor = LightColorFactor(gstate.getAmbientRGBA(), ones);
state->setColor1 = gstate.isUsingSecondaryColor() && anySpecular;
state->addColor1 = !gstate.isUsingSecondaryColor() && anySpecular;
state->usesWorldPos = anyDirectional;
state->usesWorldNormal = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP || anyDiffuse || anySpecular;
}
static inline float GenerateLightCoord(VertexData &vertex, const WorldCoords &worldnormal, int light) {
@@ -192,6 +197,62 @@ void GenerateLightST(VertexData &vertex, const WorldCoords &worldnormal) {
vertex.texturecoords.t() = GenerateLightCoord(vertex, worldnormal, gstate.getUVLS1());
}
#if defined(_M_SSE)
#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)
[[gnu::target("sse4.1")]]
#endif
static inline int LightCeilSSE4(float f) {
__m128 v = _mm_set_ss(f);
// This isn't terribly fast, but seems to be better than calling ceilf().
return _mm_cvt_ss2si(_mm_ceil_ss(v, v));
}
#if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER)
[[gnu::target("sse4.1")]]
#endif
static inline __m128i LightColorScaleBy512SSE4(__m128i factor, __m128i color, __m128i scale) {
// We can use 16-bit multiply here (faster than 32-bit multiply) since our top bits are zero.
__m128i result18 = _mm_madd_epi16(factor, color);
// But now with 18 bits, we need a full multiply.
__m128i multiplied = _mm_mullo_epi32(result18, scale);
return _mm_srai_epi32(multiplied, 19);
}
#endif
static inline int LightCeil(float f) {
#if defined(_M_SSE)
if (cpu_info.bSSE4_1)
return LightCeilSSE4(f);
#elif PPSSPP_ARCH(ARM64_NEON)
return vcvtps_s32_f32(f);
#endif
return (int)ceilf(f);
}
static Vec4<int> LightColorScaleBy512(const Vec4<int> &factor, const Vec4<int> &color, int scale) {
// We multiply s9 * s9 * s9, resulting in s27, then shift off 19 to get 8-bit.
// The reason all factors are s9 is to account for rounding.
// Also note that all values are positive, so can be treated as unsigned.
#if defined(_M_SSE) && !PPSSPP_ARCH(X86)
if (cpu_info.bSSE4_1)
return LightColorScaleBy512SSE4(factor.ivec, color.ivec, _mm_set1_epi32(scale));
#elif PPSSPP_ARCH(ARM64_NEON)
int32x4_t multiplied = vmulq_n_s32(vmulq_s32(factor.ivec, color.ivec), scale);
return vshrq_n_s32(multiplied, 19);
#endif
return (factor * color * scale) / (1024 * 512);
}
static inline void LightColorSum(Vec4<int> &sum, const Vec4<int> &src) {
#if defined(_M_SSE) && !PPSSPP_ARCH(X86)
sum.ivec = _mm_add_epi32(sum.ivec, src.ivec);
#elif PPSSPP_ARCH(ARM64_NEON)
sum.ivec = vaddq_s32(sum.ivec, src.ivec);
#else
sum += src;
#endif
}
void Process(VertexData &vertex, const WorldCoords &worldpos, const WorldCoords &worldnormal, const State &state) {
// Lighting blending rounds using the half offset method (like alpha blend.)
const Vec4<int> ones = Vec4<int>::AssignToAll(1);
@@ -245,11 +306,11 @@ void Process(VertexData &vertex, const WorldCoords &worldpos, const WorldCoords
// ambient lighting
if (lstate.ambient) {
int attspot = (int)ceilf(256 * 2 * att * spot + 1);
int attspot = (int)LightCeil(256 * 2 * att * spot + 1);
if (attspot > 512)
attspot = 512;
Vec4<int> lambient = (mac * lstate.ambientColorFactor * attspot) / (1024 * 512);
final_color += lambient;
Vec4<int> lambient = LightColorScaleBy512(lstate.ambientColorFactor, mac, attspot);
LightColorSum(final_color, lambient);
}
// diffuse lighting
@@ -262,12 +323,12 @@ void Process(VertexData &vertex, const WorldCoords &worldpos, const WorldCoords
}
if (lstate.diffuse && diffuse_factor > 0.0f) {
int diffuse_attspot = (int)ceilf(256 * 2 * att * spot * diffuse_factor + 1);
int diffuse_attspot = (int)LightCeil(256 * 2 * att * spot * diffuse_factor + 1);
if (diffuse_attspot > 512)
diffuse_attspot = 512;
Vec4<int> mdc = state.colorForDiffuse ? colorFactor : state.material.diffuseColorFactor;
Vec4<int> ldiffuse = (lstate.diffuseColorFactor * mdc * diffuse_attspot) / (1024 * 512);
final_color += ldiffuse;
Vec4<int> ldiffuse = LightColorScaleBy512(lstate.diffuseColorFactor, mdc, diffuse_attspot);
LightColorSum(final_color, ldiffuse);
}
if (lstate.specular && diffuse_factor >= 0.0f) {
@@ -277,24 +338,25 @@ void Process(VertexData &vertex, const WorldCoords &worldpos, const WorldCoords
specular_factor = pspLightPow(specular_factor, state.specularExp);
if (specular_factor > 0.0f) {
int specular_attspot = (int)ceilf(256 * 2 * att * spot * specular_factor + 1);
int specular_attspot = (int)LightCeil(256 * 2 * att * spot * specular_factor + 1);
if (specular_attspot > 512)
specular_attspot = 512;
Vec4<int> msc = state.colorForSpecular ? colorFactor : state.material.specularColorFactor;
Vec4<int> lspecular = (lstate.specularColorFactor * msc * specular_attspot) / (1024 * 512);
specular_color += lspecular;
Vec4<int> lspecular = LightColorScaleBy512(lstate.specularColorFactor, msc, specular_attspot);
LightColorSum(specular_color, lspecular);
}
}
}
// Note: these are all naturally clamped by ToRGBA/toRGB.
if (state.setColor1) {
vertex.color0 = final_color.Clamp(0, 255).ToRGBA();
vertex.color1 = specular_color.Clamp(0, 255).rgb().ToRGB();
vertex.color0 = final_color.ToRGBA();
vertex.color1 = specular_color.rgb().ToRGB();
} else if (state.addColor1) {
vertex.color0 = (final_color + specular_color).Clamp(0, 255).ToRGBA();
vertex.color0 = (final_color + specular_color).ToRGBA();
} else {
vertex.color0 = final_color.Clamp(0, 255).ToRGBA();
vertex.color0 = final_color.ToRGBA();
}
}
+2
View File
@@ -60,6 +60,8 @@ struct State {
bool colorForSpecular : 1;
bool setColor1 : 1;
bool addColor1 : 1;
bool usesWorldPos : 1;
bool usesWorldNormal : 1;
};
};
+4 -7
View File
@@ -273,12 +273,9 @@ void ComputeTransformState(TransformState *state, const VertexReader &vreader) {
bool canSkipWorldPos = true;
if (state->enableLighting) {
Lighting::ComputeState(&state->lightingState, vreader.hasColor0());
for (int i = 0; i < 4; ++i) {
if (!state->lightingState.lights[i].enabled)
continue;
if (!state->lightingState.lights[i].directional)
canSkipWorldPos = false;
}
canSkipWorldPos = !state->lightingState.usesWorldPos;
} else {
state->lightingState.usesWorldNormal = state->uvGenMode == GE_TEXMAP_ENVIRONMENT_MAP;
}
float world[16];
@@ -412,7 +409,7 @@ ClipVertexData TransformUnit::ReadVertex(const VertexReader &vreader, const Tran
vertex.v.clipw = vertex.clippos.w;
Vec3<float> worldnormal;
if (state.enableLighting || state.uvGenMode == GE_TEXMAP_ENVIRONMENT_MAP) {
if (state.lightingState.usesWorldNormal) {
worldnormal = TransformUnit::ModelToWorldNormal(normal);
worldnormal.NormalizeOr001();
}