Merge pull request #8284 from stenzek/logic-op-hack

RenderState: Approximate logic op with blending if unsupported
This commit is contained in:
Connor McLaughlin 2019-08-04 14:39:38 +10:00 committed by GitHub
commit 7de6b57c13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 0 deletions

View File

@ -167,6 +167,42 @@ void BlendingState::Generate(const BPMemory& bp)
}
}
void BlendingState::ApproximateLogicOpWithBlending()
{
// Any of these which use SRC as srcFactor or DST as dstFactor won't be correct.
// This is because the two are aliased to one another (see the enum).
struct LogicOpApproximation
{
bool subtract;
BlendMode::BlendFactor srcfactor;
BlendMode::BlendFactor dstfactor;
};
static constexpr std::array<LogicOpApproximation, 16> approximations = {{
{false, BlendMode::ZERO, BlendMode::ZERO}, // CLEAR
{false, BlendMode::DSTCLR, BlendMode::ZERO}, // AND
{true, BlendMode::ONE, BlendMode::INVSRCCLR}, // AND_REVERSE
{false, BlendMode::ONE, BlendMode::ZERO}, // COPY
{true, BlendMode::DSTCLR, BlendMode::ONE}, // AND_INVERTED
{false, BlendMode::ZERO, BlendMode::ONE}, // NOOP
{false, BlendMode::INVDSTCLR, BlendMode::INVSRCCLR}, // XOR
{false, BlendMode::INVDSTCLR, BlendMode::ONE}, // OR
{false, BlendMode::INVSRCCLR, BlendMode::INVDSTCLR}, // NOR
{false, BlendMode::INVSRCCLR, BlendMode::ZERO}, // EQUIV
{false, BlendMode::INVDSTCLR, BlendMode::INVDSTCLR}, // INVERT
{false, BlendMode::ONE, BlendMode::INVDSTALPHA}, // OR_REVERSE
{false, BlendMode::INVSRCCLR, BlendMode::INVSRCCLR}, // COPY_INVERTED
{false, BlendMode::INVSRCCLR, BlendMode::ONE}, // OR_INVERTED
{false, BlendMode::INVDSTCLR, BlendMode::INVSRCCLR}, // NAND
{false, BlendMode::ONE, BlendMode::ONE}, // SET
}};
logicopenable = false;
blendenable = true;
subtract = approximations[logicmode].subtract;
srcfactor = approximations[logicmode].srcfactor;
dstfactor = approximations[logicmode].dstfactor;
}
BlendingState& BlendingState::operator=(const BlendingState& rhs)
{
hex = rhs.hex;

View File

@ -68,6 +68,10 @@ union BlendingState
{
void Generate(const BPMemory& bp);
// HACK: Replaces logical operations with blend operations.
// Will not be bit-correct, and in some cases not even remotely in the same ballpark.
void ApproximateLogicOpWithBlending();
BlendingState& operator=(const BlendingState& rhs);
bool operator==(const BlendingState& rhs) const { return hex == rhs.hex; }

View File

@ -558,6 +558,13 @@ AbstractPipelineConfig ShaderCache::GetGXPipelineConfig(
config.depth_state = depth_state;
config.blending_state = blending_state;
config.framebuffer_state = g_framebuffer_manager->GetEFBFramebufferState();
if (config.blending_state.logicopenable && !g_ActiveConfig.backend_info.bSupportsLogicOp)
{
WARN_LOG(VIDEO, "Approximating logic op with blending, this will produce incorrect rendering.");
config.blending_state.ApproximateLogicOpWithBlending();
}
return config;
}