diff --git a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm index 9b2f0824ca..3898a694b2 100644 --- a/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm +++ b/pcsx2/GS/Renderers/Metal/GSDeviceMTL.mm @@ -1413,6 +1413,7 @@ void GSDeviceMTL::MRESetHWPipelineState(GSHWDrawConfig::VSSelector vssel, GSHWDr setFnConstantB(m_fn_constants, pssel.automatic_lod, GSMTLConstantIndex_PS_AUTOMATIC_LOD); setFnConstantB(m_fn_constants, pssel.manual_lod, GSMTLConstantIndex_PS_MANUAL_LOD); setFnConstantB(m_fn_constants, pssel.point_sampler, GSMTLConstantIndex_PS_POINT_SAMPLER); + setFnConstantB(m_fn_constants, pssel.region_rect, GSMTLConstantIndex_PS_REGION_RECT); setFnConstantI(m_fn_constants, pssel.scanmsk, GSMTLConstantIndex_PS_SCANMSK); auto newps = LoadShader(@"ps_main"); ps = newps; diff --git a/pcsx2/GS/Renderers/Metal/GSMTLSharedHeader.h b/pcsx2/GS/Renderers/Metal/GSMTLSharedHeader.h index d5f7e57b54..d36473c528 100644 --- a/pcsx2/GS/Renderers/Metal/GSMTLSharedHeader.h +++ b/pcsx2/GS/Renderers/Metal/GSMTLSharedHeader.h @@ -211,5 +211,6 @@ enum GSMTLFnConstants GSMTLConstantIndex_PS_AUTOMATIC_LOD, GSMTLConstantIndex_PS_MANUAL_LOD, GSMTLConstantIndex_PS_POINT_SAMPLER, + GSMTLConstantIndex_PS_REGION_RECT, GSMTLConstantIndex_PS_SCANMSK, }; diff --git a/pcsx2/GS/Renderers/Metal/tfx.metal b/pcsx2/GS/Renderers/Metal/tfx.metal index b98f62839d..bd55c7fd9f 100644 --- a/pcsx2/GS/Renderers/Metal/tfx.metal +++ b/pcsx2/GS/Renderers/Metal/tfx.metal @@ -70,6 +70,7 @@ constant bool PS_TEX_IS_FB [[function_constant(GSMTLConstantIndex_PS_TE constant bool PS_AUTOMATIC_LOD [[function_constant(GSMTLConstantIndex_PS_AUTOMATIC_LOD)]]; constant bool PS_MANUAL_LOD [[function_constant(GSMTLConstantIndex_PS_MANUAL_LOD)]]; constant bool PS_POINT_SAMPLER [[function_constant(GSMTLConstantIndex_PS_POINT_SAMPLER)]]; +constant bool PS_REGION_RECT [[function_constant(GSMTLConstantIndex_PS_REGION_RECT)]]; constant uint PS_SCANMSK [[function_constant(GSMTLConstantIndex_PS_SCANMSK)]]; constant GSMTLExpandType VS_EXPAND_TYPE = static_cast(VS_EXPAND_TYPE_RAW); @@ -310,10 +311,20 @@ struct PSMain return tex.sample(args...); } + float4 read_tex(uint2 pos, uint lod = 0) + { + if (PS_TEX_IS_DEPTH) + return float4(tex_depth.read(pos, lod)); + else + return tex.read(pos, lod); + } + float4 sample_c(float2 uv) { if (PS_TEX_IS_FB) return current_color; + if (PS_REGION_RECT) + return read_tex(uint2(uv)); if (PS_POINT_SAMPLER) { @@ -382,7 +393,15 @@ struct PSMain if (PS_WMS == PS_WMT) { - if (PS_WMS == 2) + if (PS_REGION_RECT && PS_WMS == 0) + { + uv_out = fract(uv); + } + else if (PS_REGION_RECT && PS_WMS == 1) + { + uv_out = saturate(uv); + } + else if (PS_WMS == 2) { uv_out = clamp(uv, cb.uv_min_max.xyxy, cb.uv_min_max.zwzw); } @@ -398,7 +417,15 @@ struct PSMain } else { - if (PS_WMS == 2) + if (PS_REGION_RECT && PS_WMS == 0) + { + uv_out.xz = fract(uv.xz); + } + else if (PS_REGION_RECT && PS_WMS == 1) + { + uv_out.xz = saturate(uv.xz); + } + else if (PS_WMS == 2) { uv_out.xz = clamp(uv.xz, cb.uv_min_max.xx, cb.uv_min_max.zz); } @@ -410,7 +437,15 @@ struct PSMain uv_out.xz = float2((ushort2(uv.xz * tex_size.xx) & ushort2(cb.uv_msk_fix.xx)) | ushort2(cb.uv_msk_fix.zz)) / tex_size.xx; } - if (PS_WMT == 2) + if (PS_REGION_RECT && PS_WMT == 0) + { + uv_out.yw = fract(uv.yw); + } + else if (PS_REGION_RECT && PS_WMT == 1) + { + uv_out.yw = saturate(uv.yw); + } + else if (PS_WMT == 2) { uv_out.yw = clamp(uv.yw, cb.uv_min_max.yy, cb.uv_min_max.ww); } @@ -423,6 +458,12 @@ struct PSMain } } + if (PS_REGION_RECT) + { + // Normalized -> Integer Coordinates. + uv_out = clamp(uv_out * cb.wh.zwzw + cb.st_range.xyxy, cb.st_range.xyxy, cb.st_range.zwzw); + } + return uv_out; } @@ -631,7 +672,7 @@ struct PSMain float4x4 c; float2 dd; - if (!PS_LTF && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_WMS < 2 && PS_WMT < 2) + if (!PS_LTF && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && !PS_REGION_RECT && PS_WMS < 2 && PS_WMT < 2) { c[0] = sample_c(st); }