mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
gpu: fix separate alpha blending on swizzled render targets
Co-authored-by: Çağatay Güçlü <33038942+defektu@users.noreply.github.com>
This commit is contained in:
@@ -39,6 +39,16 @@ namespace Libs::Graphics {
|
||||
|
||||
namespace {
|
||||
|
||||
uint8_t RemapSourceAlphaFactor(uint8_t factor) {
|
||||
switch (static_cast<Prospero::BlendFactor>(factor)) {
|
||||
case Prospero::BlendFactor::kSrcAlpha:
|
||||
return static_cast<uint8_t>(Prospero::BlendFactor::kSrc1Alpha);
|
||||
case Prospero::BlendFactor::kOneMinusSrcAlpha:
|
||||
return static_cast<uint8_t>(Prospero::BlendFactor::kOneMinusSrc1Alpha);
|
||||
default: return factor;
|
||||
}
|
||||
}
|
||||
|
||||
vk::PolygonMode ResolvePolygonMode(const HW::ModeControl& mode, bool cull_front, bool cull_back) {
|
||||
// CxPrimitiveSetup::PolygonMode disables both per-face modes when it is zero.
|
||||
if (mode.poly_mode == 0) {
|
||||
@@ -619,14 +629,21 @@ PipelineCache::GraphicsPrograms PipelineCache::GetGraphicsPrograms(
|
||||
pixel_info.target_output_mode[0] != 0 && pixel_info.target_output_mode[0] != 7 &&
|
||||
std::all_of(std::begin(pixel_info.target_output_mode) + 1,
|
||||
std::end(pixel_info.target_output_mode),
|
||||
[](uint8_t mode) { return mode == 0; }) &&
|
||||
ClassifyBlendMapping(blend, pixel_info.target_export_mapping[0]) ==
|
||||
BlendMappingSupport::SourceAlpha) {
|
||||
// Preserve logical alpha when the export mapping moves it.
|
||||
pixel_info.alpha_blend_source_remap = true;
|
||||
pixel_info.dual_source_blending = true;
|
||||
pixel_info.target_output_mode[1] = pixel_info.target_output_mode[0];
|
||||
pixel_info.target_export_mapping[1] = {};
|
||||
[](uint8_t mode) { return mode == 0; })) {
|
||||
switch (ClassifyBlendMapping(blend, pixel_info.target_export_mapping[0])) {
|
||||
case BlendMappingSupport::SourceAlpha:
|
||||
pixel_info.alpha_blend_source = ShaderAlphaBlendSource::SourceAlpha;
|
||||
break;
|
||||
case BlendMappingSupport::SourceAlphaOne:
|
||||
pixel_info.alpha_blend_source = ShaderAlphaBlendSource::SourceAlphaOne;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (pixel_info.alpha_blend_source != ShaderAlphaBlendSource::None) {
|
||||
pixel_info.dual_source_blending = true;
|
||||
pixel_info.target_output_mode[1] = pixel_info.target_output_mode[0];
|
||||
pixel_info.target_export_mapping[1] = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
if (context.GetClipControl().clip_disable) {
|
||||
@@ -729,10 +746,12 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
}
|
||||
const auto& rt = ctx.GetRenderTarget(colors[i].target_slot);
|
||||
const auto& bc = ctx.GetBlendControl(colors[i].target_slot);
|
||||
const bool alpha_remap =
|
||||
slot == 0 && ps_input_info != nullptr && ps_input_info->alpha_blend_source_remap;
|
||||
auto alpha_source = ShaderAlphaBlendSource::None;
|
||||
if (slot == 0 && ps_input_info != nullptr) {
|
||||
alpha_source = ps_input_info->alpha_blend_source;
|
||||
}
|
||||
static_params.blend_enable[slot] = bc.enable && !rt.info.blend_bypass;
|
||||
if (static_params.blend_enable[slot] && !alpha_remap &&
|
||||
if (static_params.blend_enable[slot] && alpha_source == ShaderAlphaBlendSource::None &&
|
||||
ClassifyBlendMapping(bc, colors[i].export_mapping) != BlendMappingSupport::Direct) {
|
||||
static_params.blend_enable[slot] = false;
|
||||
static std::atomic_bool warned = false;
|
||||
@@ -744,18 +763,34 @@ PipelineCache::Pipeline& PipelineCache::GetGraphicsPipeline(
|
||||
bc.alpha_srcblend, bc.alpha_destblend, bc.separate_alpha_blend ? 1 : 0));
|
||||
}
|
||||
}
|
||||
if (alpha_remap) {
|
||||
static_params.blend_alpha_source_remap = true;
|
||||
}
|
||||
if (static_params.blend_enable[slot]) {
|
||||
static_params.color_srcblend[slot] = bc.color_srcblend;
|
||||
static_params.color_comb_fcn[slot] = bc.color_comb_fcn;
|
||||
static_params.color_destblend[slot] = bc.color_destblend;
|
||||
static_params.separate_alpha_blend[slot] = bc.separate_alpha_blend;
|
||||
if (bc.separate_alpha_blend) {
|
||||
static_params.alpha_srcblend[slot] = bc.alpha_srcblend;
|
||||
static_params.alpha_comb_fcn[slot] = bc.alpha_comb_fcn;
|
||||
static_params.alpha_destblend[slot] = bc.alpha_destblend;
|
||||
auto blend = bc;
|
||||
switch (alpha_source) {
|
||||
case ShaderAlphaBlendSource::SourceAlpha:
|
||||
blend.color_srcblend = RemapSourceAlphaFactor(blend.color_srcblend);
|
||||
blend.color_destblend = RemapSourceAlphaFactor(blend.color_destblend);
|
||||
if (blend.separate_alpha_blend) {
|
||||
blend.alpha_srcblend = RemapSourceAlphaFactor(blend.alpha_srcblend);
|
||||
blend.alpha_destblend = RemapSourceAlphaFactor(blend.alpha_destblend);
|
||||
}
|
||||
break;
|
||||
case ShaderAlphaBlendSource::SourceAlphaOne:
|
||||
// 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 =
|
||||
static_cast<uint8_t>(Prospero::BlendFactor::kOneMinusSrc1Alpha);
|
||||
blend.separate_alpha_blend = false;
|
||||
break;
|
||||
case ShaderAlphaBlendSource::None: break;
|
||||
}
|
||||
static_params.color_srcblend[slot] = blend.color_srcblend;
|
||||
static_params.color_comb_fcn[slot] = blend.color_comb_fcn;
|
||||
static_params.color_destblend[slot] = blend.color_destblend;
|
||||
static_params.separate_alpha_blend[slot] = blend.separate_alpha_blend;
|
||||
if (blend.separate_alpha_blend) {
|
||||
static_params.alpha_srcblend[slot] = blend.alpha_srcblend;
|
||||
static_params.alpha_comb_fcn[slot] = blend.alpha_comb_fcn;
|
||||
static_params.alpha_destblend[slot] = blend.alpha_destblend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user