Refactor binding logic + Bind image arrays

This commit is contained in:
Isaac Marovitz 2024-09-06 23:42:59 +02:00 committed by Isaac Marovitz
parent 04c0090653
commit 2f0235fc37
2 changed files with 212 additions and 214 deletions

View file

@ -1111,6 +1111,95 @@ namespace Ryujinx.Graphics.Metal
resources.VertexBuffers.Add(new BufferResource(zeroMtlBuffer, 0, Constants.ZeroBufferIndex)); resources.VertexBuffers.Add(new BufferResource(zeroMtlBuffer, 0, Constants.ZeroBufferIndex));
} }
private readonly (ulong gpuAddress, IntPtr nativePtr) AddressForBuffer(ref BufferRef buffer)
{
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
var range = buffer.Range;
var autoBuffer = buffer.Buffer;
if (autoBuffer != null)
{
var offset = 0;
MTLBuffer mtlBuffer;
if (range.HasValue)
{
offset = range.Value.Offset;
mtlBuffer = autoBuffer.Get(_pipeline.Cbs, offset, range.Value.Size, range.Value.Write).Value;
}
else
{
mtlBuffer = autoBuffer.Get(_pipeline.Cbs).Value;
}
gpuAddress = mtlBuffer.GpuAddress + (ulong)offset;
nativePtr = mtlBuffer.NativePtr;
}
return (gpuAddress, nativePtr);
}
private readonly (ulong gpuAddress, IntPtr nativePtr) AddressForTexture(ref TextureRef texture)
{
var storage = texture.Storage;
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (storage != null)
{
if (storage is TextureBuffer textureBuffer)
{
textureBuffer.RebuildStorage(false);
}
var mtlTexture = storage.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
return (gpuAddress, nativePtr);
}
private readonly (ulong gpuAddress, IntPtr nativePtr) AddressForImage(ref ImageRef image)
{
var storage = image.Storage;
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (storage != null)
{
var mtlTexture = storage.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
return (gpuAddress, nativePtr);
}
private readonly (ulong gpuAddress, IntPtr nativePtr) AddressForTextureBuffer(ref TextureBuffer bufferTexture)
{
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (bufferTexture != null)
{
bufferTexture.RebuildStorage(false);
var mtlTexture = bufferTexture.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
return (gpuAddress, nativePtr);
}
private readonly void UpdateAndBind(Program program, uint setIndex, ref readonly RenderEncoderResources resources) private readonly void UpdateAndBind(Program program, uint setIndex, ref readonly RenderEncoderResources resources)
{ {
var bindingSegments = program.BindingSegments[setIndex]; var bindingSegments = program.BindingSegments[setIndex];
@ -1152,32 +1241,7 @@ namespace Ryujinx.Graphics.Metal
int index = binding + i; int index = binding + i;
ref BufferRef buffer = ref _currentState.UniformBufferRefs[index]; ref BufferRef buffer = ref _currentState.UniformBufferRefs[index];
var (gpuAddress, nativePtr) = AddressForBuffer(ref buffer);
var range = buffer.Range;
var autoBuffer = buffer.Buffer;
var offset = 0;
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (autoBuffer != null)
{
MTLBuffer mtlBuffer;
if (range.HasValue)
{
offset = range.Value.Offset;
mtlBuffer = autoBuffer.Get(_pipeline.Cbs, offset, range.Value.Size, range.Value.Write).Value;
}
else
{
mtlBuffer = autoBuffer.Get(_pipeline.Cbs).Value;
}
gpuAddress = mtlBuffer.GpuAddress + (ulong)offset;
nativePtr = mtlBuffer.NativePtr;
}
MTLRenderStages renderStages = 0; MTLRenderStages renderStages = 0;
@ -1206,32 +1270,7 @@ namespace Ryujinx.Graphics.Metal
int index = binding + i; int index = binding + i;
ref BufferRef buffer = ref _currentState.StorageBufferRefs[index]; ref BufferRef buffer = ref _currentState.StorageBufferRefs[index];
var (gpuAddress, nativePtr) = AddressForBuffer(ref buffer);
var range = buffer.Range;
var autoBuffer = buffer.Buffer;
var offset = 0;
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (autoBuffer != null)
{
MTLBuffer mtlBuffer;
if (range.HasValue)
{
offset = range.Value.Offset;
mtlBuffer = autoBuffer.Get(_pipeline.Cbs, offset, range.Value.Size, range.Value.Write).Value;
}
else
{
mtlBuffer = autoBuffer.Get(_pipeline.Cbs).Value;
}
gpuAddress = mtlBuffer.GpuAddress + (ulong)offset;
nativePtr = mtlBuffer.NativePtr;
}
MTLRenderStages renderStages = 0; MTLRenderStages renderStages = 0;
@ -1262,24 +1301,7 @@ namespace Ryujinx.Graphics.Metal
int index = binding + i; int index = binding + i;
ref var texture = ref _currentState.TextureRefs[index]; ref var texture = ref _currentState.TextureRefs[index];
var (gpuAddress, nativePtr) = AddressForTexture(ref texture);
var storage = texture.Storage;
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (storage != null)
{
if (storage is TextureBuffer textureBuffer)
{
textureBuffer.RebuildStorage(false);
}
var mtlTexture = storage.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
MTLRenderStages renderStages = 0; MTLRenderStages renderStages = 0;
@ -1326,17 +1348,7 @@ namespace Ryujinx.Graphics.Metal
for (int i = 0; i < textures.Length; i++) for (int i = 0; i < textures.Length; i++)
{ {
TextureRef texture = textures[i]; TextureRef texture = textures[i];
var (gpuAddress, nativePtr) = AddressForTexture(ref texture);
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (texture.Storage != null)
{
var mtlTexture = texture.Storage.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
samplers[i] = texture.Sampler; samplers[i] = texture.Sampler;
@ -1387,20 +1399,10 @@ namespace Ryujinx.Graphics.Metal
{ {
var bufferTextures = textureArray.GetBufferTextureRefs(); var bufferTextures = textureArray.GetBufferTextureRefs();
foreach (TextureBuffer bufferTexture in bufferTextures) for (int i = 0; i < bufferTextures.Length; i++)
{ {
ulong gpuAddress = 0; TextureBuffer bufferTexture = bufferTextures[i];
IntPtr nativePtr = IntPtr.Zero; var (gpuAddress, nativePtr) = AddressForTextureBuffer(ref bufferTexture);
if (bufferTexture != null)
{
bufferTexture.RebuildStorage(false);
var mtlTexture = bufferTexture.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
MTLRenderStages renderStages = 0; MTLRenderStages renderStages = 0;
@ -1433,19 +1435,7 @@ namespace Ryujinx.Graphics.Metal
int index = binding + i; int index = binding + i;
ref var image = ref _currentState.ImageRefs[index]; ref var image = ref _currentState.ImageRefs[index];
var (gpuAddress, nativePtr) = AddressForImage(ref image);
var storage = image.Storage;
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (storage != null)
{
var mtlTexture = storage.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
MTLRenderStages renderStages = 0; MTLRenderStages renderStages = 0;
@ -1466,6 +1456,67 @@ namespace Ryujinx.Graphics.Metal
resources.Resources.Add(new Resource(new MTLResource(nativePtr), MTLResourceUsage.Read | MTLResourceUsage.Write, renderStages)); resources.Resources.Add(new Resource(new MTLResource(nativePtr), MTLResourceUsage.Read | MTLResourceUsage.Write, renderStages));
} }
} }
else
{
var imageArray = _currentState.ImageArrayRefs[binding].Array;
if (segment.Type != ResourceType.BufferImage)
{
var images = imageArray.GetTextureRefs();
for (int i = 0; i < images.Length; i++)
{
TextureRef image = images[i];
var (gpuAddress, nativePtr) = AddressForTexture(ref image);
MTLRenderStages renderStages = 0;
if ((segment.Stages & ResourceStages.Vertex) != 0)
{
vertResourceIds[vertResourceIdIndex] = gpuAddress;
vertResourceIdIndex++;
renderStages |= MTLRenderStages.RenderStageVertex;
}
if ((segment.Stages & ResourceStages.Fragment) != 0)
{
fragResourceIds[fragResourceIdIndex] = gpuAddress;
fragResourceIdIndex++;
renderStages |= MTLRenderStages.RenderStageFragment;
}
resources.Resources.Add(new Resource(new MTLResource(nativePtr), MTLResourceUsage.Read | MTLResourceUsage.Write, renderStages));
}
}
else
{
var bufferImages = imageArray.GetBufferTextureRefs();
for (int i = 0; i < bufferImages.Length; i++)
{
TextureBuffer image = bufferImages[i];
var (gpuAddress, nativePtr) = AddressForTextureBuffer(ref image);
MTLRenderStages renderStages = 0;
if ((segment.Stages & ResourceStages.Vertex) != 0)
{
vertResourceIds[vertResourceIdIndex] = gpuAddress;
vertResourceIdIndex++;
renderStages |= MTLRenderStages.RenderStageVertex;
}
if ((segment.Stages & ResourceStages.Fragment) != 0)
{
fragResourceIds[fragResourceIdIndex] = gpuAddress;
fragResourceIdIndex++;
renderStages |= MTLRenderStages.RenderStageFragment;
}
resources.Resources.Add(new Resource(new MTLResource(nativePtr), MTLResourceUsage.Read | MTLResourceUsage.Write, renderStages));
}
}
}
break; break;
} }
} }
@ -1517,32 +1568,7 @@ namespace Ryujinx.Graphics.Metal
int index = binding + i; int index = binding + i;
ref BufferRef buffer = ref _currentState.UniformBufferRefs[index]; ref BufferRef buffer = ref _currentState.UniformBufferRefs[index];
var (gpuAddress, nativePtr) = AddressForBuffer(ref buffer);
var range = buffer.Range;
var autoBuffer = buffer.Buffer;
var offset = 0;
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (autoBuffer != null)
{
MTLBuffer mtlBuffer;
if (range.HasValue)
{
offset = range.Value.Offset;
mtlBuffer = autoBuffer.Get(_pipeline.Cbs, offset, range.Value.Size, range.Value.Write).Value;
}
else
{
mtlBuffer = autoBuffer.Get(_pipeline.Cbs).Value;
}
gpuAddress = mtlBuffer.GpuAddress + (ulong)offset;
nativePtr = mtlBuffer.NativePtr;
}
if ((segment.Stages & ResourceStages.Compute) != 0) if ((segment.Stages & ResourceStages.Compute) != 0)
{ {
@ -1558,32 +1584,7 @@ namespace Ryujinx.Graphics.Metal
int index = binding + i; int index = binding + i;
ref BufferRef buffer = ref _currentState.StorageBufferRefs[index]; ref BufferRef buffer = ref _currentState.StorageBufferRefs[index];
var (gpuAddress, nativePtr) = AddressForBuffer(ref buffer);
var range = buffer.Range;
var autoBuffer = buffer.Buffer;
var offset = 0;
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (autoBuffer != null)
{
MTLBuffer mtlBuffer;
if (range.HasValue)
{
offset = range.Value.Offset;
mtlBuffer = autoBuffer.Get(_pipeline.Cbs, offset, range.Value.Size, range.Value.Write).Value;
}
else
{
mtlBuffer = autoBuffer.Get(_pipeline.Cbs).Value;
}
gpuAddress = mtlBuffer.GpuAddress + (ulong)offset;
nativePtr = mtlBuffer.NativePtr;
}
if ((segment.Stages & ResourceStages.Compute) != 0) if ((segment.Stages & ResourceStages.Compute) != 0)
{ {
@ -1601,24 +1602,7 @@ namespace Ryujinx.Graphics.Metal
int index = binding + i; int index = binding + i;
ref var texture = ref _currentState.TextureRefs[index]; ref var texture = ref _currentState.TextureRefs[index];
var (gpuAddress, nativePtr) = AddressForTexture(ref texture);
var storage = texture.Storage;
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (storage != null)
{
if (storage is TextureBuffer textureBuffer)
{
textureBuffer.RebuildStorage(false);
}
var mtlTexture = storage.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
if ((segment.Stages & ResourceStages.Compute) != 0) if ((segment.Stages & ResourceStages.Compute) != 0)
{ {
@ -1646,17 +1630,7 @@ namespace Ryujinx.Graphics.Metal
for (int i = 0; i < textures.Length; i++) for (int i = 0; i < textures.Length; i++)
{ {
TextureRef texture = textures[i]; TextureRef texture = textures[i];
var (gpuAddress, nativePtr) = AddressForTexture(ref texture);
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (texture.Storage != null)
{
var mtlTexture = texture.Storage.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
if ((segment.Stages & ResourceStages.Compute) != 0) if ((segment.Stages & ResourceStages.Compute) != 0)
{ {
@ -1681,20 +1655,10 @@ namespace Ryujinx.Graphics.Metal
{ {
var bufferTextures = textureArray.GetBufferTextureRefs(); var bufferTextures = textureArray.GetBufferTextureRefs();
foreach (TextureBuffer bufferTexture in bufferTextures) for (int i = 0; i < bufferTextures.Length; i++)
{ {
ulong gpuAddress = 0; TextureBuffer bufferTexture = bufferTextures[i];
IntPtr nativePtr = IntPtr.Zero; var (gpuAddress, nativePtr) = AddressForTextureBuffer(ref bufferTexture);
if (bufferTexture != null)
{
bufferTexture.RebuildStorage(false);
var mtlTexture = bufferTexture.GetHandle();
gpuAddress = mtlTexture.GpuResourceID._impl;
nativePtr = mtlTexture.NativePtr;
}
if ((segment.Stages & ResourceStages.Compute) != 0) if ((segment.Stages & ResourceStages.Compute) != 0)
{ {
@ -1708,27 +1672,51 @@ namespace Ryujinx.Graphics.Metal
break; break;
case Constants.ImagesSetIndex: case Constants.ImagesSetIndex:
if (!segment.IsArray) if (!segment.IsArray)
{
if (segment.Type != ResourceType.BufferTexture)
{ {
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
int index = binding + i; int index = binding + i;
ref var image = ref _currentState.ImageRefs[index]; ref var image = ref _currentState.ImageRefs[index];
var (gpuAddress, nativePtr) = AddressForImage(ref image);
var storage = image.Storage; if ((segment.Stages & ResourceStages.Compute) != 0)
ulong gpuAddress = 0;
IntPtr nativePtr = IntPtr.Zero;
if (storage != null)
{ {
var mtlTexture = storage.GetHandle(); resources.Resources.Add(new Resource(new MTLResource(nativePtr), MTLResourceUsage.Read | MTLResourceUsage.Write, 0));
resourceIds[resourceIdIndex] = gpuAddress;
gpuAddress = mtlTexture.GpuResourceID._impl; resourceIdIndex++;
nativePtr = mtlTexture.NativePtr;
} }
}
}
else
{
var imageArray = _currentState.ImageArrayRefs[binding].Array;
if (segment.Type != ResourceType.BufferImage)
{
var images = imageArray.GetTextureRefs();
for (int i = 0; i < images.Length; i++)
{
TextureRef image = images[i];
var (gpuAddress, nativePtr) = AddressForTexture(ref image);
if ((segment.Stages & ResourceStages.Compute) != 0)
{
resources.Resources.Add(new Resource(new MTLResource(nativePtr), MTLResourceUsage.Read | MTLResourceUsage.Write, 0));
resourceIds[resourceIdIndex] = gpuAddress;
resourceIdIndex++;
}
}
}
else
{
var bufferImages = imageArray.GetBufferTextureRefs();
for (int i = 0; i < bufferImages.Length; i++)
{
TextureBuffer image = bufferImages[i];
var (gpuAddress, nativePtr) = AddressForTextureBuffer(ref image);
if ((segment.Stages & ResourceStages.Compute) != 0) if ((segment.Stages & ResourceStages.Compute) != 0)
{ {

View file

@ -64,6 +64,16 @@ namespace Ryujinx.Graphics.Metal
SetDirty(); SetDirty();
} }
public TextureRef[] GetTextureRefs()
{
return _textureRefs;
}
public TextureBuffer[] GetBufferTextureRefs()
{
return _bufferTextureRefs;
}
private void SetDirty() private void SetDirty()
{ {
_pipeline.DirtyImages(); _pipeline.DirtyImages();