diff --git a/src/Ryujinx.Graphics.Metal/HelperShader.cs b/src/Ryujinx.Graphics.Metal/HelperShader.cs index 647e4ba8b..270a628dc 100644 --- a/src/Ryujinx.Graphics.Metal/HelperShader.cs +++ b/src/Ryujinx.Graphics.Metal/HelperShader.cs @@ -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 _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; diff --git a/src/Ryujinx.Graphics.Metal/Pipeline.cs b/src/Ryujinx.Graphics.Metal/Pipeline.cs index 00ca85b56..00020267b 100644 --- a/src/Ryujinx.Graphics.Metal/Pipeline.cs +++ b/src/Ryujinx.Graphics.Metal/Pipeline.cs @@ -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() diff --git a/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj b/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj index f4e98cd45..8b6de05f3 100644 --- a/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj +++ b/src/Ryujinx.Graphics.Metal/Ryujinx.Graphics.Metal.csproj @@ -16,6 +16,7 @@ + diff --git a/src/Ryujinx.Graphics.Metal/Shaders/Blit.metal b/src/Ryujinx.Graphics.Metal/Shaders/Blit.metal index 37962bbf7..a5e4e8170 100644 --- a/src/Ryujinx.Graphics.Metal/Shaders/Blit.metal +++ b/src/Ryujinx.Graphics.Metal/Shaders/Blit.metal @@ -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; diff --git a/src/Ryujinx.Graphics.Metal/Shaders/BlitMs.metal b/src/Ryujinx.Graphics.Metal/Shaders/BlitMs.metal new file mode 100644 index 000000000..b8e01ffe8 --- /dev/null +++ b/src/Ryujinx.Graphics.Metal/Shaders/BlitMs.metal @@ -0,0 +1,45 @@ +#include + +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 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); +} diff --git a/src/Ryujinx.Graphics.Metal/Texture.cs b/src/Ryujinx.Graphics.Metal/Texture.cs index fa5def60b..9392b5e6d 100644 --- a/src/Ryujinx.Graphics.Metal/Texture.cs +++ b/src/Ryujinx.Graphics.Metal/Texture.cs @@ -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)