Files
issn_pc/tests/test_blend_rewrite.cpp
Felipe Prado 9c88add1e6 Fix(GPU): corrigido o blend MIN/MAX com escala do God of War III
- Adicionada regra de reescrita do blend MIN/MAX com escala (vk_blend_rewrite.h)
- Adicionado segundo desenho que eleva o destino ao quadrado, igual ao PS4
- Removida a emulação antiga que elevava só a saída do shader
- Adicionada variável GOW3_SQUARE_PASS=0 para desligar o segundo desenho
- Adicionado teste blend-rewrite-test
2026-10-08 21:46:23 -03:00

56 lines
2.5 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
// GNM scaled MIN/MAX blend rewrite (vk_blend_rewrite.h). No game, Vulkan device or window required.
#include <cassert>
#include <cstdio>
#include "video_core/renderer_vulkan/vk_blend_rewrite.h"
using namespace Vulkan;
using F = AmdGpu::BlendControl::BlendFactor;
using Fn = AmdGpu::BlendControl::BlendFunc;
using Nf = AmdGpu::NumberFormat;
static BlendRewriteResult Rewrite(BlendEquation& eq, Nf format = Nf::Unorm,
BlendChannel channel = BlendChannel::Color) {
return RewriteScaledMinMaxBlend(eq, format, channel);
}
int main() {
// Not MIN/MAX, or MIN/MAX with unit factors: untouched.
{
BlendEquation eq{F::SrcAlpha, Fn::Add, F::OneMinusSrcAlpha};
assert(Rewrite(eq) == BlendRewriteResult::Native);
assert(eq.src_factor == F::SrcAlpha && eq.function == Fn::Add);
BlendEquation mm{F::One, Fn::Min, F::One};
assert(Rewrite(mm) == BlendRewriteResult::Native && mm.function == Fn::Min);
}
// MIN/MAX(s*s, d*d): native operation, squared by a second draw (God of War III shadows).
{
BlendEquation eq{F::SrcColor, Fn::Min, F::DstColor};
assert(Rewrite(eq) == BlendRewriteResult::Squared && eq.function == Fn::Min);
BlendEquation alpha{F::SrcAlpha, Fn::Max, F::DstAlpha};
assert(Rewrite(alpha, Nf::Srgb, BlendChannel::Alpha) == BlendRewriteResult::Squared);
// The color channel only squares through color factors.
BlendEquation color{F::SrcAlpha, Fn::Max, F::DstAlpha};
assert(Rewrite(color) == BlendRewriteResult::Unsupported);
}
// A zero factor: exact ADD. MIN(x, 0) = 0 and MAX(x, 0) = x on unsigned normalized targets.
{
BlendEquation min{F::One, Fn::Min, F::Zero};
assert(Rewrite(min) == BlendRewriteResult::Exact);
assert(min.function == Fn::Add && min.src_factor == F::Zero && min.dst_factor == F::Zero);
BlendEquation max{F::Zero, Fn::Max, F::One};
assert(Rewrite(max) == BlendRewriteResult::Exact);
assert(max.function == Fn::Add && max.src_factor == F::Zero && max.dst_factor == F::One);
}
// Signed or float targets cannot use those identities.
{
BlendEquation eq{F::SrcColor, Fn::Min, F::DstColor};
assert(Rewrite(eq, Nf::Float) == BlendRewriteResult::Unsupported);
BlendEquation other{F::SrcAlpha, Fn::Min, F::OneMinusSrcAlpha};
assert(Rewrite(other) == BlendRewriteResult::Unsupported);
}
std::puts("blend-rewrite-test: OK");
return 0;
}