Maintain identity swizzle view of textures for rendering

This commit is contained in:
riperiperi 2024-07-03 13:43:45 +01:00 committed by Isaac Marovitz
parent 7b9b23e500
commit 468ab8242f
2 changed files with 64 additions and 6 deletions

View file

@ -101,10 +101,10 @@ namespace Ryujinx.Graphics.Metal
for (int i = 0; i < Constants.MaxColorAttachments; i++)
{
if (_currentState.RenderTargets[i] != null)
if (_currentState.RenderTargets[i] is Texture tex)
{
var passAttachment = renderPassDescriptor.ColorAttachments.Object((ulong)i);
passAttachment.Texture = _currentState.RenderTargets[i].GetHandle();
tex.PopulateRenderPassAttachment(passAttachment);
passAttachment.LoadAction = _currentState.ClearLoadAction ? MTLLoadAction.Clear : MTLLoadAction.Load;
passAttachment.StoreAction = MTLStoreAction.Store;
}

View file

@ -11,6 +11,9 @@ namespace Ryujinx.Graphics.Metal
[SupportedOSPlatform("macos")]
class Texture : TextureBase, ITexture
{
private MTLTexture _identitySwizzleHandle;
private bool _identityIsDifferent;
public Texture(MTLDevice device, MetalRenderer renderer, Pipeline pipeline, TextureCreateInfo info) : base(device, renderer, pipeline, info)
{
MTLPixelFormat pixelFormat = FormatTable.GetFormat(Info.Format);
@ -35,9 +38,19 @@ namespace Ryujinx.Graphics.Metal
descriptor.ArrayLength = (ulong)Info.Depth;
}
descriptor.Swizzle = GetSwizzle(info, descriptor.PixelFormat);
MTLTextureSwizzleChannels swizzle = GetSwizzle(info, descriptor.PixelFormat);
_mtlTexture = _device.NewTexture(descriptor);
_identitySwizzleHandle = _device.NewTexture(descriptor);
if (SwizzleIsIdentity(swizzle))
{
_mtlTexture = _identitySwizzleHandle;
}
else
{
_mtlTexture = CreateDefaultView(_identitySwizzleHandle, swizzle, descriptor);
_identityIsDifferent = true;
}
MtlFormat = pixelFormat;
descriptor.Dispose();
@ -56,13 +69,48 @@ namespace Ryujinx.Graphics.Metal
var swizzle = GetSwizzle(info, pixelFormat);
_identitySwizzleHandle = sourceTexture.NewTextureView(pixelFormat, textureType, levels, slices);
if (SwizzleIsIdentity(swizzle))
{
_mtlTexture = _identitySwizzleHandle;
}
else
{
_mtlTexture = sourceTexture.NewTextureView(pixelFormat, textureType, levels, slices, swizzle);
_identityIsDifferent = true;
}
MtlFormat = pixelFormat;
FirstLayer = firstLayer;
FirstLevel = firstLevel;
}
public void PopulateRenderPassAttachment(MTLRenderPassColorAttachmentDescriptor descriptor)
{
descriptor.Texture = _identitySwizzleHandle;
}
private MTLTexture CreateDefaultView(MTLTexture texture, MTLTextureSwizzleChannels swizzle, MTLTextureDescriptor descriptor)
{
NSRange levels;
levels.location = 0;
levels.length = (ulong)Info.Levels;
NSRange slices;
slices.location = 0;
slices.length = Info.Target == Target.Texture3D ? 1 : (ulong)Info.GetDepthOrLayers();
return texture.NewTextureView(descriptor.PixelFormat, descriptor.TextureType, levels, slices, swizzle);
}
private bool SwizzleIsIdentity(MTLTextureSwizzleChannels swizzle)
{
return swizzle.red == MTLTextureSwizzle.Red &&
swizzle.green == MTLTextureSwizzle.Green &&
swizzle.blue == MTLTextureSwizzle.Blue &&
swizzle.alpha == MTLTextureSwizzle.Alpha;
}
private MTLTextureSwizzleChannels GetSwizzle(TextureCreateInfo info, MTLPixelFormat pixelFormat)
{
var swizzleR = Info.SwizzleR.Convert();
@ -237,7 +285,7 @@ namespace Ryujinx.Graphics.Metal
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel)
{
return new Texture(_device, _renderer, _pipeline, info, _mtlTexture, firstLayer, firstLevel);
return new Texture(_device, _renderer, _pipeline, info, _identitySwizzleHandle, firstLayer, firstLevel);
}
private int GetBufferDataLength(int size)
@ -521,5 +569,15 @@ namespace Ryujinx.Graphics.Metal
{
throw new NotImplementedException();
}
public override void Release()
{
if (_identityIsDifferent)
{
_identitySwizzleHandle.Dispose();
}
base.Release();
}
}
}