mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-27 16:02:37 +00:00
gpu: fix zero-source alpha blending on swizzled targets
Co-authored-by: Çağatay Güçlü <33038942+defektu@users.noreply.github.com>
This commit is contained in:
1 parent
8274e517b2
commit
94e7d239dd
7 files changed
+35
-10
No files matched your search
@@ -32,12 +32,15 @@ BlendMappingSupport ClassifyBlendMapping(const HW::BlendControl&
|
||||
}
|
||||
if (blend.separate_alpha_blend &&
|
||||
blend.color_srcblend == static_cast<uint8_t>(Prospero::BlendFactor::kSrcAlpha) &&
|
||||
blend.alpha_srcblend == static_cast<uint8_t>(Prospero::BlendFactor::kOne) &&
|
||||
blend.color_destblend == static_cast<uint8_t>(Prospero::BlendFactor::kOneMinusSrcAlpha) &&
|
||||
blend.alpha_destblend == blend.color_destblend &&
|
||||
blend.color_comb_fcn == static_cast<uint8_t>(Prospero::BlendOp::kAdd) &&
|
||||
blend.alpha_comb_fcn == blend.color_comb_fcn) {
|
||||
return BlendMappingSupport::SourceAlphaOne;
|
||||
switch (static_cast<Prospero::BlendFactor>(blend.alpha_srcblend)) {
|
||||
case Prospero::BlendFactor::kZero: return BlendMappingSupport::SourceAlphaZero;
|
||||
case Prospero::BlendFactor::kOne: return BlendMappingSupport::SourceAlphaOne;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
// Moving alpha requires the same equation for all channels.
|
||||
if (blend.separate_alpha_blend && (blend.alpha_srcblend != blend.color_srcblend ||
|
||||
|
||||
@@ -16,6 +16,7 @@ enum class BlendMappingSupport {
|
||||
Direct,
|
||||
SourceAlpha, // Requires logical alpha in the second blend source.
|
||||
SourceAlphaOne, // Source alpha for RGB, one for alpha, with a shared destination equation.
|
||||
SourceAlphaZero, // Source alpha for RGB, zero for alpha, with a shared destination equation.
|
||||
Unsupported,
|
||||
};
|
||||
|
||||
|
||||
@@ -640,6 +640,9 @@ PipelineCache::GraphicsPrograms PipelineCache::GetGraphicsPrograms(
|
||||
case BlendMappingSupport::SourceAlphaOne:
|
||||
pixel_info.alpha_blend_source = ShaderAlphaBlendSource::SourceAlphaOne;
|
||||
break;
|
||||
case BlendMappingSupport::SourceAlphaZero:
|
||||
pixel_info.alpha_blend_source = ShaderAlphaBlendSource::SourceAlphaZero;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (pixel_info.alpha_blend_source != ShaderAlphaBlendSource::None) {
|
||||
@@ -764,6 +767,7 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
blend.separate_alpha_blend = false;
|
||||
break;
|
||||
case ShaderAlphaBlendSource::SourceAlphaOne:
|
||||
case ShaderAlphaBlendSource::SourceAlphaZero:
|
||||
// The second source carries the mapped source factor; its alpha stays logical Sa.
|
||||
blend.color_srcblend = static_cast<uint8_t>(Prospero::BlendFactor::kSrc1Color);
|
||||
blend.color_destblend =
|
||||
|
||||
@@ -512,14 +512,23 @@ void EmitSetAttribute(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
auto alpha = state.builder.AllocateId();
|
||||
state.builder.AddFunction(spv::OpVectorShuffle, vector_type, alpha, value, value,
|
||||
3u, 3u, 3u, 3u);
|
||||
if (state.input_info.pixel->alpha_blend_source ==
|
||||
ShaderAlphaBlendSource::SourceAlphaOne) {
|
||||
uint32_t alpha_factor = 0;
|
||||
switch (state.input_info.pixel->alpha_blend_source) {
|
||||
case ShaderAlphaBlendSource::SourceAlphaOne:
|
||||
alpha_factor = ConstantF32Value(state, 1.0f);
|
||||
break;
|
||||
case ShaderAlphaBlendSource::SourceAlphaZero:
|
||||
alpha_factor = ConstantF32Value(state, 0.0f);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (alpha_factor != 0) {
|
||||
const auto mapping = state.input_info.pixel->target_export_mapping[0];
|
||||
for (uint32_t component = 0; component < 4; component++) {
|
||||
if (mapping.Map(component) != 3u) continue;
|
||||
const auto factors = state.builder.AllocateId();
|
||||
state.builder.AddFunction(spv::OpCompositeInsert, vector_type, factors,
|
||||
ConstantF32Value(state, 1.0f), alpha, component);
|
||||
alpha_factor, alpha, component);
|
||||
alpha = factors;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ struct ShaderComputeInputInfo: ShaderWorkgroupInputInfo {
|
||||
ShaderStageRuntime stage;
|
||||
};
|
||||
|
||||
enum class ShaderAlphaBlendSource : uint8_t { None, SourceAlpha, SourceAlphaOne };
|
||||
enum class ShaderAlphaBlendSource : uint8_t { None, SourceAlpha, SourceAlphaOne, SourceAlphaZero };
|
||||
|
||||
struct ShaderPixelInputInfo {
|
||||
uint32_t interpolator_settings[32] = {0};
|
||||
|
||||
@@ -15830,7 +15830,7 @@ public:
|
||||
"wave32 and wave64 pixel programs shared a cache key");
|
||||
|
||||
// Reversed RGBA targets must use logical Sa for RGB, with a separate
|
||||
// unit source factor when alpha accumulates as Sa + Da * (1 - Sa).
|
||||
// zero or unit source factor for separate alpha attenuation or accumulation.
|
||||
static const auto blend_pixel = [] {
|
||||
std::vector<u32> code;
|
||||
constexpr std::array<float, 4> source{0.8f, 0.6f, 0.4f, 0.5f};
|
||||
@@ -15871,7 +15871,8 @@ public:
|
||||
for (const auto test : {
|
||||
AlphaBlendCase{false, Prospero::BlendFactor::kOne, ShaderAlphaBlendSource::SourceAlpha, 0.4f},
|
||||
AlphaBlendCase{true, Prospero::BlendFactor::kSrcAlpha, ShaderAlphaBlendSource::SourceAlpha, 0.4f},
|
||||
AlphaBlendCase{true, Prospero::BlendFactor::kOne, ShaderAlphaBlendSource::SourceAlphaOne, 0.65f}}) {
|
||||
AlphaBlendCase{true, Prospero::BlendFactor::kOne, ShaderAlphaBlendSource::SourceAlphaOne, 0.65f},
|
||||
AlphaBlendCase{true, Prospero::BlendFactor::kZero, ShaderAlphaBlendSource::SourceAlphaZero, 0.15f}}) {
|
||||
alpha_blend.separate_alpha_blend = test.separate;
|
||||
alpha_blend.alpha_srcblend = static_cast<uint8_t>(test.alpha_source);
|
||||
registers.SetBlendControl(0, alpha_blend);
|
||||
|
||||
@@ -12906,6 +12906,9 @@ void TestBlendMappingClassification() {
|
||||
static_cast<uint8_t>(Factor::kOneMinusSrcAlpha);
|
||||
Check(classify(Prospero::ColorMappingAbgr) == Support::SourceAlphaOne,
|
||||
"separate alpha accumulation did not preserve its unit source factor");
|
||||
blend.alpha_srcblend = static_cast<uint8_t>(Factor::kZero);
|
||||
Check(classify(Prospero::ColorMappingAbgr) == Support::SourceAlphaZero,
|
||||
"separate alpha attenuation did not preserve its zero source factor");
|
||||
blend.alpha_srcblend = blend.color_srcblend;
|
||||
Check(classify(Prospero::ColorMappingAbgr) == Support::SourceAlpha,
|
||||
"equal separate alpha equations did not reuse the broadcast alpha mode");
|
||||
@@ -12916,7 +12919,7 @@ void TestBlendMappingClassification() {
|
||||
switch (changed) {
|
||||
case 0: blend.color_srcblend = static_cast<uint8_t>(Factor::kZero); break;
|
||||
case 1: blend.color_destblend = static_cast<uint8_t>(Factor::kOne); break;
|
||||
case 2: blend.alpha_srcblend = static_cast<uint8_t>(Factor::kZero); break;
|
||||
case 2: blend.alpha_srcblend = static_cast<uint8_t>(Factor::kDstAlpha); break;
|
||||
case 3: blend.alpha_destblend = static_cast<uint8_t>(Factor::kOne); break;
|
||||
case 4: blend.color_comb_fcn = static_cast<uint8_t>(Prospero::BlendOp::kSubtract); break;
|
||||
case 5: blend.alpha_comb_fcn = static_cast<uint8_t>(Prospero::BlendOp::kSubtract); break;
|
||||
@@ -12937,9 +12940,13 @@ void TestLogicalAlphaBlendExport() {
|
||||
const auto remapped_key = MakeStageStaticKey(pixel);
|
||||
pixel.alpha_blend_source = ShaderAlphaBlendSource::SourceAlphaOne;
|
||||
const auto separate_key = MakeStageStaticKey(pixel);
|
||||
pixel.alpha_blend_source = ShaderAlphaBlendSource::SourceAlphaZero;
|
||||
const auto zero_key = MakeStageStaticKey(pixel);
|
||||
Check(ordinary_key != guest_key && guest_key != remapped_key &&
|
||||
ordinary_key != remapped_key && separate_key != ordinary_key &&
|
||||
separate_key != guest_key && separate_key != remapped_key,
|
||||
separate_key != guest_key && separate_key != remapped_key &&
|
||||
zero_key != ordinary_key && zero_key != guest_key &&
|
||||
zero_key != remapped_key && zero_key != separate_key,
|
||||
"ordinary, guest dual-source, and logical-alpha modes share a cache key");
|
||||
|
||||
auto options = MakeCompileOptions(ShaderType::Pixel);
|
||||
|
||||
Reference in new issue
Block a user