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++) 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); 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.LoadAction = _currentState.ClearLoadAction ? MTLLoadAction.Clear : MTLLoadAction.Load;
passAttachment.StoreAction = MTLStoreAction.Store; passAttachment.StoreAction = MTLStoreAction.Store;
} }

View file

@ -11,6 +11,9 @@ namespace Ryujinx.Graphics.Metal
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
class Texture : TextureBase, ITexture 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) public Texture(MTLDevice device, MetalRenderer renderer, Pipeline pipeline, TextureCreateInfo info) : base(device, renderer, pipeline, info)
{ {
MTLPixelFormat pixelFormat = FormatTable.GetFormat(Info.Format); MTLPixelFormat pixelFormat = FormatTable.GetFormat(Info.Format);
@ -35,9 +38,19 @@ namespace Ryujinx.Graphics.Metal
descriptor.ArrayLength = (ulong)Info.Depth; 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; MtlFormat = pixelFormat;
descriptor.Dispose(); descriptor.Dispose();
@ -56,13 +69,48 @@ namespace Ryujinx.Graphics.Metal
var swizzle = GetSwizzle(info, pixelFormat); 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); _mtlTexture = sourceTexture.NewTextureView(pixelFormat, textureType, levels, slices, swizzle);
_identityIsDifferent = true;
}
MtlFormat = pixelFormat; MtlFormat = pixelFormat;
FirstLayer = firstLayer; FirstLayer = firstLayer;
FirstLevel = firstLevel; 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) private MTLTextureSwizzleChannels GetSwizzle(TextureCreateInfo info, MTLPixelFormat pixelFormat)
{ {
var swizzleR = Info.SwizzleR.Convert(); var swizzleR = Info.SwizzleR.Convert();
@ -237,7 +285,7 @@ namespace Ryujinx.Graphics.Metal
public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel) 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) private int GetBufferDataLength(int size)
@ -521,5 +569,15 @@ namespace Ryujinx.Graphics.Metal
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override void Release()
{
if (_identityIsDifferent)
{
_identitySwizzleHandle.Dispose();
}
base.Release();
}
} }
} }