Helper Shader fixes for non float formats

This commit is contained in:
Isaac Marovitz 2024-08-01 00:37:37 +01:00 committed by Isaac Marovitz
parent 4cd15cb1a6
commit 245778bc7e
5 changed files with 166 additions and 31 deletions

View file

@ -21,9 +21,15 @@ namespace Ryujinx.Graphics.Metal
private readonly ISampler _samplerLinear; private readonly ISampler _samplerLinear;
private readonly ISampler _samplerNearest; private readonly ISampler _samplerNearest;
private readonly IProgram _programColorBlit; private readonly IProgram _programColorBlitF;
private readonly IProgram _programColorBlitMs; private readonly IProgram _programColorBlitI;
private readonly List<IProgram> _programsColorClear = new(); private readonly IProgram _programColorBlitU;
private readonly IProgram _programColorBlitMsF;
private readonly IProgram _programColorBlitMsI;
private readonly IProgram _programColorBlitMsU;
private readonly List<IProgram> _programsColorClearF = new();
private readonly List<IProgram> _programsColorClearI = new();
private readonly List<IProgram> _programsColorClearU = new();
private readonly IProgram _programDepthStencilClear; private readonly IProgram _programDepthStencilClear;
private readonly IProgram _programStrideChange; private readonly IProgram _programStrideChange;
private readonly IProgram _programDepthBlit; private readonly IProgram _programDepthBlit;
@ -47,27 +53,80 @@ namespace Ryujinx.Graphics.Metal
.Add(ResourceStages.Fragment, ResourceType.TextureAndSampler, 0).Build(); .Add(ResourceStages.Fragment, ResourceType.TextureAndSampler, 0).Build();
var blitSource = ReadMsl("Blit.metal"); var blitSource = ReadMsl("Blit.metal");
_programColorBlit = new Program(
var blitSourceF = blitSource.Replace("FORMAT", "float", StringComparison.Ordinal);
_programColorBlitF = new Program(
[ [
new ShaderSource(blitSource, ShaderStage.Fragment, TargetLanguage.Msl), new ShaderSource(blitSourceF, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl) new ShaderSource(blitSourceF, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device);
var blitSourceI = blitSource.Replace("FORMAT", "int");
_programColorBlitI = new Program(
[
new ShaderSource(blitSourceI, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitSourceI, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device);
var blitSourceU = blitSource.Replace("FORMAT", "uint");
_programColorBlitU = new Program(
[
new ShaderSource(blitSourceU, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitSourceU, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device); ], blitResourceLayout, device);
var blitMsSource = ReadMsl("BlitMs.metal"); var blitMsSource = ReadMsl("BlitMs.metal");
_programColorBlitMs = new Program(
var blitMsSourceF = blitMsSource.Replace("FORMAT", "float");
_programColorBlitMsF = new Program(
[ [
new ShaderSource(blitMsSource, ShaderStage.Fragment, TargetLanguage.Msl), new ShaderSource(blitMsSourceF, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl) new ShaderSource(blitMsSourceF, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device);
var blitMsSourceI = blitMsSource.Replace("FORMAT", "int");
_programColorBlitMsI = new Program(
[
new ShaderSource(blitMsSourceI, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitMsSourceI, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device);
var blitMsSourceU = blitMsSource.Replace("FORMAT", "uint");
_programColorBlitMsU = new Program(
[
new ShaderSource(blitMsSourceU, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitMsSourceU, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device); ], blitResourceLayout, device);
var colorClearResourceLayout = new ResourceLayoutBuilder() var colorClearResourceLayout = new ResourceLayoutBuilder()
.Add(ResourceStages.Fragment, ResourceType.UniformBuffer, 0).Build(); .Add(ResourceStages.Fragment, ResourceType.UniformBuffer, 0).Build();
var colorClearSource = ReadMsl("ColorClear.metal"); var colorClearSource = ReadMsl("ColorClear.metal");
for (int i = 0; i < Constants.MaxColorAttachments; i++) for (int i = 0; i < Constants.MaxColorAttachments; i++)
{ {
var crntSource = colorClearSource.Replace("COLOR_ATTACHMENT_INDEX", i.ToString()); var crntSource = colorClearSource.Replace("COLOR_ATTACHMENT_INDEX", i.ToString()).Replace("FORMAT", "float");
_programsColorClear.Add(new Program( _programsColorClearF.Add(new Program(
[
new ShaderSource(crntSource, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(crntSource, ShaderStage.Vertex, TargetLanguage.Msl)
], colorClearResourceLayout, device));
}
for (int i = 0; i < Constants.MaxColorAttachments; i++)
{
var crntSource = colorClearSource.Replace("COLOR_ATTACHMENT_INDEX", i.ToString()).Replace("FORMAT", "int");
_programsColorClearI.Add(new Program(
[
new ShaderSource(crntSource, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(crntSource, ShaderStage.Vertex, TargetLanguage.Msl)
], colorClearResourceLayout, device));
}
for (int i = 0; i < Constants.MaxColorAttachments; i++)
{
var crntSource = colorClearSource.Replace("COLOR_ATTACHMENT_INDEX", i.ToString()).Replace("FORMAT", "uint");
_programsColorClearU.Add(new Program(
[ [
new ShaderSource(crntSource, ShaderStage.Fragment, TargetLanguage.Msl), new ShaderSource(crntSource, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(crntSource, ShaderStage.Vertex, TargetLanguage.Msl) new ShaderSource(crntSource, ShaderStage.Vertex, TargetLanguage.Msl)
@ -96,28 +155,28 @@ namespace Ryujinx.Graphics.Metal
_programDepthBlit = new Program( _programDepthBlit = new Program(
[ [
new ShaderSource(depthBlitSource, ShaderStage.Fragment, TargetLanguage.Msl), new ShaderSource(depthBlitSource, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl) new ShaderSource(blitSourceF, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device); ], blitResourceLayout, device);
var depthBlitMsSource = ReadMsl("DepthBlitMs.metal"); var depthBlitMsSource = ReadMsl("DepthBlitMs.metal");
_programDepthBlitMs = new Program( _programDepthBlitMs = new Program(
[ [
new ShaderSource(depthBlitMsSource, ShaderStage.Fragment, TargetLanguage.Msl), new ShaderSource(depthBlitMsSource, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl) new ShaderSource(blitSourceF, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device); ], blitResourceLayout, device);
var stencilBlitSource = ReadMsl("StencilBlit.metal"); var stencilBlitSource = ReadMsl("StencilBlit.metal");
_programStencilBlit = new Program( _programStencilBlit = new Program(
[ [
new ShaderSource(stencilBlitSource, ShaderStage.Fragment, TargetLanguage.Msl), new ShaderSource(stencilBlitSource, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl) new ShaderSource(blitSourceF, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device); ], blitResourceLayout, device);
var stencilBlitMsSource = ReadMsl("StencilBlitMs.metal"); var stencilBlitMsSource = ReadMsl("StencilBlitMs.metal");
_programStencilBlitMs = new Program( _programStencilBlitMs = new Program(
[ [
new ShaderSource(stencilBlitMsSource, ShaderStage.Fragment, TargetLanguage.Msl), new ShaderSource(stencilBlitMsSource, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl) new ShaderSource(blitSourceF, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device); ], blitResourceLayout, device);
} }
@ -201,11 +260,33 @@ namespace Ryujinx.Graphics.Metal
} }
else if (src.Info.Target.IsMultisample()) else if (src.Info.Target.IsMultisample())
{ {
_pipeline.SetProgram(_programColorBlitMs); if (dst.Info.Format.IsSint())
{
_pipeline.SetProgram(_programColorBlitMsI);
}
else if (dst.Info.Format.IsUint())
{
_pipeline.SetProgram(_programColorBlitMsU);
}
else
{
_pipeline.SetProgram(_programColorBlitMsF);
}
} }
else else
{ {
_pipeline.SetProgram(_programColorBlit); if (dst.Info.Format.IsSint())
{
_pipeline.SetProgram(_programColorBlitI);
}
else if (dst.Info.Format.IsUint())
{
_pipeline.SetProgram(_programColorBlitU);
}
else
{
_pipeline.SetProgram(_programColorBlitF);
}
} }
int dstWidth = dst.Width; int dstWidth = dst.Width;
@ -438,7 +519,7 @@ namespace Ryujinx.Graphics.Metal
0f, 0f,
1f); 1f);
_pipeline.SetProgram(_programColorBlit); _pipeline.SetProgram(_programColorBlitF);
_pipeline.SetViewports(viewports); _pipeline.SetViewports(viewports);
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
_pipeline.Draw(4, 1, 0, 0); _pipeline.Draw(4, 1, 0, 0);
@ -502,7 +583,8 @@ namespace Ryujinx.Graphics.Metal
ReadOnlySpan<float> clearColor, ReadOnlySpan<float> clearColor,
uint componentMask, uint componentMask,
int dstWidth, int dstWidth,
int dstHeight) int dstHeight,
Format format)
{ {
// Keep original scissor // Keep original scissor
DirtyFlags clearFlags = DirtyFlags.All & (~DirtyFlags.Scissors); DirtyFlags clearFlags = DirtyFlags.All & (~DirtyFlags.Scissors);
@ -536,7 +618,19 @@ namespace Ryujinx.Graphics.Metal
Span<uint> componentMasks = stackalloc uint[index + 1]; Span<uint> componentMasks = stackalloc uint[index + 1];
componentMasks[index] = componentMask; componentMasks[index] = componentMask;
_pipeline.SetProgram(_programsColorClear[index]); if (format.IsSint())
{
_pipeline.SetProgram(_programsColorClearI[index]);
}
else if (format.IsUint())
{
_pipeline.SetProgram(_programsColorClearU[index]);
}
else
{
_pipeline.SetProgram(_programsColorClearF[index]);
}
_pipeline.SetBlendState(index, new BlendDescriptor()); _pipeline.SetBlendState(index, new BlendDescriptor());
_pipeline.SetFaceCulling(false, Face.Front); _pipeline.SetFaceCulling(false, Face.Front);
_pipeline.SetDepthTest(new DepthTestDescriptor(false, false, CompareOp.Always)); _pipeline.SetDepthTest(new DepthTestDescriptor(false, false, CompareOp.Always));
@ -630,11 +724,28 @@ namespace Ryujinx.Graphics.Metal
public void Dispose() public void Dispose()
{ {
_programColorBlit.Dispose(); _programColorBlitF.Dispose();
foreach (var programColorClear in _programsColorClear) _programColorBlitI.Dispose();
_programColorBlitU.Dispose();
_programColorBlitMsF.Dispose();
_programColorBlitMsI.Dispose();
_programColorBlitMsU.Dispose();
foreach (var programColorClear in _programsColorClearF)
{ {
programColorClear.Dispose(); programColorClear.Dispose();
} }
foreach (var programColorClear in _programsColorClearU)
{
programColorClear.Dispose();
}
foreach (var programColorClear in _programsColorClearI)
{
programColorClear.Dispose();
}
_programDepthStencilClear.Dispose(); _programDepthStencilClear.Dispose();
_pipeline.Dispose(); _pipeline.Dispose();
_samplerLinear.Dispose(); _samplerLinear.Dispose();

View file

@ -269,7 +269,7 @@ namespace Ryujinx.Graphics.Metal
return; return;
} }
_renderer.HelperShader.ClearColor(index, colors, componentMask, dst.Width, dst.Height); _renderer.HelperShader.ClearColor(index, colors, componentMask, dst.Width, dst.Height, dst.Info.Format);
} }
public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)

View file

@ -17,7 +17,7 @@ struct ConstantBuffers {
struct Textures struct Textures
{ {
texture2d<float, access::sample> texture; texture2d<FORMAT, access::sample> texture;
sampler sampler; sampler sampler;
}; };
@ -37,7 +37,7 @@ vertex CopyVertexOut vertexMain(uint vid [[vertex_id]],
return out; return out;
} }
fragment float4 fragmentMain(CopyVertexOut in [[stage_in]], fragment FORMAT4 fragmentMain(CopyVertexOut in [[stage_in]],
constant Textures &textures [[buffer(TEXTURES_INDEX)]]) { constant Textures &textures [[buffer(TEXTURES_INDEX)]]) {
return textures.texture.sample(textures.sampler, in.uv); return textures.texture.sample(textures.sampler, in.uv);
} }

View file

@ -7,12 +7,36 @@ struct CopyVertexOut {
float2 uv; float2 uv;
}; };
struct Textures struct TexCoords {
{ float data[4];
texture2d_ms<float, access::read> texture;
}; };
fragment float4 fragmentMain(CopyVertexOut in [[stage_in]], struct ConstantBuffers {
constant TexCoords* tex_coord;
};
struct Textures
{
texture2d_ms<FORMAT, access::read> texture;
};
vertex CopyVertexOut vertexMain(uint vid [[vertex_id]],
constant ConstantBuffers &constant_buffers [[buffer(CONSTANT_BUFFERS_INDEX)]]) {
CopyVertexOut out;
int low = vid & 1;
int high = vid >> 1;
out.uv.x = constant_buffers.tex_coord->data[low];
out.uv.y = constant_buffers.tex_coord->data[2 + high];
out.position.x = (float(low) - 0.5f) * 2.0f;
out.position.y = (float(high) - 0.5f) * 2.0f;
out.position.z = 0.0f;
out.position.w = 1.0f;
return out;
}
fragment FORMAT4 fragmentMain(CopyVertexOut in [[stage_in]],
constant Textures &textures [[buffer(TEXTURES_INDEX)]], constant Textures &textures [[buffer(TEXTURES_INDEX)]],
uint sample_id [[sample_id]]) { uint sample_id [[sample_id]]) {
uint2 tex_size = uint2(textures.texture.get_width(), textures.texture.get_height()); uint2 tex_size = uint2(textures.texture.get_width(), textures.texture.get_height());

View file

@ -7,7 +7,7 @@ struct VertexOut {
}; };
struct ClearColor { struct ClearColor {
float4 data; FORMAT4 data;
}; };
struct ConstantBuffers { struct ConstantBuffers {
@ -29,7 +29,7 @@ vertex VertexOut vertexMain(ushort vid [[vertex_id]]) {
} }
struct FragmentOut { struct FragmentOut {
float4 color [[color(COLOR_ATTACHMENT_INDEX)]]; FORMAT4 color [[color(COLOR_ATTACHMENT_INDEX)]];
}; };
fragment FragmentOut fragmentMain(VertexOut in [[stage_in]], fragment FragmentOut fragmentMain(VertexOut in [[stage_in]],