softgpu: Centralize more prim drawing state.

This commit is contained in:
Unknown W. Brackets committed 2022-01-12 21:23:49 -08:00
1 parent d06f17d27b
commit d962fb35d3
3 files changed
+74 -53

No files matched your search

+52 -47
View File
@@ -116,10 +116,12 @@ void ComputeRasterizerState(RasterizerState *state) {
state->linear = state->nearest;
}
int maxTexLevel = state->samplerID.hasAnyMips ? gstate.getTextureMaxLevel() : 0;
if (gstate.isTextureMapEnabled() && !state->pixelID.clearMode) {
state->maxTexLevel = state->samplerID.hasAnyMips ? gstate.getTextureMaxLevel() : 0;
state->enableTextures = gstate.isTextureMapEnabled();
if (state->enableTextures && !state->pixelID.clearMode) {
GETextureFormat texfmt = state->samplerID.TexFmt();
for (int i = 0; i <= maxTexLevel; i++) {
for (uint8_t i = 0; i <= state->maxTexLevel; i++) {
u32 texaddr = gstate.getTextureAddress(i);
state->texbufw[i] = GetTextureBufw(i, texaddr, texfmt);
if (Memory::IsValidAddress(texaddr))
@@ -128,6 +130,14 @@ void ComputeRasterizerState(RasterizerState *state) {
state->texptr[i] = nullptr;
}
}
state->texLevelMode = gstate.getTexLevelMode();
state->texLevelOffset = (int8_t)gstate.getTexLevelOffset16();
state->shadeGouraud = gstate.getShadeMode() == GE_SHADE_GOURAUD;
state->throughMode = gstate.isModeThrough();
state->mipFilt = gstate.isMipmapFilteringEnabled();
state->minFilt = gstate.isMinifyFilteringEnabled();
state->magFilt = gstate.isMagnifyFilteringEnabled();
}
static inline u8 ClampFogDepth(float fogdepth) {
@@ -506,9 +516,9 @@ Vec3<int> AlphaBlendingResult(const PixelFuncID &pixelID, const Vec4<int> &sourc
}
}
static inline Vec4IntResult SOFTRAST_CALL ApplyTexturing(float s, float t, int x, int y, Vec4IntArg prim_color, u8 *const texptr[], const int texbufw[], int texlevel, int frac_texlevel, bool bilinear, const RasterizerState &state) {
const u8 **tptr0 = const_cast<const u8 **>(&texptr[texlevel]);
const int *bufw0 = &texbufw[texlevel];
static inline Vec4IntResult SOFTRAST_CALL ApplyTexturing(float s, float t, int x, int y, Vec4IntArg prim_color, int texlevel, int frac_texlevel, bool bilinear, const RasterizerState &state) {
const u8 **tptr0 = const_cast<const u8 **>(&state.texptr[texlevel]);
const int *bufw0 = &state.texbufw[texlevel];
if (!bilinear) {
return state.nearest(s, t, x, y, prim_color, tptr0, bufw0, texlevel, frac_texlevel);
@@ -516,8 +526,8 @@ static inline Vec4IntResult SOFTRAST_CALL ApplyTexturing(float s, float t, int x
return state.linear(s, t, x, y, prim_color, tptr0, bufw0, texlevel, frac_texlevel);
}
static inline Vec4IntResult SOFTRAST_CALL ApplyTexturingSingle(float s, float t, int x, int y, Vec4IntArg prim_color, u8 *const texptr[], const int texbufw[], int texlevel, int frac_texlevel, bool bilinear, const RasterizerState &state) {
return ApplyTexturing(s, t, ((x & 15) + 1) / 2, ((y & 15) + 1) / 2, prim_color, texptr, texbufw, texlevel, frac_texlevel, bilinear, state);
static inline Vec4IntResult SOFTRAST_CALL ApplyTexturingSingle(float s, float t, int x, int y, Vec4IntArg prim_color, int texlevel, int frac_texlevel, bool bilinear, const RasterizerState &state) {
return ApplyTexturing(s, t, ((x & 15) + 1) / 2, ((y & 15) + 1) / 2, prim_color, texlevel, frac_texlevel, bilinear, state);
}
// Produces a signed 1.27.4 value.
@@ -535,13 +545,13 @@ static int TexLog2(float delta) {
return useful - 127 * 16;
}
static inline void CalculateSamplingParams(const float ds, const float dt, const int maxTexLevel, int &level, int &levelFrac, bool &filt) {
const int width = gstate.getTextureWidth(0);
const int height = gstate.getTextureHeight(0);
static inline void CalculateSamplingParams(const float ds, const float dt, const RasterizerState &state, int &level, int &levelFrac, bool &filt) {
const int width = 1 << state.samplerID.width0Shift;
const int height = 1 << state.samplerID.height0Shift;
// With 8 bits of fraction (because texslope can be fairly precise.)
int detail;
switch (gstate.getTexLevelMode()) {
switch (state.TexLevelMode()) {
case GE_TEXLEVEL_MODE_AUTO:
detail = TexLog2(std::max(ds * width, dt * height));
break;
@@ -556,13 +566,13 @@ static inline void CalculateSamplingParams(const float ds, const float dt, const
break;
}
// Add in the bias (used in all modes), expanding to 8 bits of fraction.
detail += gstate.getTexLevelOffset16();
// Add in the bias (used in all modes), with 4 bits of fraction.
detail += state.texLevelOffset;
if (detail > 0 && maxTexLevel > 0) {
bool mipFilt = gstate.isMipmapFilteringEnabled();
if (detail > 0 && state.maxTexLevel > 0) {
bool mipFilt = state.mipFilt;
int level8 = std::min(detail, maxTexLevel * 16);
int level8 = std::min(detail, state.maxTexLevel * 16);
if (!mipFilt) {
// Round up at 1.5.
level8 += 8;
@@ -575,24 +585,24 @@ static inline void CalculateSamplingParams(const float ds, const float dt, const
}
if (detail > 0)
filt = gstate.isMinifyFilteringEnabled();
filt = state.minFilt;
else
filt = gstate.isMagnifyFilteringEnabled();
filt = state.magFilt;
}
static inline void ApplyTexturing(const RasterizerState &state, Vec4<int> *prim_color, const Vec4<int> &mask, const Vec4<float> &s, const Vec4<float> &t, int maxTexLevel, u8 *const texptr[], const int texbufw[], int x, int y) {
static inline void ApplyTexturing(const RasterizerState &state, Vec4<int> *prim_color, const Vec4<int> &mask, const Vec4<float> &s, const Vec4<float> &t, int x, int y) {
float ds = s[1] - s[0];
float dt = t[2] - t[0];
int level;
int levelFrac;
bool bilinear;
CalculateSamplingParams(ds, dt, maxTexLevel, level, levelFrac, bilinear);
CalculateSamplingParams(ds, dt, state, level, levelFrac, bilinear);
PROFILE_THIS_SCOPE("sampler");
for (int i = 0; i < 4; ++i) {
if (mask[i] >= 0)
prim_color[i] = ApplyTexturing(s[i], t[i], ((x & 15) + 1) / 2, ((y & 15) + 1) / 2, ToVec4IntArg(prim_color[i]), texptr, texbufw, level, levelFrac, bilinear, state);
prim_color[i] = ApplyTexturing(s[i], t[i], ((x & 15) + 1) / 2, ((y & 15) + 1) / 2, ToVec4IntArg(prim_color[i]), level, levelFrac, bilinear, state);
}
}
@@ -775,7 +785,6 @@ void DrawTriangleSlice(
Vec4<int> bias2 = Vec4<int>::AssignToAll(IsRightSideOrFlatBottomLine(v2.screenpos.xy(), v0.screenpos.xy(), v1.screenpos.xy()) ? -1 : 0);
const PixelFuncID &pixelID = state.pixelID;
int maxTexLevel = state.samplerID.hasAnyMips ? gstate.getTextureMaxLevel() : 0;
TriangleEdge<useSSE4> e0;
TriangleEdge<useSSE4> e1;
@@ -791,7 +800,7 @@ void DrawTriangleSlice(
// All the z values are the same, no interpolation required.
// This is common, and when we interpolate, we lose accuracy.
const bool flatZ = v0.screenpos.z == v1.screenpos.z && v0.screenpos.z == v2.screenpos.z;
const bool flatColorAll = clearMode || gstate.getShadeMode() != GE_SHADE_GOURAUD;
const bool flatColorAll = clearMode || !state.shadeGouraud;
const bool flatColor0 = flatColorAll || (v0.color0 == v1.color0 && v0.color0 == v2.color0);
const bool flatColor1 = flatColorAll || (v0.color1 == v1.color1 && v0.color1 == v2.color1);
const bool noFog = clearMode || !pixelID.applyFog || (v0.fogdepth >= 1.0f && v1.fogdepth >= 1.0f && v2.fogdepth >= 1.0f);
@@ -867,21 +876,21 @@ void DrawTriangleSlice(
}
}
if (gstate.isTextureMapEnabled() && !clearMode) {
if (state.enableTextures && !clearMode) {
Vec4<float> s, t;
if (gstate.isModeThrough()) {
if (state.throughMode) {
s = Interpolate(v0.texturecoords.s(), v1.texturecoords.s(), v2.texturecoords.s(), w0, w1, w2, wsum_recip);
t = Interpolate(v0.texturecoords.t(), v1.texturecoords.t(), v2.texturecoords.t(), w0, w1, w2, wsum_recip);
// For levels > 0, mipmapping is always based on level 0. Simpler to scale first.
s *= 1.0f / (float)gstate.getTextureWidth(0);
t *= 1.0f / (float)gstate.getTextureHeight(0);
s *= 1.0f / (float)(1 << state.samplerID.width0Shift);
t *= 1.0f / (float)(1 << state.samplerID.height0Shift);
} else {
// Texture coordinate interpolation must definitely be perspective-correct.
GetTextureCoordinates(v0, v1, v2, w0, w1, w2, wsum_recip, s, t);
}
ApplyTexturing(state, prim_color, mask, s, t, maxTexLevel, state.texptr, state.texbufw, curX, curY);
ApplyTexturing(state, prim_color, mask, s, t, curX, curY);
}
if (!clearMode) {
@@ -1037,14 +1046,12 @@ void DrawPoint(const VertexData &v0, const RasterizerState &state) {
auto &pixelID = state.pixelID;
auto &samplerID = state.samplerID;
if (gstate.isTextureMapEnabled() && !pixelID.clearMode) {
int maxTexLevel = samplerID.hasAnyMips ? gstate.getTextureMaxLevel() : 0;
if (state.enableTextures && !pixelID.clearMode) {
float s = v0.texturecoords.s();
float t = v0.texturecoords.t();
if (gstate.isModeThrough()) {
s *= 1.0f / (float)gstate.getTextureWidth(0);
t *= 1.0f / (float)gstate.getTextureHeight(0);
if (state.throughMode) {
s *= 1.0f / (float)(1 << state.samplerID.width0Shift);
t *= 1.0f / (float)(1 << state.samplerID.height0Shift);
} else {
// Texture coordinate interpolation must definitely be perspective-correct.
GetTextureCoordinates(v0, v0, 0.0f, s, t);
@@ -1053,9 +1060,9 @@ void DrawPoint(const VertexData &v0, const RasterizerState &state) {
int texLevel;
int texLevelFrac;
bool bilinear;
CalculateSamplingParams(0.0f, 0.0f, maxTexLevel, texLevel, texLevelFrac, bilinear);
CalculateSamplingParams(0.0f, 0.0f, state, texLevel, texLevelFrac, bilinear);
PROFILE_THIS_SCOPE("sampler");
prim_color = ApplyTexturingSingle(s, t, pos.x, pos.y, ToVec4IntArg(prim_color), state.texptr, state.texbufw, texLevel, texLevelFrac, bilinear, state);
prim_color = ApplyTexturingSingle(s, t, pos.x, pos.y, ToVec4IntArg(prim_color), texLevel, texLevelFrac, bilinear, state);
}
if (!pixelID.clearMode)
@@ -1308,8 +1315,6 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const RasterizerState
scissorBR.x += 15;
scissorBR.y += 15;
int maxTexLevel = state.samplerID.hasAnyMips ? gstate.getTextureMaxLevel() : 0;
auto &pixelID = state.pixelID;
auto &samplerID = state.samplerID;
@@ -1349,17 +1354,17 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const RasterizerState
prim_color.a() = 0x7F;
}
if (gstate.isTextureMapEnabled() && !pixelID.clearMode) {
if (state.enableTextures && !pixelID.clearMode) {
float s, s1;
float t, t1;
if (gstate.isModeThrough()) {
if (state.throughMode) {
Vec2<float> tc = (v0.texturecoords * (float)(steps - i) + v1.texturecoords * (float)i) / steps1;
Vec2<float> tc1 = (v0.texturecoords * (float)(steps - i - 1) + v1.texturecoords * (float)(i + 1)) / steps1;
s = tc.s() * (1.0f / (float)gstate.getTextureWidth(0));
s1 = tc1.s() * (1.0f / (float)gstate.getTextureWidth(0));
t = tc.t() * (1.0f / (float)gstate.getTextureHeight(0));
t1 = tc1.t() * (1.0f / (float)gstate.getTextureHeight(0));
s = tc.s() * (1.0f / (float)(1 << state.samplerID.width0Shift));
s1 = tc1.s() * (1.0f / (float)(1 << state.samplerID.width0Shift));
t = tc.t() * (1.0f / (float)(1 << state.samplerID.height0Shift));
t1 = tc1.t() * (1.0f / (float)(1 << state.samplerID.height0Shift));
} else {
// Texture coordinate interpolation must definitely be perspective-correct.
GetTextureCoordinates(v0, v1, (float)(steps - i) / steps1, s, t);
@@ -1373,7 +1378,7 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const RasterizerState
int texLevel;
int texLevelFrac;
bool texBilinear;
CalculateSamplingParams(ds, dt, maxTexLevel, texLevel, texLevelFrac, texBilinear);
CalculateSamplingParams(ds, dt, state, texLevel, texLevelFrac, texBilinear);
if (gstate.isAntiAliasEnabled()) {
// TODO: This is a niave and wrong implementation.
@@ -1385,7 +1390,7 @@ void DrawLine(const VertexData &v0, const VertexData &v1, const RasterizerState
}
PROFILE_THIS_SCOPE("sampler");
prim_color = ApplyTexturingSingle(s, t, x, y, ToVec4IntArg(prim_color), state.texptr, state.texbufw, texLevel, texLevelFrac, texBilinear, state);
prim_color = ApplyTexturingSingle(s, t, x, y, ToVec4IntArg(prim_color), texLevel, texLevelFrac, texBilinear, state);
}
if (!pixelID.clearMode)
+16
View File
@@ -40,6 +40,22 @@ struct RasterizerState {
Sampler::NearestFunc nearest;
int texbufw[8]{};
u8 *texptr[8]{};
struct {
uint8_t maxTexLevel : 3;
bool enableTextures : 1;
uint8_t texLevelMode : 2;
bool shadeGouraud : 1;
bool throughMode : 1;
int8_t texLevelOffset : 8;
bool mipFilt : 1;
bool minFilt : 1;
bool magFilt : 1;
};
GETexLevelMode TexLevelMode() const {
return GETexLevelMode(texLevelMode);
}
};
void ComputeRasterizerState(RasterizerState *state);
+6 -6
View File
@@ -102,7 +102,7 @@ void DrawSprite(const VertexData &v0, const VertexData &v1, const RasterizerStat
constexpr int MIN_LINES_PER_THREAD = 32;
if (gstate.isTextureMapEnabled()) {
if (state.enableTextures) {
// 1:1 (but with mirror support) texture mapping!
int s_start = v0.texturecoords.x;
int t_start = v0.texturecoords.y;
@@ -184,10 +184,10 @@ void DrawSprite(const VertexData &v0, const VertexData &v1, const RasterizerStat
int xoff = ((v0.screenpos.x & 15) + 1) / 2;
int yoff = ((v0.screenpos.y & 15) + 1) / 2;
float dsf = ds * (1.0f / (float)gstate.getTextureWidth(0));
float dtf = dt * (1.0f / (float)gstate.getTextureHeight(0));
float sf_start = s_start * (1.0f / (float)gstate.getTextureWidth(0));
float tf_start = t_start * (1.0f / (float)gstate.getTextureHeight(0));
float dsf = ds * (1.0f / (float)(1 << state.samplerID.width0Shift));
float dtf = dt * (1.0f / (float)(1 << state.samplerID.height0Shift));
float sf_start = s_start * (1.0f / (float)(1 << state.samplerID.width0Shift));
float tf_start = t_start * (1.0f / (float)(1 << state.samplerID.height0Shift));
ParallelRangeLoop(&g_threadManager, [=](int y1, int y2) {
float t = tf_start + (y1 - pos0.y) * dtf;
@@ -291,7 +291,7 @@ bool RectangleFastPath(const VertexData &v0, const VertexData &v1, const Rasteri
// We already have a fast path for clear in ClearRectangle.
bool state_check = !state.pixelID.clearMode && NoClampOrWrap(v0.texturecoords) && NoClampOrWrap(v1.texturecoords);
// TODO: No mipmap levels? Might be a font at level 1...
if ((coord_check || !gstate.isTextureMapEnabled()) && orient_check && state_check) {
if ((coord_check || !state.enableTextures) && orient_check && state_check) {
Rasterizer::DrawSprite(v0, v1, state);
return true;
}