Revert the Metal Experiment (#701)

Metal sounded like a good idea to get in the emulator but frankly I
underestimated just how experimental and not ready it was.
From my write up in the Discord:
```
As is, Metal supports only a few games.
The games it does support freeze on first use of not playing them via Vulkan, because shader translation is broken.
So you need to use a dirty hack to not delete all your shaders.
Not to mention it breaks many games via MoltenVK because of changes to the shared GPU code.

Merging Metal seemed like a great idea, because of the few games it does support.
But I don't think it's worth it. Many of the games it breaks via MoltenVK *don't work via Metal*. 
Which effectively makes current Ryubing worse for Mac users than Ryujinx 1.1.1403.

I think what I'm gonna do is revert Metal, and reopen it as a PR. That way, you can still take advantage of the Metal backend as is, but without making other games worse with no solution.
```

For what it's worth, the shader translation part could at least be
"fixed" by always applying a 30ms delay for shader translation to Metal.
That being said, that solution sucks ass.
The MoltenVK regressions are even worse.



I hope this is not a let down to the Mac users. I hope you realize I'm
reverting this because you're actively getting a worse experience with
it in the emulator.
This commit is contained in:
Evan Husted
2025-02-22 21:26:46 -06:00
committed by GitHub
parent eb6b0e9adc
commit fe1617ffea
135 changed files with 302 additions and 15077 deletions

View File

@@ -1,43 +0,0 @@
#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<FORMAT, access::sample> texture;
sampler sampler;
};
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)]]) {
return textures.texture.sample(textures.sampler, in.uv);
}

View File

@@ -1,45 +0,0 @@
#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<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)]],
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

@@ -1,72 +0,0 @@
#include <metal_stdlib>
using namespace metal;
struct StrideArguments {
int4 data;
};
struct InData {
uint8_t data[1];
};
struct OutData {
uint8_t data[1];
};
struct ConstantBuffers {
constant StrideArguments* stride_arguments;
};
struct StorageBuffers {
device InData* in_data;
device OutData* out_data;
};
kernel void kernelMain(constant ConstantBuffers &constant_buffers [[buffer(CONSTANT_BUFFERS_INDEX)]],
device StorageBuffers &storage_buffers [[buffer(STORAGE_BUFFERS_INDEX)]],
uint3 thread_position_in_grid [[thread_position_in_grid]],
uint3 threads_per_threadgroup [[threads_per_threadgroup]],
uint3 threadgroups_per_grid [[threadgroups_per_grid]])
{
// Determine what slice of the stride copies this invocation will perform.
int sourceStride = constant_buffers.stride_arguments->data.x;
int targetStride = constant_buffers.stride_arguments->data.y;
int bufferSize = constant_buffers.stride_arguments->data.z;
int sourceOffset = constant_buffers.stride_arguments->data.w;
int strideRemainder = targetStride - sourceStride;
int invocations = int(threads_per_threadgroup.x * threadgroups_per_grid.x);
int copiesRequired = bufferSize / sourceStride;
// Find the copies that this invocation should perform.
// - Copies that all invocations perform.
int allInvocationCopies = copiesRequired / invocations;
// - Extra remainder copy that this invocation performs.
int index = int(thread_position_in_grid.x);
int extra = (index < (copiesRequired % invocations)) ? 1 : 0;
int copyCount = allInvocationCopies + extra;
// Finally, get the starting offset. Make sure to count extra copies.
int startCopy = allInvocationCopies * index + min(copiesRequired % invocations, index);
int srcOffset = sourceOffset + startCopy * sourceStride;
int dstOffset = startCopy * targetStride;
// Perform the copies for this region
for (int i = 0; i < copyCount; i++) {
for (int j = 0; j < sourceStride; j++) {
storage_buffers.out_data->data[dstOffset++] = storage_buffers.in_data->data[srcOffset++];
}
for (int j = 0; j < strideRemainder; j++) {
storage_buffers.out_data->data[dstOffset++] = uint8_t(0);
}
}
}

View File

@@ -1,38 +0,0 @@
#include <metal_stdlib>
using namespace metal;
struct VertexOut {
float4 position [[position]];
};
struct ClearColor {
FORMAT4 data;
};
struct ConstantBuffers {
constant ClearColor* clear_color;
};
vertex VertexOut vertexMain(ushort vid [[vertex_id]]) {
int low = vid & 1;
int high = vid >> 1;
VertexOut out;
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;
}
struct FragmentOut {
FORMAT4 color [[color(COLOR_ATTACHMENT_INDEX)]];
};
fragment FragmentOut fragmentMain(VertexOut in [[stage_in]],
constant ConstantBuffers &constant_buffers [[buffer(CONSTANT_BUFFERS_INDEX)]]) {
return {constant_buffers.clear_color->data};
}

View File

@@ -1,66 +0,0 @@
#include <metal_stdlib>
using namespace metal;
struct StrideArguments {
int pixelCount;
int dstStartOffset;
};
struct InData {
uint data[1];
};
struct OutData {
uint data[1];
};
struct ConstantBuffers {
constant StrideArguments* stride_arguments;
};
struct StorageBuffers {
device InData* in_data;
device OutData* out_data;
};
kernel void kernelMain(constant ConstantBuffers &constant_buffers [[buffer(CONSTANT_BUFFERS_INDEX)]],
device StorageBuffers &storage_buffers [[buffer(STORAGE_BUFFERS_INDEX)]],
uint3 thread_position_in_grid [[thread_position_in_grid]],
uint3 threads_per_threadgroup [[threads_per_threadgroup]],
uint3 threadgroups_per_grid [[threadgroups_per_grid]])
{
// Determine what slice of the stride copies this invocation will perform.
int invocations = int(threads_per_threadgroup.x * threadgroups_per_grid.x);
int copiesRequired = constant_buffers.stride_arguments->pixelCount;
// Find the copies that this invocation should perform.
// - Copies that all invocations perform.
int allInvocationCopies = copiesRequired / invocations;
// - Extra remainder copy that this invocation performs.
int index = int(thread_position_in_grid.x);
int extra = (index < (copiesRequired % invocations)) ? 1 : 0;
int copyCount = allInvocationCopies + extra;
// Finally, get the starting offset. Make sure to count extra copies.
int startCopy = allInvocationCopies * index + min(copiesRequired % invocations, index);
int srcOffset = startCopy * 2;
int dstOffset = constant_buffers.stride_arguments->dstStartOffset + startCopy;
// Perform the conversion for this region.
for (int i = 0; i < copyCount; i++)
{
float depth = as_type<float>(storage_buffers.in_data->data[srcOffset++]);
uint stencil = storage_buffers.in_data->data[srcOffset++];
uint rescaledDepth = uint(clamp(depth, 0.0, 1.0) * 16777215.0);
storage_buffers.out_data->data[dstOffset++] = (rescaledDepth << 8) | (stencil & 0xff);
}
}

View File

@@ -1,59 +0,0 @@
#include <metal_stdlib>
using namespace metal;
struct IndexBufferPattern {
int pattern[8];
int primitiveVertices;
int primitiveVerticesOut;
int indexSize;
int indexSizeOut;
int baseIndex;
int indexStride;
int srcOffset;
int totalPrimitives;
};
struct InData {
uint8_t data[1];
};
struct OutData {
uint8_t data[1];
};
struct StorageBuffers {
device InData* in_data;
device OutData* out_data;
constant IndexBufferPattern* index_buffer_pattern;
};
kernel void kernelMain(device StorageBuffers &storage_buffers [[buffer(STORAGE_BUFFERS_INDEX)]],
uint3 thread_position_in_grid [[thread_position_in_grid]])
{
int primitiveIndex = int(thread_position_in_grid.x);
if (primitiveIndex >= storage_buffers.index_buffer_pattern->totalPrimitives)
{
return;
}
int inOffset = primitiveIndex * storage_buffers.index_buffer_pattern->indexStride;
int outOffset = primitiveIndex * storage_buffers.index_buffer_pattern->primitiveVerticesOut;
for (int i = 0; i < storage_buffers.index_buffer_pattern->primitiveVerticesOut; i++)
{
int j;
int io = max(0, inOffset + storage_buffers.index_buffer_pattern->baseIndex + storage_buffers.index_buffer_pattern->pattern[i]) * storage_buffers.index_buffer_pattern->indexSize;
int oo = (outOffset + i) * storage_buffers.index_buffer_pattern->indexSizeOut;
for (j = 0; j < storage_buffers.index_buffer_pattern->indexSize; j++)
{
storage_buffers.out_data->data[oo + j] = storage_buffers.in_data->data[storage_buffers.index_buffer_pattern->srcOffset + io + j];
}
for(; j < storage_buffers.index_buffer_pattern->indexSizeOut; j++)
{
storage_buffers.out_data->data[oo + j] = uint8_t(0);
}
}
}

View File

@@ -1,27 +0,0 @@
#include <metal_stdlib>
using namespace metal;
struct CopyVertexOut {
float4 position [[position]];
float2 uv;
};
struct Textures
{
texture2d<float, access::sample> texture;
sampler sampler;
};
struct FragmentOut {
float depth [[depth(any)]];
};
fragment FragmentOut fragmentMain(CopyVertexOut in [[stage_in]],
constant Textures &textures [[buffer(TEXTURES_INDEX)]]) {
FragmentOut out;
out.depth = textures.texture.sample(textures.sampler, in.uv).r;
return out;
}

View File

@@ -1,29 +0,0 @@
#include <metal_stdlib>
using namespace metal;
struct CopyVertexOut {
float4 position [[position]];
float2 uv;
};
struct Textures
{
texture2d_ms<float, access::read> texture;
};
struct FragmentOut {
float depth [[depth(any)]];
};
fragment FragmentOut fragmentMain(CopyVertexOut in [[stage_in]],
constant Textures &textures [[buffer(TEXTURES_INDEX)]],
uint sample_id [[sample_id]]) {
FragmentOut out;
uint2 tex_size = uint2(textures.texture.get_width(), textures.texture.get_height());
uint2 tex_coord = uint2(in.uv * float2(tex_size));
out.depth = textures.texture.read(tex_coord, sample_id).r;
return out;
}

View File

@@ -1,42 +0,0 @@
#include <metal_stdlib>
using namespace metal;
struct VertexOut {
float4 position [[position]];
};
struct FragmentOut {
float depth [[depth(any)]];
};
struct ClearDepth {
float data;
};
struct ConstantBuffers {
constant ClearDepth* clear_depth;
};
vertex VertexOut vertexMain(ushort vid [[vertex_id]]) {
int low = vid & 1;
int high = vid >> 1;
VertexOut out;
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 FragmentOut fragmentMain(VertexOut in [[stage_in]],
constant ConstantBuffers &constant_buffers [[buffer(CONSTANT_BUFFERS_INDEX)]]) {
FragmentOut out;
out.depth = constant_buffers.clear_depth->data;
return out;
}

View File

@@ -1,27 +0,0 @@
#include <metal_stdlib>
using namespace metal;
struct CopyVertexOut {
float4 position [[position]];
float2 uv;
};
struct Textures
{
texture2d<uint, access::sample> texture;
sampler sampler;
};
struct FragmentOut {
uint stencil [[stencil]];
};
fragment FragmentOut fragmentMain(CopyVertexOut in [[stage_in]],
constant Textures &textures [[buffer(TEXTURES_INDEX)]]) {
FragmentOut out;
out.stencil = textures.texture.sample(textures.sampler, in.uv).r;
return out;
}

View File

@@ -1,29 +0,0 @@
#include <metal_stdlib>
using namespace metal;
struct CopyVertexOut {
float4 position [[position]];
float2 uv;
};
struct Textures
{
texture2d_ms<uint, access::read> texture;
};
struct FragmentOut {
uint stencil [[stencil]];
};
fragment FragmentOut fragmentMain(CopyVertexOut in [[stage_in]],
constant Textures &textures [[buffer(TEXTURES_INDEX)]],
uint sample_id [[sample_id]]) {
FragmentOut out;
uint2 tex_size = uint2(textures.texture.get_width(), textures.texture.get_height());
uint2 tex_coord = uint2(in.uv * float2(tex_size));
out.stencil = textures.texture.read(tex_coord, sample_id).r;
return out;
}