GS/HW: Treat depth input as R32 color input in convert shaders.

Co-authored-by: TellowKrinkle
This commit is contained in:
TJnotJT
2026-05-31 18:43:01 +02:00
committed by lightningterror
co-authored by TellowKrinkle
parent a44fe80caa
commit bf892e9ece
14 changed files with 26 additions and 82 deletions
+9 -13
View File
@@ -1824,27 +1824,23 @@ void GSHWDrawConfig::DumpConfig(const std::string& path, const GSHWDrawConfig& c
}
}
static constexpr u32 NUM_REMAP_INPUTS = static_cast<u32>(ShaderConvert::Count) * 8;
static constexpr u32 NUM_REMAP_INPUTS = static_cast<u32>(ShaderConvert::Count) * 4;
static constexpr ShaderConvertSelector GetRemappedShader(u32 idx)
{
ShaderConvert convert = static_cast<ShaderConvert>(idx >> 3);
bool depth_in = (idx >> 0) & 1;
bool depth_out = (idx >> 1) & 1;
bool biln = (idx >> 2) & 1;
return ShaderConvertSelector(convert, 0xf, depth_in, depth_out, biln);
ShaderConvert convert = static_cast<ShaderConvert>(idx >> 2);
bool depth_out = (idx >> 0) & 1;
bool biln = (idx >> 1) & 1;
return ShaderConvertSelector(convert, 0xf, depth_out, biln);
}
static constexpr bool RemapIndexIsValid(u32 idx)
{
ShaderConvert convert = static_cast<ShaderConvert>(idx >> 3);
bool depth_in = (idx >> 0) & 1;
bool depth_out = (idx >> 1) & 1;
bool biln = (idx >> 2) & 1;
if (HasVariableWriteMask(convert) && !depth_in && !depth_out && !biln)
ShaderConvert convert = static_cast<ShaderConvert>(idx >> 2);
bool depth_out = (idx >> 0) & 1;
bool biln = (idx >> 1) & 1;
if (HasVariableWriteMask(convert) && !depth_out && !biln)
return false; // Handled as variable write mask
if (depth_in && !HasFloat32Input(convert))
return false;
if (depth_out && !HasFloat32Output(convert))
return false;
if (biln && !SupportsBilinear(convert))
+10 -25
View File
@@ -248,7 +248,6 @@ class ShaderConvertSelector
{
u32 shader : 8; // Main shader
u32 mask : 8; // Variable color mask
u32 depth_in : 1; // Depth texture input
u32 depth_out : 1; // Depth texture output
u32 biln : 1; // Shader bilinear (HW bilinear is specified separately)
};
@@ -259,11 +258,11 @@ class ShaderConvertSelector
static_assert(sizeof(fields) == 4);
public:
constexpr ShaderConvertSelector(ShaderConvert shader = ShaderConvert::COPY, u8 mask = 0xf, bool depth_in = false,
constexpr ShaderConvertSelector(ShaderConvert shader = ShaderConvert::COPY, u8 mask = 0xf,
bool depth_out = false, bool biln = false)
: fields { static_cast<u32>(shader) }
{
*this = SetMask(mask).SetDepthInput(depth_in).SetDepthOutput(depth_out).SetBiln(biln);
*this = SetMask(mask).SetDepthOutput(depth_out).SetBiln(biln);
}
constexpr ShaderConvert Shader() const
@@ -301,11 +300,6 @@ public:
return fields.depth_out;
}
constexpr bool DepthInput() const
{
return fields.depth_in;
}
constexpr bool StencilOutput() const
{
return HasStencilOutput(Shader());
@@ -351,7 +345,7 @@ public:
return ShaderEntryPoint(Shader());
}
constexpr ShaderConvertSelector SetMask(u8 mask) const
constexpr ShaderConvertSelector SetMask(u8 mask = 0xf) const
{
ShaderConvertSelector tmp = *this;
tmp.fields.mask = VariableWriteMask() ? (mask & 0xf) : DefaultMask();
@@ -363,13 +357,6 @@ public:
return SetMask((wr ? 1 : 0) | (wg ? 2 : 0) | (wb ? 4 : 0) | (wa ? 8 : 0));
}
constexpr ShaderConvertSelector SetDepthInput(bool depth_in) const
{
ShaderConvertSelector tmp = *this;
tmp.fields.depth_in = Float32Input() && depth_in;
return tmp;
}
constexpr ShaderConvertSelector SetDepthOutput(bool depth_out) const
{
ShaderConvertSelector tmp = *this;
@@ -386,7 +373,7 @@ public:
GSTexture::Format OutputFormat() const
{
if (fields.depth_out)
if (DepthOutput())
return GSTexture::Format::DepthStencil;
else if (int bpp = IntegerOutputBpp())
return bpp == 16 ? GSTexture::Format::UInt16 : GSTexture::Format::UInt32;
@@ -403,7 +390,7 @@ public:
private:
// Helper variables for packing valid shaders into a contiguous range.
static const std::span<const ShaderConvertSelector> SHADERS;
static const std::array<u8, static_cast<u32>(ShaderConvert::Count) * 8> INDEX_REMAP;
static const std::array<u8, static_cast<u32>(ShaderConvert::Count) * 4> INDEX_REMAP;
static const u32 NUM_REMAPPED_SHADERS;
public:
@@ -412,12 +399,11 @@ public:
u32 Index() const
{
if (VariableWriteMask() && !fields.depth_in && !fields.depth_out && !fields.biln)
if (VariableWriteMask() && !fields.depth_out && !fields.biln)
return GetShaderIndexForMask(Shader(), fields.mask) + NUM_REMAPPED_SHADERS;
u32 remapped = INDEX_REMAP[(fields.depth_in << 0) +
(fields.depth_out << 1) +
(fields.biln << 2) +
(fields.shader << 3)];
u32 remapped = INDEX_REMAP[(fields.depth_out << 0) +
(fields.biln << 1) +
(fields.shader << 2)];
pxAssert(remapped < NUM_REMAPPED_SHADERS);
return remapped;
}
@@ -513,8 +499,7 @@ static inline ShaderConvertSelector GetConvertShader(GSTexture::Format src, GSTe
break;
}
return ShaderConvertSelector(shader, mask, src == GSTexture::Format::DepthStencil,
dst == GSTexture::Format::DepthStencil);
return ShaderConvertSelector(shader, mask, dst == GSTexture::Format::DepthStencil);
}
static inline ShaderConvertSelector GetConvertShader(const GSTexture* src, const GSTexture* dst, u32 src_bpp, u32 dst_bpp, u8 mask = 0xf)
+2 -3
View File
@@ -242,7 +242,6 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
sm_ps.AddMacro("HAS_BILN", static_cast<int>(shader.Biln()));
sm_ps.AddMacro("HAS_STENCIL_OUTPUT", static_cast<int>(shader.StencilOutput()));
sm_ps.AddMacro("HAS_INTEGER_OUTPUT", static_cast<int>(shader.IntegerOutputBpp() != 0));
sm_ps.AddMacro("HAS_DEPTH_INPUT", 0); // unused
sm_ps.AddMacro("HAS_DEPTH_OUTPUT", static_cast<int>(shader.DepthOutput()));
sm_ps.AddMacro("HAS_FLOAT32_INPUT", static_cast<int>(shader.Float32Input()));
sm_ps.AddMacro("HAS_FLOAT32_OUTPUT", static_cast<int>(shader.Float32Output()));
@@ -1413,7 +1412,7 @@ void GSDevice11::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextur
ShaderConvertSelector shader, bool linear)
{
const u8 mask = shader.Mask();
shader = ProcessShaderConvertSelector(shader); // Removes mask and depth output.
shader = shader.SetMask(); // Mask is handled separately from program.
DoStretchRect(sTex, sRect, dTex, dRect, GetConvertShader(shader), nullptr, m_convert.bs[mask].get(), linear);
}
@@ -1615,7 +1614,7 @@ void GSDevice11::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
void GSDevice11::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvertSelector shader)
{
shader = ProcessShaderConvertSelector(shader);
shader = shader.SetMask(); // Mask is handled separately from program.
IASetInputLayout(m_convert.il.get());
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
-5
View File
@@ -280,11 +280,6 @@ private:
protected:
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
ShaderConvertSelector shader, bool linear) override;
ShaderConvertSelector ProcessShaderConvertSelector(ShaderConvertSelector shader) const
{
// Depth input is handled same as color input. Mask is handled separately from program.
return shader.SetDepthInput(false).SetMask(0xf);
}
public:
GSDevice11();
~GSDevice11() override;
-4
View File
@@ -1672,7 +1672,6 @@ void GSDevice12::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextur
ShaderConvertSelector shader, bool linear)
{
pxAssert(dTex);
shader = ProcessShaderConvertSelector(shader); // Removes depth input
const bool allow_discard = (shader.Mask() == 0xf);
DoStretchRect(static_cast<GSTexture12*>(sTex), sRect, static_cast<GSTexture12*>(dTex), dRect,
GetConvertPipeline(shader), linear, allow_discard);
@@ -1768,8 +1767,6 @@ void GSDevice12::FilteredDownsampleTexture(GSTexture* sTex, GSTexture* dTex, u32
void GSDevice12::DrawMultiStretchRects(
const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvertSelector shader)
{
shader = ProcessShaderConvertSelector(shader); // Removes depth input
GSTexture* last_tex = rects[0].src;
bool last_linear = rects[0].linear;
u8 last_wmask = rects[0].wmask.wrgba;
@@ -2766,7 +2763,6 @@ bool GSDevice12::CompileConvertPipelines()
sm.AddMacro("HAS_BILN", static_cast<int>(shader.Biln()));
sm.AddMacro("HAS_STENCIL_OUTPUT", static_cast<int>(shader.StencilOutput()));
sm.AddMacro("HAS_INTEGER_OUTPUT", static_cast<int>(shader.IntegerOutputBpp() != 0));
sm.AddMacro("HAS_DEPTH_INPUT", 0); // unused
sm.AddMacro("HAS_DEPTH_OUTPUT", static_cast<int>(shader.DepthOutput()));
sm.AddMacro("HAS_FLOAT32_INPUT", static_cast<int>(shader.Float32Input()));
sm.AddMacro("HAS_FLOAT32_OUTPUT", static_cast<int>(shader.Float32Output()));
-5
View File
@@ -443,11 +443,6 @@ protected:
ShaderConvertSelector shader, bool linear) override;
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, const GSVector4& dRect,
PresentShader shader, bool linear) override;
ShaderConvertSelector ProcessShaderConvertSelector(ShaderConvertSelector shader) const
{
// Depth input handled same as color input.
return shader.SetDepthInput(false);
}
public:
GSDevice12();
~GSDevice12() override;
-3
View File
@@ -1209,8 +1209,6 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
name = [name stringByAppendingString:[NSString stringWithFormat:@" Mask=%x", shader.Mask()]];
if (shader.Biln())
name = [name stringByAppendingString:@" Biln"];
if (shader.Float32Input())
name = [name stringByAppendingString:shader.DepthInput() ? @" Depth" : @" Float"];
if (shader.Float32Output())
name = [name stringByAppendingString:shader.DepthOutput() ? @" → Depth" : @" → Float"];
@@ -1222,7 +1220,6 @@ bool GSDeviceMTL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
if (scmask & 8) mask |= MTLColorWriteMaskAlpha;
pdesc.colorAttachments[0].writeMask = mask;
setFnConstantB(m_fn_constants, shader.Biln(), GSMTLConstantIndex_BILN);
setFnConstantB(m_fn_constants, shader.DepthInput(), GSMTLConstantIndex_DEPTH_IN);
setFnConstantB(m_fn_constants, shader.DepthOutput(), GSMTLConstantIndex_DEPTH_OUT);
m_convert_pipeline[shader.Index()] = MakePipeline(pdesc, vs_convert, LoadShader(shader_name), name);
}
@@ -156,7 +156,6 @@ enum GSMTLAttributes
enum GSMTLFnConstants
{
GSMTLConstantIndex_BILN,
GSMTLConstantIndex_DEPTH_IN,
GSMTLConstantIndex_DEPTH_OUT,
GSMTLConstantIndex_CAS_SHARPEN_ONLY,
GSMTLConstantIndex_FRAMEBUFFER_FETCH,
+2 -5
View File
@@ -6,9 +6,7 @@
using namespace metal;
constant bool BILN [[function_constant(GSMTLConstantIndex_BILN)]];
constant bool DEPTH_IN [[function_constant(GSMTLConstantIndex_DEPTH_IN)]];
constant bool DEPTH_OUT [[function_constant(GSMTLConstantIndex_DEPTH_OUT)]];
constant bool COLOR_IN = !DEPTH_IN;
constant bool COLOR_OUT = !DEPTH_OUT;
struct ConvertVSIn
@@ -229,12 +227,11 @@ struct DepthOrColorOut
struct ConvertPSDepthOrColorRes
{
texture2d<float> color [[texture(GSMTLTextureIndexNonHW), function_constant(COLOR_IN)]];
depth2d<float> depth [[texture(GSMTLTextureIndexNonHW), function_constant(DEPTH_IN)]];
texture2d<float> texture [[texture(GSMTLTextureIndexNonHW)]];
sampler s [[sampler(0)]];
float sample(float2 coord)
{
return COLOR_IN ? color.sample(s, coord).x : depth.sample(s, coord);
return texture.sample(s, coord).x;
}
};
+2 -3
View File
@@ -427,7 +427,6 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
macro += fmt::format("#define HAS_BILN {}\n", static_cast<int>(shader.Biln()));
macro += fmt::format("#define HAS_STENCIL_OUTPUT {}\n", static_cast<int>(shader.StencilOutput()));
macro += fmt::format("#define HAS_INTEGER_OUTPUT {}\n", static_cast<int>(shader.IntegerOutputBpp() != 0));
macro += fmt::format("#define HAS_DEPTH_INPUT {}\n", 0); // unused
macro += fmt::format("#define HAS_DEPTH_OUTPUT {}\n", static_cast<int>(shader.DepthOutput()));
macro += fmt::format("#define HAS_FLOAT32_INPUT {}\n", static_cast<int>(shader.Float32Input()));
macro += fmt::format("#define HAS_FLOAT32_OUTPUT {}\n", static_cast<int>(shader.Float32Output()));
@@ -1677,7 +1676,7 @@ void GSDeviceOGL::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextu
ShaderConvertSelector shader, bool linear)
{
const u8 mask = shader.Mask();
shader = ProcessShaderConvertSelector(shader); // Removes mask and depth input.
shader = shader.SetMask(); // Mask is handled separately from program.
DoStretchRect(sTex, sRect, dTex, dRect, GetConvertProgram(shader), false, OMColorMaskSelector(mask), linear);
}
@@ -1868,7 +1867,7 @@ void GSDeviceOGL::DrawStretchRect(const GSVector4& sRect, const GSVector4& dRect
void GSDeviceOGL::DrawMultiStretchRects(
const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvertSelector shader)
{
shader = ProcessShaderConvertSelector(shader);
shader = shader.SetMask(); // Mask is handled separately from program.
IASetVAO(m_vao);
IASetPrimitiveTopology(GL_TRIANGLE_STRIP);
-5
View File
@@ -291,11 +291,6 @@ private:
protected:
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect,
ShaderConvertSelector shader, bool linear) override;
virtual ShaderConvertSelector ProcessShaderConvertSelector(ShaderConvertSelector shader) const
{
// Depth input is handled same as color. Color mask is handled separately.
return shader.SetDepthInput(false).SetMask(0xf);
}
public:
GSDeviceOGL();
virtual ~GSDeviceOGL();
-4
View File
@@ -2925,7 +2925,6 @@ void GSDeviceVK::DoStretchRect(GSTexture* sTex, const GSVector4& sRect, GSTextur
ShaderConvertSelector shader, bool linear)
{
pxAssert(dTex);
shader = ProcessShaderConvertSelector(shader); // Removes depth input
const bool allow_discard = (shader.Mask() == 0xf);
DoStretchRect(static_cast<GSTextureVK*>(sTex), sRect, static_cast<GSTextureVK*>(dTex), dRect,
GetConvertPipeline(shader), linear, allow_discard);
@@ -2954,8 +2953,6 @@ void GSDeviceVK::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
void GSDeviceVK::DrawMultiStretchRects(
const MultiStretchRect* rects, u32 num_rects, GSTexture* dTex, ShaderConvertSelector shader)
{
shader = ProcessShaderConvertSelector(shader); // Removes depth input
GSTexture* last_tex = rects[0].src;
bool last_linear = rects[0].linear;
u8 last_wmask = rects[0].wmask.wrgba;
@@ -4077,7 +4074,6 @@ bool GSDeviceVK::CompileConvertPipelines()
macro += fmt::format("#define HAS_BILN {}\n", static_cast<int>(shader.Biln()));
macro += fmt::format("#define HAS_STENCIL_OUTPUT {}\n", static_cast<int>(shader.StencilOutput()));
macro += fmt::format("#define HAS_INTEGER_OUTPUT {}\n", static_cast<int>(shader.IntegerOutputBpp() != 0));
macro += fmt::format("#define HAS_DEPTH_INPUT {}\n", 0); // unused
macro += fmt::format("#define HAS_DEPTH_OUTPUT {}\n", static_cast<int>(shader.DepthOutput()));
macro += fmt::format("#define HAS_FLOAT32_INPUT {}\n", static_cast<int>(shader.Float32Input()));
macro += fmt::format("#define HAS_FLOAT32_OUTPUT {}\n", static_cast<int>(shader.Float32Output()));
-5
View File
@@ -495,11 +495,6 @@ protected:
ShaderConvertSelector shader, bool linear) override;
virtual void DoStretchRect(GSTexture* sTex, const GSVector4& sRect, const GSVector4& dRect,
PresentShader shader, bool linear) override;
ShaderConvertSelector ProcessShaderConvertSelector(ShaderConvertSelector shader) const
{
// Depth input handled same as color input.
return shader.SetDepthInput(false);
}
public:
GSDeviceVK();
~GSDeviceVK() override;
+1 -1
View File
@@ -3,4 +3,4 @@
/// Version number for GS and other shaders. Increment whenever any of the contents of the
/// shaders change, to invalidate the cache.
static constexpr u32 SHADER_CACHE_VERSION = 97; // Last changed in PR 14477
static constexpr u32 SHADER_CACHE_VERSION = 98; // Last changed in PR 14477