mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: RTA Correction, implement on DATE.
Less copies, and makes it work with DATE.
This commit is contained in:
parent
58628b8dd3
commit
0900c2fd8b
|
@ -113,6 +113,28 @@ PS_OUTPUT ps_datm0(PS_INPUT input)
|
|||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_datm1_rta_correction(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
clip(sample_c(input.t).a - 254.5f / 255); // >= 0x80 pass
|
||||
|
||||
output.c = 0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_datm0_rta_correction(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
clip(254.5f / 255 - sample_c(input.t).a); // < 0x80 pass (== 0x80 should not pass)
|
||||
|
||||
output.c = 0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_rta_correction(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
@ -414,3 +436,25 @@ float ps_stencil_image_init_1(PS_INPUT input) : SV_Target
|
|||
c = float(0x7FFFFFFF);
|
||||
return c;
|
||||
}
|
||||
|
||||
float ps_stencil_image_init_2(PS_INPUT input)
|
||||
: SV_Target
|
||||
{
|
||||
float c;
|
||||
if ((254.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
c = float(-1);
|
||||
else
|
||||
c = float(0x7FFFFFFF);
|
||||
return c;
|
||||
}
|
||||
|
||||
float ps_stencil_image_init_3(PS_INPUT input)
|
||||
: SV_Target
|
||||
{
|
||||
float c;
|
||||
if (sample_c(input.t).a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
c = float(-1);
|
||||
else
|
||||
c = float(0x7FFFFFFF);
|
||||
return c;
|
||||
}
|
||||
|
|
|
@ -313,6 +313,26 @@ void ps_datm0()
|
|||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 1
|
||||
#ifdef ps_datm1_rta_correction
|
||||
void ps_datm1_rta_correction()
|
||||
{
|
||||
if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Used for DATE (stencil)
|
||||
// DATM == 0
|
||||
#ifdef ps_datm0_rta_correction
|
||||
void ps_datm0_rta_correction()
|
||||
{
|
||||
if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_correction
|
||||
void ps_rta_correction()
|
||||
{
|
||||
|
@ -435,7 +455,7 @@ void ps_yuv()
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1)
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1) || defined(ps_stencil_image_init_2) || defined(ps_stencil_image_init_3)
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -449,6 +469,14 @@ void main()
|
|||
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_2
|
||||
if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_3
|
||||
if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
SV_Target0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -943,10 +943,18 @@ void ps_main()
|
|||
|
||||
#if (PS_DATE & 3) == 1
|
||||
// DATM == 0: Pixel with alpha equal to 1 will failed
|
||||
bool bad = (127.5f / 255.0f) < rt_a;
|
||||
#if PS_RTA_CORRECTION
|
||||
bool bad = (254.5f / 255.0f) < rt_a;
|
||||
#else
|
||||
bool bad = (127.5f / 255.0f) < rt_a;
|
||||
#endif
|
||||
#elif (PS_DATE & 3) == 2
|
||||
// DATM == 1: Pixel with alpha equal to 0 will failed
|
||||
bool bad = rt_a < (127.5f / 255.0f);
|
||||
#if PS_RTA_CORRECTION
|
||||
bool bad = rt_a < (254.5f / 255.0f);
|
||||
#else
|
||||
bool bad = rt_a < (127.5f / 255.0f);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (bad) {
|
||||
|
|
|
@ -24,6 +24,8 @@ layout(location = 0) in vec2 v_tex;
|
|||
layout(location = 0) out uint o_col0;
|
||||
#elif !defined(ps_datm1) && \
|
||||
!defined(ps_datm0) && \
|
||||
!defined(ps_datm1_rta_correction) && \
|
||||
!defined(ps_datm0_rta_correction) && \
|
||||
!defined(ps_convert_rgba8_float32) && \
|
||||
!defined(ps_convert_rgba8_float24) && \
|
||||
!defined(ps_convert_rgba8_float16) && \
|
||||
|
@ -92,6 +94,22 @@ void ps_datm0()
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm1_rta_correction
|
||||
void ps_datm1_rta_correction()
|
||||
{
|
||||
if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_datm0_rta_correction
|
||||
void ps_datm0_rta_correction()
|
||||
{
|
||||
if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
discard;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_rta_correction
|
||||
void ps_rta_correction()
|
||||
{
|
||||
|
@ -416,7 +434,7 @@ void ps_yuv()
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1)
|
||||
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1) || defined(ps_stencil_image_init_2) || defined(ps_stencil_image_init_3)
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -430,6 +448,14 @@ void main()
|
|||
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_2
|
||||
if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
#ifdef ps_stencil_image_init_3
|
||||
if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass
|
||||
o_col0 = vec4(-1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1194,10 +1194,18 @@ void main()
|
|||
|
||||
#if (PS_DATE & 3) == 1
|
||||
// DATM == 0: Pixel with alpha equal to 1 will failed
|
||||
bool bad = (127.5f / 255.0f) < rt_a;
|
||||
#if PS_RTA_CORRECTION
|
||||
bool bad = (254.5f / 255.0f) < rt_a;
|
||||
#else
|
||||
bool bad = (127.5f / 255.0f) < rt_a;
|
||||
#endif
|
||||
#elif (PS_DATE & 3) == 2
|
||||
// DATM == 1: Pixel with alpha equal to 0 will failed
|
||||
bool bad = rt_a < (127.5f / 255.0f);
|
||||
#if PS_RTA_CORRECTION
|
||||
bool bad = rt_a < (254.5f / 255.0f);
|
||||
#else
|
||||
bool bad = rt_a < (127.5f / 255.0f);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (bad) {
|
||||
|
|
|
@ -17,6 +17,22 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
int SetDATMShader(SetDATM datm)
|
||||
{
|
||||
switch (datm)
|
||||
{
|
||||
case SetDATM::DATM1_RTA_CORRECTION:
|
||||
return static_cast<int>(ShaderConvert::DATM_1_RTA_CORRECTION);
|
||||
case SetDATM::DATM0_RTA_CORRECTION:
|
||||
return static_cast<int>(ShaderConvert::DATM_0_RTA_CORRECTION);
|
||||
case SetDATM::DATM1:
|
||||
return static_cast<int>(ShaderConvert::DATM_1);
|
||||
case SetDATM::DATM0:
|
||||
default:
|
||||
return static_cast<int>(ShaderConvert::DATM_0);
|
||||
}
|
||||
}
|
||||
|
||||
const char* shaderName(ShaderConvert value)
|
||||
{
|
||||
switch (value)
|
||||
|
@ -26,6 +42,8 @@ const char* shaderName(ShaderConvert value)
|
|||
case ShaderConvert::RGBA8_TO_16_BITS: return "ps_convert_rgba8_16bits";
|
||||
case ShaderConvert::DATM_1: return "ps_datm1";
|
||||
case ShaderConvert::DATM_0: return "ps_datm0";
|
||||
case ShaderConvert::DATM_1_RTA_CORRECTION: return "ps_datm1_rta_correction";
|
||||
case ShaderConvert::DATM_0_RTA_CORRECTION: return "ps_datm0_rta_correction";
|
||||
case ShaderConvert::HDR_INIT: return "ps_hdr_init";
|
||||
case ShaderConvert::HDR_RESOLVE: return "ps_hdr_resolve";
|
||||
case ShaderConvert::RTA_CORRECTION: return "ps_rta_correction";
|
||||
|
|
|
@ -19,6 +19,8 @@ enum class ShaderConvert
|
|||
RGBA8_TO_16_BITS,
|
||||
DATM_1,
|
||||
DATM_0,
|
||||
DATM_1_RTA_CORRECTION,
|
||||
DATM_0_RTA_CORRECTION,
|
||||
HDR_INIT,
|
||||
HDR_RESOLVE,
|
||||
RTA_CORRECTION,
|
||||
|
@ -45,6 +47,14 @@ enum class ShaderConvert
|
|||
Count
|
||||
};
|
||||
|
||||
enum class SetDATM : u8
|
||||
{
|
||||
DATM0 = 0U,
|
||||
DATM1,
|
||||
DATM0_RTA_CORRECTION,
|
||||
DATM1_RTA_CORRECTION
|
||||
};
|
||||
|
||||
enum class ShaderInterlace
|
||||
{
|
||||
WEAVE = 0,
|
||||
|
@ -80,6 +90,8 @@ static inline bool HasStencilOutput(ShaderConvert shader)
|
|||
{
|
||||
case ShaderConvert::DATM_0:
|
||||
case ShaderConvert::DATM_1:
|
||||
case ShaderConvert::DATM_0_RTA_CORRECTION:
|
||||
case ShaderConvert::DATM_1_RTA_CORRECTION:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -140,6 +152,7 @@ enum class PresentShader
|
|||
|
||||
/// Get the name of a shader
|
||||
/// (Can't put methods on an enum class)
|
||||
int SetDATMShader(SetDATM datm);
|
||||
const char* shaderName(ShaderConvert value);
|
||||
const char* shaderName(PresentShader value);
|
||||
|
||||
|
@ -653,7 +666,7 @@ struct alignas(16) GSHWDrawConfig
|
|||
bool require_full_barrier; ///< Require texture barrier between all prims
|
||||
|
||||
DestinationAlphaMode destination_alpha;
|
||||
bool datm : 1;
|
||||
SetDATM datm : 2;
|
||||
bool line_expand : 1;
|
||||
bool separate_alpha_pass : 1;
|
||||
bool second_separate_alpha_pass : 1;
|
||||
|
|
|
@ -2089,7 +2089,7 @@ void GSDevice11::RenderImGui()
|
|||
m_ctx->IASetVertexBuffers(0, 1, m_vb.addressof(), &m_state.vb_stride, &vb_offset);
|
||||
}
|
||||
|
||||
void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm)
|
||||
void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, SetDATM datm)
|
||||
{
|
||||
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
|
||||
|
||||
|
@ -2117,7 +2117,7 @@ void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vert
|
|||
// ps
|
||||
PSSetShaderResource(0, rt);
|
||||
PSSetSamplerState(m_convert.pt.get());
|
||||
PSSetShader(m_convert.ps[static_cast<int>(datm ? ShaderConvert::DATM_1 : ShaderConvert::DATM_0)].get(), nullptr);
|
||||
PSSetShader(m_convert.ps[SetDATMShader(datm)].get(), nullptr);
|
||||
|
||||
//
|
||||
|
||||
|
@ -2484,7 +2484,7 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
|
|||
return;
|
||||
|
||||
StretchRect(config.rt, GSVector4(config.drawarea) / GSVector4(rtsize).xyxy(),
|
||||
primid_tex, GSVector4(config.drawarea), m_date.primid_init_ps[config.datm].get(), nullptr, false);
|
||||
primid_tex, GSVector4(config.drawarea), m_date.primid_init_ps[static_cast<u8>(config.datm)].get(), nullptr, false);
|
||||
}
|
||||
else if (config.destination_alpha != GSHWDrawConfig::DestinationAlphaMode::Off)
|
||||
{
|
||||
|
|
|
@ -227,7 +227,7 @@ private:
|
|||
{
|
||||
wil::com_ptr_nothrow<ID3D11DepthStencilState> dss;
|
||||
wil::com_ptr_nothrow<ID3D11BlendState> bs;
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> primid_init_ps[2];
|
||||
wil::com_ptr_nothrow<ID3D11PixelShader> primid_init_ps[4];
|
||||
} m_date;
|
||||
|
||||
struct
|
||||
|
@ -322,7 +322,7 @@ public:
|
|||
void DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvert shader) override;
|
||||
void DoMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, const GSVector2& ds);
|
||||
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm);
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, SetDATM datm);
|
||||
|
||||
void* IAMapVertexBuffer(u32 stride, u32 count);
|
||||
void IAUnmapVertexBuffer(u32 stride, u32 count);
|
||||
|
|
|
@ -34,7 +34,7 @@ static u32 s_debug_scope_depth = 0;
|
|||
|
||||
static bool IsDATMConvertShader(ShaderConvert i)
|
||||
{
|
||||
return (i == ShaderConvert::DATM_0 || i == ShaderConvert::DATM_1);
|
||||
return (i == ShaderConvert::DATM_0 || i == ShaderConvert::DATM_1 || i == ShaderConvert::DATM_0_RTA_CORRECTION || i == ShaderConvert::DATM_1_RTA_CORRECTION);
|
||||
}
|
||||
static bool IsDATEModePrimIDInit(u32 flag)
|
||||
{
|
||||
|
@ -2401,6 +2401,8 @@ bool GSDevice12::CompileConvertPipelines()
|
|||
break;
|
||||
case ShaderConvert::DATM_0:
|
||||
case ShaderConvert::DATM_1:
|
||||
case ShaderConvert::DATM_0_RTA_CORRECTION:
|
||||
case ShaderConvert::DATM_1_RTA_CORRECTION:
|
||||
{
|
||||
gpb.ClearRenderTargets();
|
||||
gpb.SetDepthStencilFormat(DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
|
||||
|
@ -2478,10 +2480,10 @@ bool GSDevice12::CompileConvertPipelines()
|
|||
}
|
||||
}
|
||||
|
||||
for (u32 datm = 0; datm < 2; datm++)
|
||||
for (u32 datm = 0; datm < 4; datm++)
|
||||
{
|
||||
ComPtr<ID3DBlob> ps(
|
||||
GetUtilityPixelShader(*shader, datm ? "ps_stencil_image_init_1" : "ps_stencil_image_init_0"));
|
||||
const std::string entry_point(StringUtil::StdStringFromFormat("ps_stencil_image_init_%d", datm));
|
||||
ComPtr<ID3DBlob> ps(GetUtilityPixelShader(*shader, entry_point.c_str()));
|
||||
if (!ps)
|
||||
return false;
|
||||
|
||||
|
@ -2501,7 +2503,7 @@ bool GSDevice12::CompileConvertPipelines()
|
|||
return false;
|
||||
|
||||
D3D12::SetObjectName(m_date_image_setup_pipelines[ds][datm].get(),
|
||||
TinyString::from_fmt("DATE image clear pipeline (ds={}, datm={})", ds, datm));
|
||||
TinyString::from_fmt("DATE image clear pipeline (ds={}, datm={})", ds, (datm == 1 || datm == 3)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3621,7 +3623,7 @@ void GSDevice12::SetPSConstantBuffer(const GSHWDrawConfig::PSConstantBuffer& cb)
|
|||
m_dirty_flags |= DIRTY_FLAG_PS_CONSTANT_BUFFER;
|
||||
}
|
||||
|
||||
void GSDevice12::SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVector4i& bbox)
|
||||
void GSDevice12::SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox)
|
||||
{
|
||||
GL_PUSH("SetupDATE {%d,%d} %dx%d", bbox.left, bbox.top, bbox.width(), bbox.height());
|
||||
|
||||
|
@ -3641,7 +3643,7 @@ void GSDevice12::SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVect
|
|||
OMSetRenderTargets(nullptr, ds, bbox);
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), 4);
|
||||
SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
SetPipeline(m_convert[static_cast<int>(datm ? ShaderConvert::DATM_1 : ShaderConvert::DATM_0)].get());
|
||||
SetPipeline(m_convert[SetDATMShader(datm)].get());
|
||||
SetStencilRef(1);
|
||||
BeginRenderPass(D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_NO_ACCESS, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_NO_ACCESS,
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_PRESERVE, D3D12_RENDER_PASS_ENDING_ACCESS_TYPE_PRESERVE,
|
||||
|
@ -3693,7 +3695,7 @@ GSTexture12* GSDevice12::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, Pipe
|
|||
};
|
||||
SetUtilityRootSignature();
|
||||
SetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
SetPipeline(m_date_image_setup_pipelines[pipe.ds][config.datm].get());
|
||||
SetPipeline(m_date_image_setup_pipelines[pipe.ds][static_cast<u8>(config.datm)].get());
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
|
||||
if (ApplyUtilityState())
|
||||
DrawPrimitive();
|
||||
|
|
|
@ -317,7 +317,7 @@ private:
|
|||
std::array<ComPtr<ID3D12PipelineState>, NUM_INTERLACE_SHADERS> m_interlace{};
|
||||
std::array<ComPtr<ID3D12PipelineState>, 2> m_hdr_setup_pipelines{}; // [depth]
|
||||
std::array<ComPtr<ID3D12PipelineState>, 2> m_hdr_finish_pipelines{}; // [depth]
|
||||
std::array<std::array<ComPtr<ID3D12PipelineState>, 2>, 2> m_date_image_setup_pipelines{}; // [depth][datm]
|
||||
std::array<std::array<ComPtr<ID3D12PipelineState>, 4>, 2> m_date_image_setup_pipelines{}; // [depth][datm]
|
||||
ComPtr<ID3D12PipelineState> m_fxaa_pipeline;
|
||||
ComPtr<ID3D12PipelineState> m_shadeboost_pipeline;
|
||||
ComPtr<ID3D12PipelineState> m_imgui_pipeline;
|
||||
|
@ -450,7 +450,7 @@ public:
|
|||
const ID3D12PipelineState* pipeline, bool linear, bool allow_discard);
|
||||
void DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect, const GSVector2i& ds);
|
||||
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVector4i& bbox);
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox);
|
||||
GSTexture12* SetupPrimitiveTrackingDATE(GSHWDrawConfig& config, PipelineSelector& pipe);
|
||||
|
||||
void IASetVertexBuffer(const void* vertex, size_t stride, size_t count);
|
||||
|
|
|
@ -4301,9 +4301,8 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, bool& DAT
|
|||
m_conf.ps.blend_b = 0;
|
||||
m_conf.ps.blend_d = 0;
|
||||
|
||||
// TODO: Make it work on DATE, switch to new shaders with Ad doubled.
|
||||
const bool rta_decorrection = m_channel_shuffle || m_texture_shuffle || rt_alpha_max > 128 || m_conf.ps.fbmask || m_conf.ps.tex_is_fb;
|
||||
const bool rta_correction = !rta_decorrection && !m_cached_ctx.TEST.DATE && !blend_ad_alpha_masked && m_conf.ps.blend_c == 1 && !(blend_flag & BLEND_A_MAX);
|
||||
const bool rta_correction = !rta_decorrection && !blend_ad_alpha_masked && m_conf.ps.blend_c == 1 && !(blend_flag & BLEND_A_MAX);
|
||||
if (rta_correction)
|
||||
{
|
||||
rt->RTACorrect(rt);
|
||||
|
@ -5351,7 +5350,10 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
|||
else if (features.stencil_buffer)
|
||||
m_conf.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::Stencil;
|
||||
|
||||
m_conf.datm = m_cached_ctx.TEST.DATM;
|
||||
if (m_conf.ps.rta_correction)
|
||||
m_conf.datm = static_cast<SetDATM>(m_cached_ctx.TEST.DATM + 2);
|
||||
else
|
||||
m_conf.datm = static_cast<SetDATM>(m_cached_ctx.TEST.DATM);
|
||||
|
||||
// If we're doing stencil DATE and we don't have a depth buffer, we need to allocate a temporary one.
|
||||
GSTexture* temp_ds = nullptr;
|
||||
|
@ -6899,7 +6901,7 @@ GSHWDrawConfig& GSRendererHW::BeginHLEHardwareDraw(
|
|||
config.require_one_barrier = false;
|
||||
config.require_full_barrier = false;
|
||||
config.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::Off;
|
||||
config.datm = false;
|
||||
config.datm = SetDATM::DATM0;
|
||||
config.line_expand = false;
|
||||
config.separate_alpha_pass = false;
|
||||
config.second_separate_alpha_pass = false;
|
||||
|
|
|
@ -247,13 +247,15 @@ public:
|
|||
MRCOwned<id<MTLRenderPipelineState>> m_convert_pipeline_copy_mask[1 << 4];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_merge_pipeline[4];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_interlace_pipeline[NUM_INTERLACE_SHADERS];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_datm_pipeline[2];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_datm_pipeline[4];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_clut_pipeline[2];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_stencil_clear_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_primid_init_pipeline[2][2];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_primid_init_pipeline[2][4];
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_init_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_rta_init_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_clear_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_resolve_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_hdr_rta_resolve_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_fxaa_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_shadeboost_pipeline;
|
||||
MRCOwned<id<MTLRenderPipelineState>> m_imgui_pipeline;
|
||||
|
@ -430,7 +432,7 @@ public:
|
|||
|
||||
// MARK: Render HW
|
||||
|
||||
void SetupDestinationAlpha(GSTexture* rt, GSTexture* ds, const GSVector4i& r, bool datm);
|
||||
void SetupDestinationAlpha(GSTexture* rt, GSTexture* ds, const GSVector4i& r, SetDATM datm);
|
||||
void RenderHW(GSHWDrawConfig& config) override;
|
||||
void SendHWDraw(GSHWDrawConfig& config, id<MTLRenderCommandEncoder> enc, id<MTLBuffer> buffer, size_t off);
|
||||
|
||||
|
|
|
@ -1048,15 +1048,21 @@ bool GSDeviceMTL::Create()
|
|||
pdesc.stencilAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||
m_datm_pipeline[0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_datm0"), @"datm0");
|
||||
m_datm_pipeline[1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_datm1"), @"datm1");
|
||||
m_datm_pipeline[2] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_datm0_rta_correction"), @"datm0 rta");
|
||||
m_datm_pipeline[3] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_datm1_rta_correction"), @"datm1 rta");
|
||||
m_stencil_clear_pipeline = MakePipeline(pdesc, fs_triangle, nil, @"Stencil Clear");
|
||||
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::PrimID);
|
||||
pdesc.stencilAttachmentPixelFormat = MTLPixelFormatInvalid;
|
||||
pdesc.depthAttachmentPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
|
||||
m_primid_init_pipeline[1][0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm0"), @"PrimID DATM0 Clear");
|
||||
m_primid_init_pipeline[1][1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm1"), @"PrimID DATM1 Clear");
|
||||
m_primid_init_pipeline[1][2] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_rta_init_datm0"), @"PrimID DATM0 RTA Clear");
|
||||
m_primid_init_pipeline[1][3] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_rta_init_datm1"), @"PrimID DATM1 RTA Clear");
|
||||
pdesc.depthAttachmentPixelFormat = MTLPixelFormatInvalid;
|
||||
m_primid_init_pipeline[0][0] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm0"), @"PrimID DATM0 Clear");
|
||||
m_primid_init_pipeline[0][1] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_init_datm1"), @"PrimID DATM1 Clear");
|
||||
m_primid_init_pipeline[0][2] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_rta_init_datm0"), @"PrimID DATM0 RTA Clear");
|
||||
m_primid_init_pipeline[0][3] = MakePipeline(pdesc, fs_triangle, LoadShader(@"ps_primid_rta_init_datm1"), @"PrimID DATM1 RTA Clear");
|
||||
|
||||
pdesc.colorAttachments[0].pixelFormat = ConvertPixelFormat(GSTexture::Format::Color);
|
||||
applyAttribute(pdesc.vertexDescriptor, 0, MTLVertexFormatFloat2, offsetof(ConvertShaderVertex, pos), 0);
|
||||
|
@ -1077,6 +1083,8 @@ bool GSDeviceMTL::Create()
|
|||
case ShaderConvert::Count:
|
||||
case ShaderConvert::DATM_0:
|
||||
case ShaderConvert::DATM_1:
|
||||
case ShaderConvert::DATM_0_RTA_CORRECTION:
|
||||
case ShaderConvert::DATM_1_RTA_CORRECTION:
|
||||
case ShaderConvert::CLUT_4:
|
||||
case ShaderConvert::CLUT_8:
|
||||
case ShaderConvert::HDR_INIT:
|
||||
|
@ -2032,7 +2040,7 @@ static_assert(offsetof(GSHWDrawConfig::PSConstantBuffer, STScale) == of
|
|||
static_assert(offsetof(GSHWDrawConfig::PSConstantBuffer, DitherMatrix) == offsetof(GSMTLMainPSUniform, dither_matrix));
|
||||
static_assert(offsetof(GSHWDrawConfig::PSConstantBuffer, ScaleFactor) == offsetof(GSMTLMainPSUniform, scale_factor));
|
||||
|
||||
void GSDeviceMTL::SetupDestinationAlpha(GSTexture* rt, GSTexture* ds, const GSVector4i& r, bool datm)
|
||||
void GSDeviceMTL::SetupDestinationAlpha(GSTexture* rt, GSTexture* ds, const GSVector4i& r, SetDATM datm)
|
||||
{
|
||||
FlushClears(rt);
|
||||
BeginRenderPass(@"Destination Alpha Setup", nullptr, MTLLoadActionDontCare, nullptr, MTLLoadActionDontCare, ds, MTLLoadActionDontCare);
|
||||
|
@ -2040,7 +2048,7 @@ void GSDeviceMTL::SetupDestinationAlpha(GSTexture* rt, GSTexture* ds, const GSVe
|
|||
MRESetDSS(m_dss_stencil_zero);
|
||||
RenderCopy(nullptr, m_stencil_clear_pipeline, r);
|
||||
MRESetDSS(m_dss_stencil_write);
|
||||
RenderCopy(rt, m_datm_pipeline[datm], r);
|
||||
RenderCopy(rt, m_datm_pipeline[static_cast<u8>(datm)], r);
|
||||
}
|
||||
|
||||
static id<MTLTexture> getTexture(GSTexture* tex)
|
||||
|
@ -2115,7 +2123,7 @@ void GSDeviceMTL::RenderHW(GSHWDrawConfig& config)
|
|||
dsel.zwe = 0;
|
||||
GSTexture* depth = dsel.key == DepthStencilSelector::NoDepth().key ? nullptr : config.ds;
|
||||
BeginRenderPass(@"PrimID Destination Alpha Init", primid_tex, MTLLoadActionDontCare, depth, MTLLoadActionLoad);
|
||||
RenderCopy(config.rt, m_primid_init_pipeline[static_cast<bool>(depth)][config.datm], config.drawarea);
|
||||
RenderCopy(config.rt, m_primid_init_pipeline[static_cast<bool>(depth)][static_cast<u8>(config.datm)], config.drawarea);
|
||||
MRESetDSS(dsel);
|
||||
pxAssert(config.ps.date == 1 || config.ps.date == 2);
|
||||
if (config.ps.tex_is_fb)
|
||||
|
|
|
@ -88,20 +88,42 @@ fragment void ps_datm1(float4 p [[position]], DirectReadTextureIn<float> tex)
|
|||
discard_fragment();
|
||||
}
|
||||
|
||||
fragment void ps_datm0_rta_correction(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
{
|
||||
if (tex.read(p).a > (254.5f / 255.f))
|
||||
discard_fragment();
|
||||
}
|
||||
|
||||
fragment void ps_datm1_rta_correction(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
{
|
||||
if (tex.read(p).a < (254.5f / 255.f))
|
||||
discard_fragment();
|
||||
}
|
||||
|
||||
fragment void ps_datm0(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
{
|
||||
if (tex.read(p).a > (127.5f / 255.f))
|
||||
discard_fragment();
|
||||
}
|
||||
|
||||
fragment float4 ps_primid_init_datm1(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
{
|
||||
return tex.read(p).a < (127.5f / 255.f) ? -1 : FLT_MAX;
|
||||
}
|
||||
|
||||
fragment float4 ps_primid_init_datm0(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
{
|
||||
return tex.read(p).a > (127.5f / 255.f) ? -1 : FLT_MAX;
|
||||
}
|
||||
|
||||
fragment float4 ps_primid_init_datm1(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
fragment float4 ps_primid_rta_init_datm1(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
{
|
||||
return tex.read(p).a < (127.5f / 255.f) ? -1 : FLT_MAX;
|
||||
return tex.read(p).a < (254.5f / 255.f) ? -1 : FLT_MAX;
|
||||
}
|
||||
|
||||
fragment float4 ps_primid_rta_init_datm0(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
{
|
||||
return tex.read(p).a > (254.5f / 255.f) ? -1 : FLT_MAX;
|
||||
}
|
||||
|
||||
fragment float4 ps_rta_correction(float4 p [[position]], DirectReadTextureIn<float> tex)
|
||||
|
|
|
@ -1019,7 +1019,7 @@ struct PSMain
|
|||
{
|
||||
// 1 => DATM == 0, 2 => DATM == 1
|
||||
float rt_a = PS_WRITE_RG ? current_color.g : current_color.a;
|
||||
bool bad = (PS_DATE & 3) == 1 ? (rt_a > 0.5) : (rt_a < 0.5);
|
||||
bool bad = PS_RTA_CORRECTION ? ((PS_DATE & 3) == 1 ? (rt_a > (254.5f / 255.f)) : (rt_a < (254.5f / 255.f))) : ((PS_DATE & 3) == 1 ? (rt_a > 0.5) : (rt_a < 0.5));
|
||||
|
||||
if (bad)
|
||||
discard_fragment();
|
||||
|
|
|
@ -1233,7 +1233,7 @@ GSDepthStencilOGL* GSDeviceOGL::CreateDepthStencil(OMDepthStencilSelector dssel)
|
|||
return dss;
|
||||
}
|
||||
|
||||
GSTexture* GSDeviceOGL::InitPrimDateTexture(GSTexture* rt, const GSVector4i& area, bool datm)
|
||||
GSTexture* GSDeviceOGL::InitPrimDateTexture(GSTexture* rt, const GSVector4i& area, SetDATM datm)
|
||||
{
|
||||
const GSVector2i& rtsize = rt->GetSize();
|
||||
|
||||
|
@ -1242,7 +1242,7 @@ GSTexture* GSDeviceOGL::InitPrimDateTexture(GSTexture* rt, const GSVector4i& are
|
|||
return nullptr;
|
||||
|
||||
GL_PUSH("PrimID Destination Alpha Clear");
|
||||
StretchRect(rt, GSVector4(area) / GSVector4(rtsize).xyxy(), tex, GSVector4(area), m_date.primid_ps[datm], false);
|
||||
StretchRect(rt, GSVector4(area) / GSVector4(rtsize).xyxy(), tex, GSVector4(area), m_date.primid_ps[static_cast<u8>(datm)], false);
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
@ -1856,18 +1856,18 @@ void GSDeviceOGL::DoShadeBoost(GSTexture* sTex, GSTexture* dTex, const float par
|
|||
StretchRect(sTex, sRect, dTex, dRect, m_shadeboost.ps, false);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm)
|
||||
void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, SetDATM datm)
|
||||
{
|
||||
GL_PUSH("DATE First Pass");
|
||||
|
||||
// sfex3 (after the capcom logo), vf4 (first menu fading in), ffxii shadows, rumble roses shadows, persona4 shadows
|
||||
|
||||
OMSetRenderTargets(nullptr, ds, &GLState::scissor);
|
||||
|
||||
const GLint clear_color = 0;
|
||||
glClearBufferiv(GL_STENCIL, 0, &clear_color);
|
||||
|
||||
m_convert.ps[static_cast<int>(datm ? ShaderConvert::DATM_1 : ShaderConvert::DATM_0)].Bind();
|
||||
{
|
||||
const GLint clear_color = 0;
|
||||
glClearBufferiv(GL_STENCIL, 0, &clear_color);
|
||||
}
|
||||
m_convert.ps[SetDATMShader(datm)].Bind();
|
||||
|
||||
// om
|
||||
|
||||
|
|
|
@ -190,7 +190,7 @@ private:
|
|||
struct
|
||||
{
|
||||
GSDepthStencilOGL* dss = nullptr;
|
||||
GLProgram primid_ps[2];
|
||||
GLProgram primid_ps[4];
|
||||
} m_date;
|
||||
|
||||
struct
|
||||
|
@ -306,7 +306,7 @@ public:
|
|||
|
||||
std::unique_ptr<GSDownloadTexture> CreateDownloadTexture(u32 width, u32 height, GSTexture::Format format) override;
|
||||
|
||||
GSTexture* InitPrimDateTexture(GSTexture* rt, const GSVector4i& area, bool datm);
|
||||
GSTexture* InitPrimDateTexture(GSTexture* rt, const GSVector4i& area, SetDATM datm);
|
||||
|
||||
void CopyRect(GSTexture* sTex, GSTexture* dTex, const GSVector4i& r, u32 destX, u32 destY) override;
|
||||
|
||||
|
@ -331,7 +331,7 @@ public:
|
|||
void RenderHW(GSHWDrawConfig& config) override;
|
||||
void SendHWDraw(const GSHWDrawConfig& config, bool needs_barrier);
|
||||
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm);
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, SetDATM datm);
|
||||
|
||||
void IASetVAO(GLuint vao);
|
||||
void IASetPrimitiveTopology(GLenum topology);
|
||||
|
|
|
@ -50,7 +50,7 @@ static u32 s_debug_scope_depth = 0;
|
|||
|
||||
static bool IsDATMConvertShader(ShaderConvert i)
|
||||
{
|
||||
return (i == ShaderConvert::DATM_0 || i == ShaderConvert::DATM_1);
|
||||
return (i == ShaderConvert::DATM_0 || i == ShaderConvert::DATM_1 || i == ShaderConvert::DATM_0_RTA_CORRECTION || i == ShaderConvert::DATM_1_RTA_CORRECTION);
|
||||
}
|
||||
static bool IsDATEModePrimIDInit(u32 flag)
|
||||
{
|
||||
|
@ -3967,6 +3967,8 @@ bool GSDeviceVK::CompileConvertPipelines()
|
|||
break;
|
||||
case ShaderConvert::DATM_0:
|
||||
case ShaderConvert::DATM_1:
|
||||
case ShaderConvert::DATM_0_RTA_CORRECTION:
|
||||
case ShaderConvert::DATM_1_RTA_CORRECTION:
|
||||
{
|
||||
rp = m_date_setup_render_pass;
|
||||
}
|
||||
|
@ -4068,10 +4070,11 @@ bool GSDeviceVK::CompileConvertPipelines()
|
|||
}
|
||||
}
|
||||
|
||||
for (u32 datm = 0; datm < 2; datm++)
|
||||
for (u32 datm = 0; datm < 4; datm++)
|
||||
{
|
||||
const std::string entry_point(StringUtil::StdStringFromFormat("ps_stencil_image_init_%d", datm));
|
||||
VkShaderModule ps =
|
||||
GetUtilityFragmentShader(*shader, datm ? "ps_stencil_image_init_1" : "ps_stencil_image_init_0");
|
||||
GetUtilityFragmentShader(*shader, entry_point.c_str());
|
||||
if (ps == VK_NULL_HANDLE)
|
||||
return false;
|
||||
|
||||
|
@ -4093,7 +4096,7 @@ bool GSDeviceVK::CompileConvertPipelines()
|
|||
return false;
|
||||
|
||||
Vulkan::SetObjectName(m_device, m_date_image_setup_pipelines[ds][datm],
|
||||
"DATE image clear pipeline (ds=%u, datm=%u)", ds, datm);
|
||||
"DATE image clear pipeline (ds=%u, datm=%u)", ds, (datm == 1 || datm == 3));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4624,7 +4627,7 @@ void GSDeviceVK::DestroyResources()
|
|||
}
|
||||
for (u32 ds = 0; ds < 2; ds++)
|
||||
{
|
||||
for (u32 datm = 0; datm < 2; datm++)
|
||||
for (u32 datm = 0; datm < 4; datm++)
|
||||
{
|
||||
if (m_date_image_setup_pipelines[ds][datm] != VK_NULL_HANDLE)
|
||||
vkDestroyPipeline(m_device, m_date_image_setup_pipelines[ds][datm], nullptr);
|
||||
|
@ -5479,7 +5482,7 @@ void GSDeviceVK::SetPSConstantBuffer(const GSHWDrawConfig::PSConstantBuffer& cb)
|
|||
m_dirty_flags |= DIRTY_FLAG_PS_CONSTANT_BUFFER;
|
||||
}
|
||||
|
||||
void GSDeviceVK::SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVector4i& bbox)
|
||||
void GSDeviceVK::SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox)
|
||||
{
|
||||
GL_PUSH("SetupDATE {%d,%d} %dx%d", bbox.left, bbox.top, bbox.width(), bbox.height());
|
||||
|
||||
|
@ -5498,7 +5501,7 @@ void GSDeviceVK::SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVect
|
|||
SetUtilityTexture(rt, m_point_sampler);
|
||||
OMSetRenderTargets(nullptr, ds, bbox);
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), 4);
|
||||
SetPipeline(m_convert[static_cast<int>(datm ? ShaderConvert::DATM_1 : ShaderConvert::DATM_0)]);
|
||||
SetPipeline(m_convert[SetDATMShader(datm)]);
|
||||
BeginClearRenderPass(m_date_setup_render_pass, bbox, 0.0f, 0);
|
||||
if (ApplyUtilityState())
|
||||
DrawPrimitive();
|
||||
|
@ -5553,7 +5556,7 @@ GSTextureVK* GSDeviceVK::SetupPrimitiveTrackingDATE(GSHWDrawConfig& config)
|
|||
{GSVector4(dst.x, -dst.w, 0.5f, 1.0f), GSVector2(src.x, src.w)},
|
||||
{GSVector4(dst.z, -dst.w, 0.5f, 1.0f), GSVector2(src.z, src.w)},
|
||||
};
|
||||
const VkPipeline pipeline = m_date_image_setup_pipelines[ds][config.datm];
|
||||
const VkPipeline pipeline = m_date_image_setup_pipelines[ds][static_cast<u8>(config.datm)];
|
||||
SetPipeline(pipeline);
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
|
||||
if (ApplyUtilityState())
|
||||
|
|
|
@ -422,7 +422,7 @@ private:
|
|||
VkPipeline m_hdr_setup_pipelines[2][2] = {}; // [depth][feedback_loop]
|
||||
VkPipeline m_hdr_finish_pipelines[2][2] = {}; // [depth][feedback_loop]
|
||||
VkRenderPass m_date_image_setup_render_passes[2][2] = {}; // [depth][clear]
|
||||
VkPipeline m_date_image_setup_pipelines[2][2] = {}; // [depth][datm]
|
||||
VkPipeline m_date_image_setup_pipelines[2][4] = {}; // [depth][datm]
|
||||
VkPipeline m_fxaa_pipeline = {};
|
||||
VkPipeline m_shadeboost_pipeline = {};
|
||||
|
||||
|
@ -572,7 +572,7 @@ public:
|
|||
void ConvertToIndexedTexture(GSTexture* sTex, float sScale, u32 offsetX, u32 offsetY, u32 SBW, u32 SPSM,
|
||||
GSTexture* dTex, u32 DBW, u32 DPSM) override;
|
||||
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, bool datm, const GSVector4i& bbox);
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, SetDATM datm, const GSVector4i& bbox);
|
||||
GSTextureVK* SetupPrimitiveTrackingDATE(GSHWDrawConfig& config);
|
||||
|
||||
void IASetVertexBuffer(const void* vertex, size_t stride, size_t count);
|
||||
|
|
Loading…
Reference in New Issue