mirror of https://github.com/PCSX2/pcsx2.git
GS: Make factors part of blend state
Instead of using the blend map indices.
This commit is contained in:
parent
19d310475b
commit
6b32e00097
|
@ -498,18 +498,9 @@ GSAdapter::GSAdapter(const DXGI_ADAPTER_DESC1& desc_dxgi)
|
|||
// TODO
|
||||
#endif
|
||||
|
||||
HWBlend GSDevice::GetBlend(size_t index, bool replace_dual_src)
|
||||
{
|
||||
HWBlend blend = m_blendMap[index];
|
||||
blend.op = ConvertBlendEnum(blend.op);
|
||||
blend.src = ConvertBlendEnum(replace_dual_src ? m_replaceDualSrcBlendMap[blend.src] : blend.src);
|
||||
blend.dst = ConvertBlendEnum(replace_dual_src ? m_replaceDualSrcBlendMap[blend.dst] : blend.dst);
|
||||
return blend;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
const std::array<u16, 16> GSDevice::m_replaceDualSrcBlendMap =
|
||||
const std::array<u8, 16> GSDevice::m_replaceDualSrcBlendMap =
|
||||
{{
|
||||
SRC_COLOR, // SRC_COLOR
|
||||
INV_SRC_COLOR, // INV_SRC_COLOR
|
||||
|
@ -529,7 +520,7 @@ const std::array<u16, 16> GSDevice::m_replaceDualSrcBlendMap =
|
|||
CONST_ZERO // CONST_ZERO
|
||||
}};
|
||||
|
||||
const std::array<HWBlend, 3*3*3*3 + 1> GSDevice::m_blendMap =
|
||||
const std::array<HWBlend, 3*3*3*3> GSDevice::m_blendMap =
|
||||
{{
|
||||
{ BLEND_NO_REC , OP_ADD , CONST_ONE , CONST_ZERO} , // 0000: (Cs - Cs)*As + Cs ==> Cs
|
||||
{ BLEND_CD , OP_ADD , CONST_ZERO , CONST_ONE} , // 0001: (Cs - Cs)*As + Cd ==> Cd
|
||||
|
@ -612,5 +603,4 @@ const std::array<HWBlend, 3*3*3*3 + 1> GSDevice::m_blendMap =
|
|||
{ BLEND_NO_REC , OP_ADD , CONST_ONE , CONST_ZERO} , // 2220: (0 - 0)*F + Cs ==> Cs
|
||||
{ BLEND_CD , OP_ADD , CONST_ZERO , CONST_ONE} , // 2221: (0 - 0)*F + Cd ==> Cd
|
||||
{ BLEND_NO_REC , OP_ADD , CONST_ZERO , CONST_ZERO} , // 2222: (0 - 0)*F + 0 ==> 0
|
||||
{ 0 , OP_ADD , SRC_ALPHA , INV_SRC_ALPHA} , // extra for merge operation
|
||||
}};
|
||||
|
|
|
@ -128,12 +128,14 @@ enum HWBlendFlags
|
|||
BLEND_C_CLR3 = 0x800, // Multiply Cs by (255/128) to compensate for wrong Ad/255 value, should be Ad/128
|
||||
BLEND_NO_REC = 0x1000, // Doesn't require sampling of the RT as a texture
|
||||
BLEND_ACCU = 0x2000, // Allow to use a mix of SW and HW blending to keep the best of the 2 worlds
|
||||
BLEND_DSB = 0x4000, // Blend equation uses dual-source outputs (SRC_ALPHA1/INV_SRC_ALPHA1).
|
||||
};
|
||||
|
||||
// Determines the HW blend function for DX11/OGL
|
||||
struct HWBlend
|
||||
{
|
||||
u16 flags, op, src, dst;
|
||||
u16 flags;
|
||||
u8 op, src, dst;
|
||||
};
|
||||
|
||||
struct alignas(16) GSHWDrawConfig
|
||||
|
@ -483,25 +485,25 @@ struct alignas(16) GSHWDrawConfig
|
|||
{
|
||||
struct
|
||||
{
|
||||
u8 index;
|
||||
u8 factor;
|
||||
bool is_constant : 1;
|
||||
bool is_accumulation : 1;
|
||||
bool is_mixed_hw_sw : 1;
|
||||
bool replace_dual_src: 1;
|
||||
u8 enable : 1;
|
||||
u8 constant_enable : 1;
|
||||
u8 op : 6;
|
||||
u8 src_factor;
|
||||
u8 dst_factor;
|
||||
u8 constant;
|
||||
};
|
||||
u32 key;
|
||||
};
|
||||
BlendState(): key(0) {}
|
||||
BlendState(u8 index, u8 factor, bool is_constant, bool is_accumulation, bool is_mixed_hw_sw, bool replace_dual_src)
|
||||
BlendState(bool enable_, u8 src_factor_, u8 dst_factor_, u8 op_, bool constant_enable_, u8 constant_)
|
||||
: key(0)
|
||||
{
|
||||
this->index = index;
|
||||
this->factor = factor;
|
||||
this->is_constant = is_constant;
|
||||
this->is_accumulation = is_accumulation;
|
||||
this->is_mixed_hw_sw = is_mixed_hw_sw;
|
||||
this->replace_dual_src = replace_dual_src;
|
||||
enable = enable_;
|
||||
constant_enable = constant_enable_;
|
||||
src_factor = src_factor_;
|
||||
dst_factor = dst_factor_;
|
||||
op = op_;
|
||||
constant = constant_;
|
||||
}
|
||||
};
|
||||
enum class DestinationAlphaMode : u8
|
||||
|
@ -563,6 +565,7 @@ struct alignas(16) GSHWDrawConfig
|
|||
class GSDevice : public GSAlignedClass<32>
|
||||
{
|
||||
public:
|
||||
// clang-format off
|
||||
struct FeatureSupport
|
||||
{
|
||||
bool broken_point_sampler : 1; ///< Issue with AMD cards, see tfx shader for details
|
||||
|
@ -582,28 +585,30 @@ public:
|
|||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
private:
|
||||
FastList<GSTexture*> m_pool;
|
||||
static const std::array<HWBlend, 3*3*3*3 + 1> m_blendMap;
|
||||
static const std::array<u16, 16> m_replaceDualSrcBlendMap;
|
||||
|
||||
protected:
|
||||
enum : u16
|
||||
// clang-format off
|
||||
enum : u8
|
||||
{
|
||||
// HW blend factors
|
||||
SRC_COLOR, INV_SRC_COLOR, DST_COLOR, INV_DST_COLOR,
|
||||
SRC1_COLOR, INV_SRC1_COLOR, SRC_ALPHA, INV_SRC_ALPHA,
|
||||
DST_ALPHA, INV_DST_ALPHA, SRC1_ALPHA, INV_SRC1_ALPHA,
|
||||
CONST_COLOR, INV_CONST_COLOR, CONST_ONE, CONST_ZERO,
|
||||
|
||||
SRC_COLOR, INV_SRC_COLOR, DST_COLOR, INV_DST_COLOR,
|
||||
SRC1_COLOR, INV_SRC1_COLOR, SRC_ALPHA, INV_SRC_ALPHA,
|
||||
DST_ALPHA, INV_DST_ALPHA, SRC1_ALPHA, INV_SRC1_ALPHA,
|
||||
CONST_COLOR, INV_CONST_COLOR, CONST_ONE, CONST_ZERO,
|
||||
};
|
||||
enum : u8
|
||||
{
|
||||
// HW blend operations
|
||||
OP_ADD, OP_SUBTRACT, OP_REV_SUBTRACT
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static const int m_NO_BLEND = 0;
|
||||
static const int m_MERGE_BLEND = m_blendMap.size() - 1;
|
||||
private:
|
||||
FastList<GSTexture*> m_pool;
|
||||
static const std::array<HWBlend, 3*3*3*3> m_blendMap;
|
||||
static const std::array<u8, 16> m_replaceDualSrcBlendMap;
|
||||
|
||||
protected:
|
||||
static constexpr u32 MAX_POOLED_TEXTURES = 300;
|
||||
|
||||
HostDisplay* m_display;
|
||||
|
@ -632,7 +637,6 @@ protected:
|
|||
virtual void DoFXAA(GSTexture* sTex, GSTexture* dTex) {}
|
||||
virtual void DoShadeBoost(GSTexture* sTex, GSTexture* dTex) {}
|
||||
virtual void DoExternalFX(GSTexture* sTex, GSTexture* dTex) {}
|
||||
virtual u16 ConvertBlendEnum(u16 generic) = 0; // Convert blend factors/ops from the generic enum to DX11/OGl specific.
|
||||
|
||||
public:
|
||||
GSDevice();
|
||||
|
@ -641,12 +645,6 @@ public:
|
|||
__fi HostDisplay* GetDisplay() const { return m_display; }
|
||||
__fi unsigned int GetFrameNumber() const { return m_frame; }
|
||||
|
||||
__fi static constexpr bool IsDualSourceBlendFactor(u16 factor)
|
||||
{
|
||||
return (factor == GSDevice::SRC1_ALPHA || factor == GSDevice::INV_SRC1_ALPHA
|
||||
/*|| factor == GSDevice::SRC1_COLOR || factor == GSDevice::INV_SRC1_COLOR*/); // not used
|
||||
}
|
||||
|
||||
void Recycle(GSTexture* t);
|
||||
|
||||
enum
|
||||
|
@ -737,11 +735,34 @@ public:
|
|||
|
||||
virtual void PrintMemoryUsage();
|
||||
|
||||
// Convert the GS blend equations to HW specific blend factors/ops
|
||||
__fi static constexpr bool IsDualSourceBlendFactor(u8 factor)
|
||||
{
|
||||
return (factor == SRC1_ALPHA || factor == INV_SRC1_ALPHA
|
||||
/*|| factor == SRC1_COLOR || factor == INV_SRC1_COLOR*/); // not used
|
||||
}
|
||||
__fi static constexpr bool IsConstantBlendFactor(u16 factor)
|
||||
{
|
||||
return (factor == CONST_COLOR || factor == INV_CONST_COLOR);
|
||||
}
|
||||
|
||||
// Convert the GS blend equations to HW blend factors/ops
|
||||
// Index is computed as ((((A * 3 + B) * 3) + C) * 3) + D. A, B, C, D taken from ALPHA register.
|
||||
HWBlend GetBlend(size_t index, bool replace_dual_src);
|
||||
__fi HWBlend GetUnconvertedBlend(size_t index) { return m_blendMap[index]; }
|
||||
__fi u16 GetBlendFlags(size_t index) const { return m_blendMap[index].flags; }
|
||||
__ri static HWBlend GetBlend(u32 index, bool replace_dual_src)
|
||||
{
|
||||
HWBlend ret = m_blendMap[index];
|
||||
if (replace_dual_src)
|
||||
{
|
||||
ret.src = m_replaceDualSrcBlendMap[ret.src];
|
||||
ret.dst = m_replaceDualSrcBlendMap[ret.dst];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
__ri static u16 GetBlendFlags(u32 index) { return m_blendMap[index].flags; }
|
||||
__fi static bool IsDualSourceBlend(u32 index)
|
||||
{
|
||||
return (IsDualSourceBlendFactor(m_blendMap[index].src) ||
|
||||
IsDualSourceBlendFactor(m_blendMap[index].dst));
|
||||
}
|
||||
};
|
||||
|
||||
struct GSAdapter
|
||||
|
|
|
@ -1251,10 +1251,14 @@ static GSDevice11::OMBlendSelector convertSel(GSHWDrawConfig::ColorMaskSelector
|
|||
{
|
||||
GSDevice11::OMBlendSelector out;
|
||||
out.wrgba = cm.wrgba;
|
||||
out.abe = blend.index != 0;
|
||||
out.blend_index = blend.index;
|
||||
out.accu_blend = blend.is_accumulation;
|
||||
out.blend_mix = blend.is_mixed_hw_sw;
|
||||
if (blend.enable)
|
||||
{
|
||||
out.blend_enable = true;
|
||||
out.blend_src_factor = blend.src_factor;
|
||||
out.blend_dst_factor = blend.dst_factor;
|
||||
out.blend_op = blend.op;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -1348,7 +1352,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
|||
PSSetShaderResource(0, rt_copy);
|
||||
}
|
||||
|
||||
SetupOM(config.depth, convertSel(config.colormask, config.blend), config.blend.factor);
|
||||
SetupOM(config.depth, convertSel(config.colormask, config.blend), config.blend.constant);
|
||||
SetupVS(config.vs, &config.cb_vs);
|
||||
SetupGS(config.gs);
|
||||
SetupPS(config.ps, &config.cb_ps, config.sampler);
|
||||
|
@ -1369,7 +1373,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
|||
SetupPS(config.alpha_second_pass.ps, nullptr, config.sampler);
|
||||
}
|
||||
|
||||
SetupOM(config.alpha_second_pass.depth, convertSel(config.alpha_second_pass.colormask, config.blend), config.blend.factor);
|
||||
SetupOM(config.alpha_second_pass.depth, convertSel(config.alpha_second_pass.colormask, config.blend), config.blend.constant);
|
||||
|
||||
DrawIndexedPrimitive();
|
||||
}
|
||||
|
@ -1388,30 +1392,3 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
|||
Recycle(hdr_rt);
|
||||
}
|
||||
}
|
||||
|
||||
u16 GSDevice11::ConvertBlendEnum(u16 generic)
|
||||
{
|
||||
switch (generic)
|
||||
{
|
||||
case SRC_COLOR: return D3D11_BLEND_SRC_COLOR;
|
||||
case INV_SRC_COLOR: return D3D11_BLEND_INV_SRC_COLOR;
|
||||
case DST_COLOR: return D3D11_BLEND_DEST_COLOR;
|
||||
case INV_DST_COLOR: return D3D11_BLEND_INV_DEST_COLOR;
|
||||
case SRC1_COLOR: return D3D11_BLEND_SRC1_COLOR;
|
||||
case INV_SRC1_COLOR: return D3D11_BLEND_INV_SRC1_COLOR;
|
||||
case SRC_ALPHA: return D3D11_BLEND_SRC_ALPHA;
|
||||
case INV_SRC_ALPHA: return D3D11_BLEND_INV_SRC_ALPHA;
|
||||
case DST_ALPHA: return D3D11_BLEND_DEST_ALPHA;
|
||||
case INV_DST_ALPHA: return D3D11_BLEND_INV_DEST_ALPHA;
|
||||
case SRC1_ALPHA: return D3D11_BLEND_SRC1_ALPHA;
|
||||
case INV_SRC1_ALPHA: return D3D11_BLEND_INV_SRC1_ALPHA;
|
||||
case CONST_COLOR: return D3D11_BLEND_BLEND_FACTOR;
|
||||
case INV_CONST_COLOR: return D3D11_BLEND_INV_BLEND_FACTOR;
|
||||
case CONST_ONE: return D3D11_BLEND_ONE;
|
||||
case CONST_ZERO: return D3D11_BLEND_ZERO;
|
||||
case OP_ADD: return D3D11_BLEND_OP_ADD;
|
||||
case OP_SUBTRACT: return D3D11_BLEND_OP_SUBTRACT;
|
||||
case OP_REV_SUBTRACT: return D3D11_BLEND_OP_REV_SUBTRACT;
|
||||
default: ASSERT(0); return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,10 +51,10 @@ public:
|
|||
u32 wb : 1;
|
||||
u32 wa : 1;
|
||||
// Alpha blending
|
||||
u32 blend_index : 7;
|
||||
u32 abe : 1;
|
||||
u32 accu_blend : 1;
|
||||
u32 blend_mix : 1;
|
||||
u32 blend_enable : 1;
|
||||
u32 blend_op : 2;
|
||||
u32 blend_src_factor : 4;
|
||||
u32 blend_dst_factor : 4;
|
||||
};
|
||||
|
||||
struct
|
||||
|
@ -66,7 +66,7 @@ public:
|
|||
u32 key;
|
||||
};
|
||||
|
||||
operator u32() { return key & 0x3fff; }
|
||||
operator u32() { return key & 0x7fff; }
|
||||
|
||||
OMBlendSelector()
|
||||
: key(0)
|
||||
|
@ -127,8 +127,6 @@ private:
|
|||
void DoShadeBoost(GSTexture* sTex, GSTexture* dTex) final;
|
||||
void DoExternalFX(GSTexture* sTex, GSTexture* dTex) final;
|
||||
|
||||
u16 ConvertBlendEnum(u16 generic) final;
|
||||
|
||||
wil::com_ptr_nothrow<ID3D11Device> m_dev;
|
||||
wil::com_ptr_nothrow<ID3D11DeviceContext> m_ctx;
|
||||
wil::com_ptr_nothrow<IDXGISwapChain1> m_swapchain;
|
||||
|
|
|
@ -280,6 +280,18 @@ void GSDevice11::ClearSamplerCache()
|
|||
m_ps_ss.clear();
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static constexpr std::array<D3D11_BLEND, 16> s_d3d11_blend_factors = { {
|
||||
D3D11_BLEND_SRC_COLOR, D3D11_BLEND_INV_SRC_COLOR, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_INV_DEST_COLOR,
|
||||
D3D11_BLEND_SRC1_COLOR, D3D11_BLEND_INV_SRC1_COLOR, D3D11_BLEND_SRC_ALPHA, D3D11_BLEND_INV_SRC_ALPHA,
|
||||
D3D11_BLEND_DEST_ALPHA, D3D11_BLEND_INV_DEST_ALPHA, D3D11_BLEND_SRC1_ALPHA, D3D11_BLEND_INV_SRC1_ALPHA,
|
||||
D3D11_BLEND_BLEND_FACTOR, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_ONE, D3D11_BLEND_ZERO
|
||||
} };
|
||||
static constexpr std::array<D3D11_BLEND_OP, 3> s_d3d11_blend_ops = { {
|
||||
D3D11_BLEND_OP_ADD, D3D11_BLEND_OP_SUBTRACT, D3D11_BLEND_OP_REV_SUBTRACT
|
||||
} };
|
||||
// clang-format on
|
||||
|
||||
void GSDevice11::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, u8 afix)
|
||||
{
|
||||
auto i = std::as_const(m_om_dss).find(dssel.key);
|
||||
|
@ -336,24 +348,15 @@ void GSDevice11::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, u8
|
|||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
|
||||
if (bsel.abe)
|
||||
if (bsel.blend_enable)
|
||||
{
|
||||
const HWBlend blend = GetBlend(bsel.blend_index, false);
|
||||
bd.RenderTarget[0].BlendEnable = TRUE;
|
||||
bd.RenderTarget[0].BlendOp = (D3D11_BLEND_OP)blend.op;
|
||||
bd.RenderTarget[0].SrcBlend = (D3D11_BLEND)blend.src;
|
||||
bd.RenderTarget[0].DestBlend = (D3D11_BLEND)blend.dst;
|
||||
bd.RenderTarget[0].BlendOp = s_d3d11_blend_ops[bsel.blend_op];
|
||||
bd.RenderTarget[0].SrcBlend = s_d3d11_blend_factors[bsel.blend_src_factor];
|
||||
bd.RenderTarget[0].DestBlend = s_d3d11_blend_factors[bsel.blend_dst_factor];
|
||||
bd.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
||||
bd.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
||||
bd.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
|
||||
|
||||
if (bsel.accu_blend)
|
||||
{
|
||||
bd.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
bd.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
|
||||
}
|
||||
else if (bsel.blend_mix)
|
||||
bd.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
|
||||
}
|
||||
|
||||
if (bsel.wr) bd.RenderTarget[0].RenderTargetWriteMask |= D3D11_COLOR_WRITE_ENABLE_RED;
|
||||
|
|
|
@ -599,7 +599,7 @@ void GSRendererNew::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
|
|||
blend_ad_alpha_masked = false;
|
||||
|
||||
u8 blend_index = u8(((m_conf.ps.blend_a * 3 + m_conf.ps.blend_b) * 3 + m_conf.ps.blend_c) * 3 + m_conf.ps.blend_d);
|
||||
const int blend_flag = g_gs_device->GetBlendFlags(blend_index);
|
||||
const int blend_flag = GSDevice::GetBlendFlags(blend_index);
|
||||
|
||||
// Re set alpha, it was modified, must be done after index calculation
|
||||
if (blend_ad_alpha_masked)
|
||||
|
@ -732,34 +732,29 @@ void GSRendererNew::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
|
|||
}
|
||||
|
||||
bool replace_dual_src = false;
|
||||
if (!features.dual_source_blend)
|
||||
if (!features.dual_source_blend && GSDevice::IsDualSourceBlend(blend_index))
|
||||
{
|
||||
const HWBlend unconverted_blend = g_gs_device->GetUnconvertedBlend(blend_index);
|
||||
if (GSDevice::IsDualSourceBlendFactor(unconverted_blend.dst) ||
|
||||
GSDevice::IsDualSourceBlendFactor(unconverted_blend.src))
|
||||
// if we don't have an alpha channel, we don't need a second pass, just output the alpha blend
|
||||
// in the single colour's alpha chnanel, and blend with it
|
||||
if (!m_conf.colormask.wa)
|
||||
{
|
||||
// if we don't have an alpha channel, we don't need a second pass, just output the alpha blend
|
||||
// in the single colour's alpha chnanel, and blend with it
|
||||
if (!m_conf.colormask.wa)
|
||||
{
|
||||
GL_INS("Outputting alpha blend in col0 because of no alpha write");
|
||||
m_conf.ps.no_ablend = true;
|
||||
replace_dual_src = true;
|
||||
}
|
||||
else if (features.framebuffer_fetch || m_conf.require_one_barrier || m_conf.require_full_barrier)
|
||||
{
|
||||
// prefer single pass sw blend (if barrier) or framebuffer fetch over dual pass alpha when supported
|
||||
sw_blending = true;
|
||||
color_dest_blend = false;
|
||||
accumulation_blend &= !features.framebuffer_fetch;
|
||||
blend_mix = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// split the draw into two
|
||||
blending_alpha_pass = true;
|
||||
replace_dual_src = true;
|
||||
}
|
||||
GL_INS("Outputting alpha blend in col0 because of no alpha write");
|
||||
m_conf.ps.no_ablend = true;
|
||||
replace_dual_src = true;
|
||||
}
|
||||
else if (features.framebuffer_fetch || m_conf.require_one_barrier || m_conf.require_full_barrier)
|
||||
{
|
||||
// prefer single pass sw blend (if barrier) or framebuffer fetch over dual pass alpha when supported
|
||||
sw_blending = true;
|
||||
color_dest_blend = false;
|
||||
accumulation_blend &= !features.framebuffer_fetch;
|
||||
blend_mix = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// split the draw into two
|
||||
blending_alpha_pass = true;
|
||||
replace_dual_src = true;
|
||||
}
|
||||
}
|
||||
else if (features.framebuffer_fetch)
|
||||
|
@ -868,6 +863,7 @@ void GSRendererNew::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
|
|||
{
|
||||
// Blend output will be Cd, disable hw/sw blending.
|
||||
m_conf.blend = {};
|
||||
m_conf.ps.no_color1 = true;
|
||||
sw_blending = false; // DATE_PRIMID
|
||||
|
||||
// Output is Cd, set rgb write to 0.
|
||||
|
@ -881,10 +877,11 @@ void GSRendererNew::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
|
|||
if (m_conf.ps.blend_c == 2)
|
||||
m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast<float>(ALPHA.FIX) / 128.0f;
|
||||
|
||||
const HWBlend blend = GSDevice::GetBlend(blend_index, replace_dual_src);
|
||||
if (accumulation_blend)
|
||||
{
|
||||
// Keep HW blending to do the addition/subtraction
|
||||
m_conf.blend = {blend_index, 0, false, true, false, replace_dual_src};
|
||||
m_conf.blend = {true, GSDevice::CONST_ONE, GSDevice::CONST_ONE, blend.op, false, 0};
|
||||
if (m_conf.ps.blend_a == 2)
|
||||
{
|
||||
// The blend unit does a reverse subtraction so it means
|
||||
|
@ -904,9 +901,13 @@ void GSRendererNew::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
|
|||
}
|
||||
else if (blend_mix)
|
||||
{
|
||||
m_conf.blend = {blend_index, ALPHA.FIX, m_conf.ps.blend_c == 2, false, true, replace_dual_src};
|
||||
// For mixed blend, the source blend is done in the shader (so we use CONST_ONE as a factor).
|
||||
m_conf.blend = {true, GSDevice::CONST_ONE, blend.dst, blend.op, m_conf.ps.blend_c == 2, ALPHA.FIX};
|
||||
m_conf.ps.blend_mix = 1;
|
||||
|
||||
// Elide DSB colour output if not used by dest.
|
||||
m_conf.ps.no_color1 |= !GSDevice::IsDualSourceBlendFactor(blend.dst);
|
||||
|
||||
if (blend_mix1)
|
||||
{
|
||||
m_conf.ps.blend_a = 0;
|
||||
|
@ -938,6 +939,7 @@ void GSRendererNew::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
|
|||
{
|
||||
// Disable HW blending
|
||||
m_conf.blend = {};
|
||||
m_conf.ps.no_color1 = true;
|
||||
replace_dual_src = false;
|
||||
blending_alpha_pass = false;
|
||||
|
||||
|
@ -1005,13 +1007,18 @@ void GSRendererNew::EmulateBlending(bool& DATE_PRIMID, bool& DATE_BARRIER, bool&
|
|||
if (m_conf.ps.dfmt == 1 && m_conf.ps.blend_c == 1)
|
||||
{
|
||||
// 24 bits doesn't have an alpha channel so use 1.0f fix factor as equivalent
|
||||
const u8 hacked_blend_index = blend_index + 3; // +3 <=> +1 on C
|
||||
m_conf.blend = {hacked_blend_index, 128, true, false, false, replace_dual_src};
|
||||
const HWBlend blend(GSDevice::GetBlend(blend_index + 3, replace_dual_src)); // +3 <=> +1 on C
|
||||
m_conf.blend = {true, blend.src, blend.dst, blend.op, true, 128};
|
||||
}
|
||||
else
|
||||
{
|
||||
m_conf.blend = {blend_index, ALPHA.FIX, m_conf.ps.blend_c == 2, false, false, replace_dual_src};
|
||||
const HWBlend blend(GSDevice::GetBlend(blend_index, replace_dual_src));
|
||||
m_conf.blend = {true, blend.src, blend.dst, blend.op, m_conf.ps.blend_c == 2, ALPHA.FIX};
|
||||
}
|
||||
|
||||
// Remove second color output when unused. Works around bugs in some drivers (e.g. Intel).
|
||||
m_conf.ps.no_color1 |= !GSDevice::IsDualSourceBlendFactor(m_conf.blend.src_factor) &&
|
||||
GSDevice::IsDualSourceBlendFactor(m_conf.blend.dst_factor);
|
||||
}
|
||||
|
||||
// DATE_PRIMID interact very badly with sw blending. DATE_PRIMID uses the primitiveID to find the primitive
|
||||
|
@ -1499,10 +1506,16 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
// Before emulateblending, dither will be used
|
||||
m_conf.ps.dither = GSConfig.Dithering > 0 && m_conf.ps.dfmt == 2 && m_env.DTHE.DTHE;
|
||||
|
||||
if (m_conf.ps.dfmt == 1)
|
||||
{
|
||||
// Disable writing of the alpha channel
|
||||
m_conf.colormask.wa = 0;
|
||||
}
|
||||
|
||||
// Blend
|
||||
|
||||
bool blending_alpha_pass = false;
|
||||
if (!IsOpaque() && rt)
|
||||
if (!IsOpaque() && rt && m_conf.colormask.wrgba != 0)
|
||||
{
|
||||
EmulateBlending(DATE_PRIMID, DATE_BARRIER, blending_alpha_pass);
|
||||
}
|
||||
|
@ -1519,19 +1532,9 @@ void GSRendererNew::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
m_conf.require_full_barrier = false;
|
||||
}
|
||||
|
||||
// Don't emit the second color output from the pixel shader when it's
|
||||
// not going to be used (no or sw blending).
|
||||
m_conf.ps.no_color1 |= (m_conf.blend.index == 0);
|
||||
|
||||
if (m_conf.ps.scanmsk & 2)
|
||||
DATE_PRIMID = false; // to have discard in the shader work correctly
|
||||
|
||||
if (m_conf.ps.dfmt == 1)
|
||||
{
|
||||
// Disable writing of the alpha channel
|
||||
m_conf.colormask.wa = 0;
|
||||
}
|
||||
|
||||
// DATE setup, no DATE_BARRIER please
|
||||
|
||||
if (!DATE)
|
||||
|
|
|
@ -1202,7 +1202,7 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
|
|||
|
||||
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GL::Program& ps, bool linear)
|
||||
{
|
||||
StretchRect(sTex, sRect, dTex, dRect, ps, m_NO_BLEND, OMColorMaskSelector(), linear);
|
||||
StretchRect(sTex, sRect, dTex, dRect, ps, false, OMColorMaskSelector(), linear);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha)
|
||||
|
@ -1214,10 +1214,10 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
|
|||
cms.wb = blue;
|
||||
cms.wa = alpha;
|
||||
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[(int)ShaderConvert::COPY], m_NO_BLEND, cms, false);
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[(int)ShaderConvert::COPY], false, cms, false);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GL::Program& ps, int bs, OMColorMaskSelector cms, bool linear)
|
||||
void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GL::Program& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear)
|
||||
{
|
||||
ASSERT(sTex);
|
||||
|
||||
|
@ -1263,7 +1263,7 @@ void GSDeviceOGL::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
|
|||
else
|
||||
OMSetDepthStencilState(m_convert.dss);
|
||||
|
||||
OMSetBlendState((u8)bs);
|
||||
OMSetBlendState(alpha_blend, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_FUNC_ADD);
|
||||
OMSetColorMaskState(cms);
|
||||
|
||||
// ************************************
|
||||
|
@ -1379,12 +1379,12 @@ void GSDeviceOGL::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
|
|||
// Blend with a constant alpha
|
||||
m_merge_obj.ps[1].Bind();
|
||||
m_merge_obj.ps[1].Uniform4fv(0, c.v);
|
||||
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[1], m_MERGE_BLEND, OMColorMaskSelector());
|
||||
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[1], true, OMColorMaskSelector());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Blend with 2 * input alpha
|
||||
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[0], m_MERGE_BLEND, OMColorMaskSelector());
|
||||
StretchRect(sTex[0], sRect[0], dTex, dRect[0], m_merge_obj.ps[0], true, OMColorMaskSelector());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1687,9 +1687,9 @@ void GSDeviceOGL::OMSetColorMaskState(OMColorMaskSelector sel)
|
|||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::OMSetBlendState(u8 blend_index, u8 blend_factor, bool is_blend_constant, bool accumulation_blend, bool blend_mix, bool replace_dual_src)
|
||||
void GSDeviceOGL::OMSetBlendState(bool enable, GLenum src_factor, GLenum dst_factor, GLenum op, bool is_constant, u8 constant)
|
||||
{
|
||||
if (blend_index)
|
||||
if (enable)
|
||||
{
|
||||
if (!GLState::blend)
|
||||
{
|
||||
|
@ -1697,35 +1697,24 @@ void GSDeviceOGL::OMSetBlendState(u8 blend_index, u8 blend_factor, bool is_blend
|
|||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (is_blend_constant && GLState::bf != blend_factor)
|
||||
if (is_constant && GLState::bf != constant)
|
||||
{
|
||||
GLState::bf = blend_factor;
|
||||
const float bf = (float)blend_factor / 128.0f;
|
||||
GLState::bf = constant;
|
||||
const float bf = (float)constant / 128.0f;
|
||||
glBlendColor(bf, bf, bf, bf);
|
||||
}
|
||||
|
||||
HWBlend b = GetBlend(blend_index, replace_dual_src);
|
||||
if (accumulation_blend)
|
||||
if (GLState::eq_RGB != op)
|
||||
{
|
||||
b.src = GL_ONE;
|
||||
b.dst = GL_ONE;
|
||||
}
|
||||
else if (blend_mix)
|
||||
{
|
||||
b.src = GL_ONE;
|
||||
GLState::eq_RGB = op;
|
||||
glBlendEquationSeparate(op, GL_FUNC_ADD);
|
||||
}
|
||||
|
||||
if (GLState::eq_RGB != b.op)
|
||||
if (GLState::f_sRGB != src_factor || GLState::f_dRGB != dst_factor)
|
||||
{
|
||||
GLState::eq_RGB = b.op;
|
||||
glBlendEquationSeparate(b.op, GL_FUNC_ADD);
|
||||
}
|
||||
|
||||
if (GLState::f_sRGB != b.src || GLState::f_dRGB != b.dst)
|
||||
{
|
||||
GLState::f_sRGB = b.src;
|
||||
GLState::f_dRGB = b.dst;
|
||||
glBlendFuncSeparate(b.src, b.dst, GL_ONE, GL_ZERO);
|
||||
GLState::f_sRGB = src_factor;
|
||||
GLState::f_dRGB = dst_factor;
|
||||
glBlendFuncSeparate(src_factor, dst_factor, GL_ONE, GL_ZERO);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1829,6 +1818,18 @@ static GSDeviceOGL::VSSelector convertSel(const GSHWDrawConfig::VSSelector sel)
|
|||
return out;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static constexpr std::array<GLenum, 16> s_gl_blend_factors = { {
|
||||
GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR,
|
||||
GL_SRC1_COLOR, GL_ONE_MINUS_SRC1_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
|
||||
GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_SRC1_ALPHA, GL_ONE_MINUS_SRC1_ALPHA,
|
||||
GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_ONE, GL_ZERO
|
||||
} };
|
||||
static constexpr std::array<GLenum, 3> s_gl_blend_ops = { {
|
||||
GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT
|
||||
} };
|
||||
// clang-format on
|
||||
|
||||
void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
||||
{
|
||||
if (!GLState::scissor.eq(config.scissor))
|
||||
|
@ -1900,7 +1901,9 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
|
|||
PSSetShaderResource(2, config.rt);
|
||||
|
||||
SetupSampler(config.sampler);
|
||||
OMSetBlendState(config.blend.index, config.blend.factor, config.blend.is_constant, config.blend.is_accumulation, config.blend.is_mixed_hw_sw, config.blend.replace_dual_src);
|
||||
OMSetBlendState(config.blend.enable, s_gl_blend_factors[config.blend.src_factor],
|
||||
s_gl_blend_factors[config.blend.dst_factor], s_gl_blend_ops[config.blend.op],
|
||||
config.blend.constant_enable, config.blend.constant);
|
||||
OMSetColorMaskState(config.colormask);
|
||||
SetupOM(config.depth);
|
||||
|
||||
|
@ -2174,33 +2177,6 @@ void GSDeviceOGL::DebugOutputToFile(GLenum gl_source, GLenum gl_type, GLuint id,
|
|||
#endif
|
||||
}
|
||||
|
||||
u16 GSDeviceOGL::ConvertBlendEnum(u16 generic)
|
||||
{
|
||||
switch (generic)
|
||||
{
|
||||
case SRC_COLOR : return GL_SRC_COLOR;
|
||||
case INV_SRC_COLOR : return GL_ONE_MINUS_SRC_COLOR;
|
||||
case DST_COLOR : return GL_DST_COLOR;
|
||||
case INV_DST_COLOR : return GL_ONE_MINUS_DST_COLOR;
|
||||
case SRC1_COLOR : return GL_SRC1_COLOR;
|
||||
case INV_SRC1_COLOR : return GL_ONE_MINUS_SRC1_COLOR;
|
||||
case SRC_ALPHA : return GL_SRC_ALPHA;
|
||||
case INV_SRC_ALPHA : return GL_ONE_MINUS_SRC_ALPHA;
|
||||
case DST_ALPHA : return GL_DST_ALPHA;
|
||||
case INV_DST_ALPHA : return GL_ONE_MINUS_DST_ALPHA;
|
||||
case SRC1_ALPHA : return GL_SRC1_ALPHA;
|
||||
case INV_SRC1_ALPHA : return GL_ONE_MINUS_SRC1_ALPHA;
|
||||
case CONST_COLOR : return GL_CONSTANT_COLOR;
|
||||
case INV_CONST_COLOR : return GL_ONE_MINUS_CONSTANT_COLOR;
|
||||
case CONST_ONE : return GL_ONE;
|
||||
case CONST_ZERO : return GL_ZERO;
|
||||
case OP_ADD : return GL_FUNC_ADD;
|
||||
case OP_SUBTRACT : return GL_FUNC_SUBTRACT;
|
||||
case OP_REV_SUBTRACT : return GL_FUNC_REVERSE_SUBTRACT;
|
||||
default : ASSERT(0); return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::PushDebugGroup(const char* fmt, ...)
|
||||
{
|
||||
#ifdef ENABLE_OGL_DEBUG
|
||||
|
|
|
@ -310,8 +310,6 @@ private:
|
|||
void OMAttachDs(GSTextureOGL* ds = NULL);
|
||||
void OMSetFBO(GLuint fbo);
|
||||
|
||||
u16 ConvertBlendEnum(u16 generic) final;
|
||||
|
||||
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds);
|
||||
|
||||
public:
|
||||
|
@ -355,7 +353,7 @@ public:
|
|||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, ShaderConvert shader = ShaderConvert::COPY, bool linear = true) final;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GL::Program& ps, bool linear = true);
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha) final;
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GL::Program& ps, int bs, OMColorMaskSelector cms, bool linear = true);
|
||||
void StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, const GL::Program& ps, bool alpha_blend, OMColorMaskSelector cms, bool linear = true);
|
||||
|
||||
void RenderHW(GSHWDrawConfig& config) final;
|
||||
void SendHWDraw(const GSHWDrawConfig& config);
|
||||
|
@ -372,7 +370,7 @@ public:
|
|||
void ClearSamplerCache() final;
|
||||
|
||||
void OMSetDepthStencilState(GSDepthStencilOGL* dss);
|
||||
void OMSetBlendState(u8 blend_index = 0, u8 blend_factor = 0, bool is_blend_constant = false, bool accumulation_blend = false, bool blend_mix = false, bool replace_dual_src = false);
|
||||
void OMSetBlendState(bool enable = false, GLenum src_factor = GL_ONE, GLenum dst_factor = GL_ZERO, GLenum op = GL_FUNC_ADD, bool is_constant = false, u8 constant = 0);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
|
||||
void OMSetColorMaskState(OMColorMaskSelector sel = OMColorMaskSelector());
|
||||
|
||||
|
|
|
@ -922,54 +922,6 @@ void GSDeviceVK::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
|
|||
SetScissor(scissor);
|
||||
}
|
||||
|
||||
u16 GSDeviceVK::ConvertBlendEnum(u16 generic)
|
||||
{
|
||||
switch (generic)
|
||||
{
|
||||
case SRC_COLOR:
|
||||
return VK_BLEND_FACTOR_SRC_COLOR;
|
||||
case INV_SRC_COLOR:
|
||||
return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
|
||||
case DST_COLOR:
|
||||
return VK_BLEND_FACTOR_DST_COLOR;
|
||||
case INV_DST_COLOR:
|
||||
return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
|
||||
case SRC1_COLOR:
|
||||
return VK_BLEND_FACTOR_SRC1_COLOR;
|
||||
case INV_SRC1_COLOR:
|
||||
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
|
||||
case SRC_ALPHA:
|
||||
return VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
case INV_SRC_ALPHA:
|
||||
return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
case DST_ALPHA:
|
||||
return VK_BLEND_FACTOR_DST_ALPHA;
|
||||
case INV_DST_ALPHA:
|
||||
return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
|
||||
case SRC1_ALPHA:
|
||||
return VK_BLEND_FACTOR_SRC1_ALPHA;
|
||||
case INV_SRC1_ALPHA:
|
||||
return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
|
||||
case CONST_COLOR:
|
||||
return VK_BLEND_FACTOR_CONSTANT_COLOR;
|
||||
case INV_CONST_COLOR:
|
||||
return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
|
||||
case CONST_ONE:
|
||||
return VK_BLEND_FACTOR_ONE;
|
||||
case CONST_ZERO:
|
||||
return VK_BLEND_FACTOR_ZERO;
|
||||
case OP_ADD:
|
||||
return VK_BLEND_OP_ADD;
|
||||
case OP_SUBTRACT:
|
||||
return VK_BLEND_OP_SUBTRACT;
|
||||
case OP_REV_SUBTRACT:
|
||||
return VK_BLEND_OP_REVERSE_SUBTRACT;
|
||||
default:
|
||||
ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
VkSampler GSDeviceVK::GetSampler(GSHWDrawConfig::SamplerSelector ss)
|
||||
{
|
||||
const auto it = m_samplers.find(ss.key);
|
||||
|
@ -1847,12 +1799,10 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p)
|
|||
if ((p.cms.wrgba & 0x7) == 0)
|
||||
{
|
||||
// disable blending when colours are masked
|
||||
pbs.index = 0;
|
||||
pbs = {};
|
||||
pps.no_color1 = true;
|
||||
}
|
||||
|
||||
// don't output alpha blend when blending is disabled
|
||||
pps.no_color1 = (pbs.index == 0);
|
||||
|
||||
VkShaderModule vs = GetTFXVertexShader(p.vs);
|
||||
VkShaderModule gs = p.gs.expand ? GetTFXGeometryShader(p.gs) : VK_NULL_HANDLE;
|
||||
VkShaderModule fs = GetTFXFragmentShader(pps);
|
||||
|
@ -1917,20 +1867,22 @@ VkPipeline GSDeviceVK::CreateTFXPipeline(const PipelineSelector& p)
|
|||
gpb.SetBlendAttachment(0, true, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_MIN, VK_BLEND_FACTOR_ONE,
|
||||
VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, VK_COLOR_COMPONENT_R_BIT);
|
||||
}
|
||||
else if (pbs.index > 0)
|
||||
else if (pbs.enable)
|
||||
{
|
||||
const HWBlend blend = GetBlend(pbs.index, pbs.replace_dual_src);
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
pxAssertRel(m_features.dual_source_blend || pbs.is_accumulation ||
|
||||
(blend.src != VK_BLEND_FACTOR_SRC1_ALPHA && blend.src != VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA &&
|
||||
blend.dst != VK_BLEND_FACTOR_SRC1_ALPHA && blend.dst != VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA),
|
||||
"Not using dual source factors");
|
||||
#endif
|
||||
// clang-format off
|
||||
static constexpr std::array<VkBlendFactor, 16> vk_blend_factors = { {
|
||||
VK_BLEND_FACTOR_SRC_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VK_BLEND_FACTOR_DST_COLOR, VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR,
|
||||
VK_BLEND_FACTOR_SRC1_COLOR, VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, VK_BLEND_FACTOR_SRC1_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA,
|
||||
VK_BLEND_FACTOR_CONSTANT_COLOR, VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO
|
||||
}};
|
||||
static constexpr std::array<VkBlendOp, 3> vk_blend_ops = {{
|
||||
VK_BLEND_OP_ADD, VK_BLEND_OP_SUBTRACT, VK_BLEND_OP_REVERSE_SUBTRACT
|
||||
}};
|
||||
// clang-format on
|
||||
|
||||
gpb.SetBlendAttachment(0, true,
|
||||
(pbs.is_accumulation || pbs.is_mixed_hw_sw) ? VK_BLEND_FACTOR_ONE : static_cast<VkBlendFactor>(blend.src),
|
||||
pbs.is_accumulation ? VK_BLEND_FACTOR_ONE : static_cast<VkBlendFactor>(blend.dst),
|
||||
static_cast<VkBlendOp>(blend.op), VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, p.cms.wrgba);
|
||||
gpb.SetBlendAttachment(0, true, vk_blend_factors[pbs.src_factor], vk_blend_factors[pbs.dst_factor],
|
||||
vk_blend_ops[pbs.op], VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, p.cms.wrgba);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2718,8 +2670,8 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
|||
}
|
||||
if (config.pal)
|
||||
PSSetShaderResource(1, config.pal, true);
|
||||
if (config.blend.is_constant)
|
||||
SetBlendConstants(config.blend.factor);
|
||||
if (config.blend.constant_enable)
|
||||
SetBlendConstants(config.blend.constant);
|
||||
|
||||
// Primitive ID tracking DATE setup.
|
||||
GSTextureVK* date_image = nullptr;
|
||||
|
@ -2995,7 +2947,7 @@ void GSDeviceVK::UpdateHWPipelineSelector(GSHWDrawConfig& config)
|
|||
m_pipeline_selector.ps.key_lo = config.ps.key_lo;
|
||||
m_pipeline_selector.dss.key = config.depth.key;
|
||||
m_pipeline_selector.bs.key = config.blend.key;
|
||||
m_pipeline_selector.bs.factor = 0; // don't dupe states with different alpha values
|
||||
m_pipeline_selector.bs.constant = 0; // don't dupe states with different alpha values
|
||||
m_pipeline_selector.cms.key = config.colormask.key;
|
||||
m_pipeline_selector.topology = static_cast<u32>(config.topology);
|
||||
m_pipeline_selector.rt = config.rt != nullptr;
|
||||
|
|
|
@ -152,7 +152,8 @@ private:
|
|||
const GSRegEXTBUF& EXTBUF, const GSVector4& c) final;
|
||||
void DoInterlace(GSTexture* sTex, GSTexture* dTex, int shader, bool linear, float yoffset = 0) final;
|
||||
|
||||
u16 ConvertBlendEnum(u16 generic) final;
|
||||
static VkBlendFactor ConvertBlendFactor(u8 generic);
|
||||
static VkBlendOp ConvertBlendOp(u8 generic);
|
||||
|
||||
VkSampler GetSampler(GSHWDrawConfig::SamplerSelector ss);
|
||||
void ClearSamplerCache() final;
|
||||
|
|
Loading…
Reference in New Issue