Skip to content
Permalink
Browse files

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

RenderState: Approximate logic op with blending if unsupported
  • Loading branch information...
stenzek committed Aug 4, 2019
2 parents c829351 + f6f9dc0 commit 7de6b57c13235a56ddda024ae46f76e88170522f
@@ -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;
@@ -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; }
@@ -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;
}

0 comments on commit 7de6b57

Please sign in to comment.
You can’t perform that action at this time.