Multisample Blits

Partially fixes Sonic Colors Ultimate
This commit is contained in:
Isaac Marovitz 2024-07-24 21:53:17 +01:00 committed by Isaac Marovitz
parent b434cae2c2
commit aa6e87e8a6
6 changed files with 81 additions and 25 deletions

View file

@ -1,4 +1,5 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
@ -21,6 +22,7 @@ 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 _programColorBlit;
private readonly IProgram _programColorBlitMs;
private readonly List<IProgram> _programsColorClear = new(); private readonly List<IProgram> _programsColorClear = new();
private readonly IProgram _programDepthStencilClear; private readonly IProgram _programDepthStencilClear;
private readonly IProgram _programStrideChange; private readonly IProgram _programStrideChange;
@ -47,6 +49,13 @@ namespace Ryujinx.Graphics.Metal
new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl) new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device); ], blitResourceLayout, device);
var blitMsSource = ReadMsl("BlitMs.metal");
_programColorBlitMs = new Program(
[
new ShaderSource(blitMsSource, ShaderStage.Fragment, TargetLanguage.Msl),
new ShaderSource(blitMsSource, ShaderStage.Vertex, TargetLanguage.Msl)
], blitResourceLayout, device);
var colorClearResourceLayout = new ResourceLayoutBuilder() var colorClearResourceLayout = new ResourceLayoutBuilder()
.Add(ResourceStages.Fragment, ResourceType.UniformBuffer, 0).Build(); .Add(ResourceStages.Fragment, ResourceType.UniformBuffer, 0).Build();
@ -87,8 +96,8 @@ namespace Ryujinx.Graphics.Metal
public unsafe void BlitColor( public unsafe void BlitColor(
CommandBufferScoped cbs, CommandBufferScoped cbs,
ITexture src, Texture src,
ITexture dst, Texture dst,
Extents2D srcRegion, Extents2D srcRegion,
Extents2D dstRegion, Extents2D dstRegion,
bool linearFilter, bool linearFilter,
@ -140,7 +149,23 @@ namespace Ryujinx.Graphics.Metal
0f, 0f,
1f); 1f);
bool dstIsDepthOrStencil = dst.Info.Format.IsDepthOrStencil();
if (dstIsDepthOrStencil)
{
// TODO: Depth & stencil blit!
Logger.Warning?.PrintMsg(LogClass.Gpu, "Requested a depth or stencil blit!");
_pipeline.SwapState(null);
return;
}
else if (src.Info.Target.IsMultisample())
{
_pipeline.SetProgram(_programColorBlitMs);
}
else
{
_pipeline.SetProgram(_programColorBlit); _pipeline.SetProgram(_programColorBlit);
}
int dstWidth = dst.Width; int dstWidth = dst.Width;
int dstHeight = dst.Height; int dstHeight = dst.Height;

View file

@ -193,23 +193,14 @@ namespace Ryujinx.Graphics.Metal
} }
public void Blit( public void Blit(
ITexture src, Texture src,
ITexture dst, Texture dst,
Extents2D srcRegion, Extents2D srcRegion,
Extents2D dstRegion, Extents2D dstRegion,
bool isDepthOrStencil,
bool linearFilter) bool linearFilter)
{
if (isDepthOrStencil)
{
// TODO: Depth & stencil blit!
Logger.Warning?.PrintMsg(LogClass.Gpu, "Requested a depth or stencil blit!");
}
else
{ {
_renderer.HelperShader.BlitColor(Cbs, src, dst, srcRegion, dstRegion, linearFilter); _renderer.HelperShader.BlitColor(Cbs, src, dst, srcRegion, dstRegion, linearFilter);
} }
}
public void Barrier() public void Barrier()
{ {

View file

@ -16,6 +16,7 @@
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Shaders\Blit.metal" /> <EmbeddedResource Include="Shaders\Blit.metal" />
<EmbeddedResource Include="Shaders\BlitMs.metal" />
<EmbeddedResource Include="Shaders\ChangeBufferStride.metal" /> <EmbeddedResource Include="Shaders\ChangeBufferStride.metal" />
<EmbeddedResource Include="Shaders\ColorClear.metal" /> <EmbeddedResource Include="Shaders\ColorClear.metal" />
<EmbeddedResource Include="Shaders\DepthStencilClear.metal" /> <EmbeddedResource Include="Shaders\DepthStencilClear.metal" />

View file

@ -12,7 +12,7 @@ struct TexCoords {
}; };
struct ConstantBuffers { struct ConstantBuffers {
constant TexCoords* texCoord; constant TexCoords* tex_coord;
}; };
struct Textures struct Textures
@ -27,8 +27,8 @@ vertex CopyVertexOut vertexMain(uint vid [[vertex_id]],
int low = vid & 1; int low = vid & 1;
int high = vid >> 1; int high = vid >> 1;
out.uv.x = constant_buffers.texCoord->data[low]; out.uv.x = constant_buffers.tex_coord->data[low];
out.uv.y = constant_buffers.texCoord->data[2 + high]; out.uv.y = constant_buffers.tex_coord->data[2 + high];
out.position.x = (float(low) - 0.5f) * 2.0f; out.position.x = (float(low) - 0.5f) * 2.0f;
out.position.y = (float(high) - 0.5f) * 2.0f; out.position.y = (float(high) - 0.5f) * 2.0f;
out.position.z = 0.0f; out.position.z = 0.0f;

View file

@ -0,0 +1,45 @@
#include <metal_stdlib>
using namespace metal;
struct CopyVertexOut {
float4 position [[position]];
float2 uv;
};
struct TexCoords {
float data[4];
};
struct ConstantBuffers {
constant TexCoords* tex_coord;
};
struct Textures
{
texture2d_ms<float, access::read> texture;
};
vertex CopyVertexOut vertexMain(uint vid [[vertex_id]],
constant ConstantBuffers &constant_buffers [[buffer(20)]]) {
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 float4 fragmentMain(CopyVertexOut in [[stage_in]],
constant Textures &textures [[buffer(22)]],
uint sample_id [[sample_id]]) {
uint2 tex_size = uint2(textures.texture.get_width(), textures.texture.get_height());
uint2 tex_coord = uint2(in.uv * float2(tex_size));
return textures.texture.read(tex_coord, sample_id);
}

View file

@ -249,14 +249,8 @@ namespace Ryujinx.Graphics.Metal
} }
var dst = (Texture)destination; var dst = (Texture)destination;
bool isDepthOrStencil = dst.Info.Format.IsDepthOrStencil();
if (dst.Info.IsCompressed) Pipeline.Blit(this, dst, srcRegion, dstRegion, linearFilter);
{
Console.WriteLine("shit");
}
Pipeline.Blit(this, destination, srcRegion, dstRegion, isDepthOrStencil, linearFilter);
} }
public void CopyTo(BufferRange range, int layer, int level, int stride) public void CopyTo(BufferRange range, int layer, int level, int stride)