Multisample Blits

Partially fixes Sonic Colors Ultimate
This commit is contained in:
Isaac Marovitz 2024-07-24 21:53:17 +01:00
parent bdcc2fd90e
commit 10110198f7
No known key found for this signature in database
GPG Key ID: 97250B2B09A132E1
6 changed files with 81 additions and 25 deletions

View File

@ -1,4 +1,5 @@
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation;
@ -21,6 +22,7 @@ namespace Ryujinx.Graphics.Metal
private readonly ISampler _samplerLinear;
private readonly ISampler _samplerNearest;
private readonly IProgram _programColorBlit;
private readonly IProgram _programColorBlitMs;
private readonly List<IProgram> _programsColorClear = new();
private readonly IProgram _programDepthStencilClear;
private readonly IProgram _programStrideChange;
@ -47,6 +49,13 @@ namespace Ryujinx.Graphics.Metal
new ShaderSource(blitSource, ShaderStage.Vertex, TargetLanguage.Msl)
], 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()
.Add(ResourceStages.Fragment, ResourceType.UniformBuffer, 0).Build();
@ -87,8 +96,8 @@ namespace Ryujinx.Graphics.Metal
public unsafe void BlitColor(
CommandBufferScoped cbs,
ITexture src,
ITexture dst,
Texture src,
Texture dst,
Extents2D srcRegion,
Extents2D dstRegion,
bool linearFilter,
@ -140,7 +149,23 @@ namespace Ryujinx.Graphics.Metal
0f,
1f);
_pipeline.SetProgram(_programColorBlit);
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);
}
int dstWidth = dst.Width;
int dstHeight = dst.Height;

View File

@ -193,22 +193,13 @@ namespace Ryujinx.Graphics.Metal
}
public void Blit(
ITexture src,
ITexture dst,
Texture src,
Texture dst,
Extents2D srcRegion,
Extents2D dstRegion,
bool isDepthOrStencil,
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()

View File

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

View File

@ -12,7 +12,7 @@ struct TexCoords {
};
struct ConstantBuffers {
constant TexCoords* texCoord;
constant TexCoords* tex_coord;
};
struct Textures
@ -27,8 +27,8 @@ vertex CopyVertexOut vertexMain(uint vid [[vertex_id]],
int low = vid & 1;
int high = vid >> 1;
out.uv.x = constant_buffers.texCoord->data[low];
out.uv.y = constant_buffers.texCoord->data[2 + high];
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;

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;
bool isDepthOrStencil = dst.Info.Format.IsDepthOrStencil();
if (dst.Info.IsCompressed)
{
Console.WriteLine("shit");
}
Pipeline.Blit(this, destination, srcRegion, dstRegion, isDepthOrStencil, linearFilter);
Pipeline.Blit(this, dst, srcRegion, dstRegion, linearFilter);
}
public void CopyTo(BufferRange range, int layer, int level, int stride)