implement compressed/uncompressed copy, fix other copies, fix int/uint output shaders (#33)

This commit is contained in:
riperiperi 2024-07-04 10:19:40 +01:00 committed by Isaac Marovitz
parent 9d866ff282
commit d22feff1d2
3 changed files with 81 additions and 26 deletions

View file

@ -189,10 +189,6 @@ namespace Ryujinx.Graphics.Metal
dstImage, dstImage,
src.Info, src.Info,
dst.Info, dst.Info,
0,//src.FirstLayer,
0,//dst.FirstLayer,
0,//src.FirstLevel,
0,//dst.FirstLevel,
0, 0,
firstLayer, firstLayer,
0, 0,
@ -234,10 +230,6 @@ namespace Ryujinx.Graphics.Metal
dstImage, dstImage,
src.Info, src.Info,
dst.Info, dst.Info,
0, //src.FirstLayer,
0, //dst.FirstLayer,
0, //src.FirstLevel,
0, //dst.FirstLevel,
srcLayer, srcLayer,
dstLayer, dstLayer,
srcLevel, srcLevel,

View file

@ -10,16 +10,61 @@ namespace Ryujinx.Graphics.Metal
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
static class TextureCopy static class TextureCopy
{ {
public static ulong CopyFromOrToBuffer(
CommandBufferScoped cbs,
MTLBuffer buffer,
MTLTexture image,
TextureCreateInfo info,
bool to,
int dstLayer,
int dstLevel,
int x,
int y,
int width,
int height,
ulong offset = 0)
{
MTLBlitCommandEncoder blitCommandEncoder = cbs.Encoders.EnsureBlitEncoder();
bool is3D = info.Target == Target.Texture3D;
int blockWidth = BitUtils.DivRoundUp(width, info.BlockWidth);
int blockHeight = BitUtils.DivRoundUp(height, info.BlockHeight);
ulong bytesPerRow = (ulong)BitUtils.AlignUp(blockWidth * info.BytesPerPixel, 4);
ulong bytesPerImage = bytesPerRow * (ulong)blockHeight;
MTLOrigin origin = new MTLOrigin { x = (ulong)x, y = (ulong)y, z = is3D ? (ulong)dstLayer : 0 };
MTLSize region = new MTLSize { width = (ulong)width, height = (ulong)height, depth = 1 };
uint layer = is3D ? 0 : (uint)dstLayer;
if (to)
{
blitCommandEncoder.CopyFromTexture(
image,
layer,
(ulong)dstLevel,
origin,
region,
buffer,
offset,
bytesPerRow,
bytesPerImage);
}
else
{
blitCommandEncoder.CopyFromBuffer(buffer, offset, bytesPerRow, bytesPerImage, region, image, layer, (ulong)dstLevel, origin);
}
return offset + bytesPerImage;
}
public static void Copy( public static void Copy(
CommandBufferScoped cbs, CommandBufferScoped cbs,
MTLTexture srcImage, MTLTexture srcImage,
MTLTexture dstImage, MTLTexture dstImage,
TextureCreateInfo srcInfo, TextureCreateInfo srcInfo,
TextureCreateInfo dstInfo, TextureCreateInfo dstInfo,
int srcViewLayer,
int dstViewLayer,
int srcViewLevel,
int dstViewLevel,
int srcLayer, int srcLayer,
int dstLayer, int dstLayer,
int srcLevel, int srcLevel,
@ -45,10 +90,6 @@ namespace Ryujinx.Graphics.Metal
dstImage, dstImage,
srcInfo, srcInfo,
dstInfo, dstInfo,
srcViewLayer,
dstViewLayer,
srcViewLevel,
dstViewLevel,
srcLayer, srcLayer,
dstLayer, dstLayer,
srcLevel, srcLevel,
@ -63,10 +104,6 @@ namespace Ryujinx.Graphics.Metal
MTLTexture dstImage, MTLTexture dstImage,
TextureCreateInfo srcInfo, TextureCreateInfo srcInfo,
TextureCreateInfo dstInfo, TextureCreateInfo dstInfo,
int srcViewLayer,
int dstViewLayer,
int srcViewLevel,
int dstViewLevel,
int srcDepthOrLayer, int srcDepthOrLayer,
int dstDepthOrLayer, int dstDepthOrLayer,
int srcLevel, int srcLevel,
@ -129,6 +166,17 @@ namespace Ryujinx.Graphics.Metal
int blockHeight = 1; int blockHeight = 1;
bool sizeInBlocks = false; bool sizeInBlocks = false;
MTLBuffer tempBuffer = default;
if (srcInfo.Format != dstInfo.Format && (srcInfo.IsCompressed || dstInfo.IsCompressed))
{
// Compressed alias copies need to happen through a temporary buffer.
// The data is copied from the source to the buffer, then the buffer to the destination.
// The length of the buffer should be the maximum slice size for the destination.
tempBuffer = blitCommandEncoder.Device.NewBuffer((ulong)dstInfo.GetMipSize2D(0), MTLResourceOptions.ResourceStorageModePrivate);
}
// When copying from a compressed to a non-compressed format, // When copying from a compressed to a non-compressed format,
// the non-compressed texture will have the size of the texture // the non-compressed texture will have the size of the texture
// in blocks (not in texels), so we must adjust that size to // in blocks (not in texels), so we must adjust that size to
@ -168,7 +216,17 @@ namespace Ryujinx.Graphics.Metal
for (int layer = 0; layer < layers; layer++) for (int layer = 0; layer < layers; layer++)
{ {
if (srcInfo.Samples > 1 && srcInfo.Samples != dstInfo.Samples) if (tempBuffer.NativePtr != 0)
{
// Copy through the temp buffer
CopyFromOrToBuffer(cbs, tempBuffer, srcImage, srcInfo, true, srcLayer + layer, srcLevel + level, 0, 0, copyWidth, copyHeight);
int dstBufferWidth = sizeInBlocks ? copyWidth * blockWidth : BitUtils.DivRoundUp(copyWidth, blockWidth);
int dstBufferHeight = sizeInBlocks ? copyHeight * blockHeight : BitUtils.DivRoundUp(copyHeight, blockHeight);
CopyFromOrToBuffer(cbs, tempBuffer, dstImage, dstInfo, false, dstLayer + layer, dstLevel + level, 0, 0, dstBufferWidth, dstBufferHeight);
}
else if (srcInfo.Samples > 1 && srcInfo.Samples != dstInfo.Samples)
{ {
// TODO // TODO
@ -178,13 +236,13 @@ namespace Ryujinx.Graphics.Metal
{ {
blitCommandEncoder.CopyFromTexture( blitCommandEncoder.CopyFromTexture(
srcImage, srcImage,
(ulong)(srcViewLevel + srcLevel + level), (ulong)(srcLayer + layer),
(ulong)(srcViewLayer + srcLayer + layer), (ulong)(srcLevel + level),
new MTLOrigin { z = (ulong)srcZ }, new MTLOrigin { z = (ulong)srcZ },
new MTLSize { width = (ulong)copyWidth, height = (ulong)copyHeight, depth = (ulong)srcDepth }, new MTLSize { width = (ulong)copyWidth, height = (ulong)copyHeight, depth = (ulong)srcDepth },
dstImage, dstImage,
(ulong)(dstViewLevel + dstLevel + level), (ulong)(dstLayer + layer),
(ulong)(dstViewLayer + dstLayer + layer), (ulong)(dstLevel + level),
new MTLOrigin { z = (ulong)dstZ }); new MTLOrigin { z = (ulong)dstZ });
} }
} }
@ -197,6 +255,11 @@ namespace Ryujinx.Graphics.Metal
srcDepth = Math.Max(1, srcDepth >> 1); srcDepth = Math.Max(1, srcDepth >> 1);
} }
} }
if (tempBuffer.NativePtr != 0)
{
tempBuffer.Dispose();
}
} }
} }
} }

View file

@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
IoVariable.BaseVertex => ("base_vertex", AggregateType.U32), IoVariable.BaseVertex => ("base_vertex", AggregateType.U32),
IoVariable.CtaId => ("threadgroup_position_in_grid", AggregateType.Vector3 | AggregateType.U32), IoVariable.CtaId => ("threadgroup_position_in_grid", AggregateType.Vector3 | AggregateType.U32),
IoVariable.ClipDistance => ("clip_distance", AggregateType.Array | AggregateType.FP32), IoVariable.ClipDistance => ("clip_distance", AggregateType.Array | AggregateType.FP32),
IoVariable.FragmentOutputColor => ($"out.color{location}", AggregateType.Vector4 | AggregateType.FP32), IoVariable.FragmentOutputColor => ($"out.color{location}", definitions.GetFragmentOutputColorType(location)),
IoVariable.FragmentOutputDepth => ("out.depth", AggregateType.FP32), IoVariable.FragmentOutputDepth => ("out.depth", AggregateType.FP32),
IoVariable.FrontFacing => ("in.front_facing", AggregateType.Bool), IoVariable.FrontFacing => ("in.front_facing", AggregateType.Bool),
IoVariable.GlobalId => ("thread_position_in_grid", AggregateType.Vector3 | AggregateType.U32), IoVariable.GlobalId => ("thread_position_in_grid", AggregateType.Vector3 | AggregateType.U32),