diff --git a/GPU/Software/BinManager.cpp b/GPU/Software/BinManager.cpp index c6c752ae73..1a23e2622a 100644 --- a/GPU/Software/BinManager.cpp +++ b/GPU/Software/BinManager.cpp @@ -388,6 +388,7 @@ void BinManager::AddTriangle(const VertexData &v0, const VertexData &v1, const V if (queue_.Full()) Drain(); queue_.Push(BinItem{ BinItemType::TRIANGLE, stateIndex_, range, v0, v1, v2 }); + CalculateRasterStateFlags(&states_[stateIndex_], v0, v1, v2); Expand(range); } @@ -399,6 +400,7 @@ void BinManager::AddClearRect(const VertexData &v0, const VertexData &v1) { if (queue_.Full()) Drain(); queue_.Push(BinItem{ BinItemType::CLEAR_RECT, stateIndex_, range, v0, v1 }); + CalculateRasterStateFlags(&states_[stateIndex_], v0, v1, true); Expand(range); } @@ -410,6 +412,7 @@ void BinManager::AddRect(const VertexData &v0, const VertexData &v1) { if (queue_.Full()) Drain(); queue_.Push(BinItem{ BinItemType::RECT, stateIndex_, range, v0, v1 }); + CalculateRasterStateFlags(&states_[stateIndex_], v0, v1, true); Expand(range); } @@ -421,6 +424,7 @@ void BinManager::AddSprite(const VertexData &v0, const VertexData &v1) { if (queue_.Full()) Drain(); queue_.Push(BinItem{ BinItemType::SPRITE, stateIndex_, range, v0, v1 }); + CalculateRasterStateFlags(&states_[stateIndex_], v0, v1, true); Expand(range); } @@ -432,6 +436,7 @@ void BinManager::AddLine(const VertexData &v0, const VertexData &v1) { if (queue_.Full()) Drain(); queue_.Push(BinItem{ BinItemType::LINE, stateIndex_, range, v0, v1 }); + CalculateRasterStateFlags(&states_[stateIndex_], v0, v1, false); Expand(range); } @@ -443,6 +448,7 @@ void BinManager::AddPoint(const VertexData &v0) { if (queue_.Full()) Drain(); queue_.Push(BinItem{ BinItemType::POINT, stateIndex_, range, v0 }); + CalculateRasterStateFlags(&states_[stateIndex_], v0); Expand(range); } diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index 8a0263238e..fc535a5779 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -155,6 +155,33 @@ void ComputeRasterizerState(RasterizerState *state, std::function flushF #endif } +static inline void CalculateRasterStateFlags(RasterizerState *state, const VertexData &v0, bool useColor) { + if (useColor) { + if ((v0.color0 & 0x00FFFFFF) != 0x00FFFFFF) + state->flags |= RasterizerStateFlags::VERTEX_NON_FULL_WHITE; + uint8_t alpha = v0.color0 >> 24; + if (alpha != 0) + state->flags |= RasterizerStateFlags::VERTEX_ALPHA_NON_ZERO; + if (alpha != 0xFF) + state->flags |= RasterizerStateFlags::VERTEX_ALPHA_NON_FULL; + } +} + +void CalculateRasterStateFlags(RasterizerState *state, const VertexData &v0) { + CalculateRasterStateFlags(state, v0, true); +} + +void CalculateRasterStateFlags(RasterizerState *state, const VertexData &v0, const VertexData &v1, bool forceFlat) { + CalculateRasterStateFlags(state, v0, !forceFlat && state->shadeGouraud); + CalculateRasterStateFlags(state, v1, true); +} + +void CalculateRasterStateFlags(RasterizerState *state, const VertexData &v0, const VertexData &v1, const VertexData &v2) { + CalculateRasterStateFlags(state, v0, state->shadeGouraud); + CalculateRasterStateFlags(state, v1, state->shadeGouraud); + CalculateRasterStateFlags(state, v2, true); +} + RasterizerState OptimizeFlatRasterizerState(const RasterizerState &origState, const VertexData &v1) { uint8_t alpha = v1.color0 >> 24; RasterizerState state = origState; diff --git a/GPU/Software/Rasterizer.h b/GPU/Software/Rasterizer.h index 6ae7122ed3..f933d8ae8e 100644 --- a/GPU/Software/Rasterizer.h +++ b/GPU/Software/Rasterizer.h @@ -33,6 +33,16 @@ struct BinCoords; namespace Rasterizer { +enum class RasterizerStateFlags { + NONE = 0, + VERTEX_NON_FULL_WHITE = 0x0001, + VERTEX_ALPHA_NON_ZERO = 0x0002, + VERTEX_ALPHA_NON_FULL = 0x0004, + + INVALID = 0x7FFFFFFF, +}; +ENUM_CLASS_BITOPS(RasterizerStateFlags); + struct RasterizerState { PixelFuncID pixelID; SamplerID samplerID; @@ -43,6 +53,7 @@ struct RasterizerState { uint16_t texbufw[8]{}; const u8 *texptr[8]{}; float textureLodSlope; + RasterizerStateFlags flags = RasterizerStateFlags::NONE; struct { uint8_t maxTexLevel : 3; @@ -68,6 +79,9 @@ struct RasterizerState { }; void ComputeRasterizerState(RasterizerState *state, std::function flushForCompile); +void CalculateRasterStateFlags(RasterizerState *state, const VertexData &v0); +void CalculateRasterStateFlags(RasterizerState *state, const VertexData &v0, const VertexData &v1, bool forceFlat); +void CalculateRasterStateFlags(RasterizerState *state, const VertexData &v0, const VertexData &v1, const VertexData &v2); // Draws a triangle if its vertices are specified in counter-clockwise order void DrawTriangle(const VertexData &v0, const VertexData &v1, const VertexData &v2, const BinCoords &range, const RasterizerState &state);