Image binding support

Kirby still has a problem with NaN 3D Texture
This commit is contained in:
Isaac Marovitz 2024-07-24 14:58:56 +01:00 committed by Isaac Marovitz
parent 4e5cf38009
commit 650f309b58
4 changed files with 99 additions and 5 deletions

View file

@ -26,6 +26,6 @@ namespace Ryujinx.Graphics.Metal
public const uint ConstantBuffersIndex = 20;
public const uint StorageBuffersIndex = 21;
public const uint TexturesIndex = 22;
public const uint ImagessIndex = 23;
public const uint ImagesIndex = 23;
}
}

View file

@ -65,6 +65,18 @@ namespace Ryujinx.Graphics.Metal
}
}
record struct ImageRef
{
public ShaderStage Stage;
public Texture Storage;
public ImageRef(ShaderStage stage, Texture storage)
{
Stage = stage;
Storage = storage;
}
}
struct PredrawState
{
public MTLCullMode CullMode;
@ -92,6 +104,7 @@ namespace Ryujinx.Graphics.Metal
public readonly BufferRef[] UniformBufferRefs = new BufferRef[Constants.MaxUniformBufferBindings];
public readonly BufferRef[] StorageBufferRefs = new BufferRef[Constants.MaxStorageBufferBindings];
public readonly TextureRef[] TextureRefs = new TextureRef[Constants.MaxTextureBindings];
public readonly ImageRef[] ImageRefs = new ImageRef[Constants.MaxTextureBindings];
public IndexBufferState IndexBuffer = default;

View file

@ -821,6 +821,20 @@ namespace Ryujinx.Graphics.Metal
_currentState.Dirty |= DirtyFlags.Textures;
}
public readonly void UpdateImage(ShaderStage stage, ulong binding, TextureBase texture)
{
if (texture is Texture view)
{
_currentState.ImageRefs[binding] = new(stage, view);
}
else
{
_currentState.ImageRefs[binding] = default;
}
_currentState.Dirty |= DirtyFlags.Images;
}
private readonly void SetDepthStencilState(MTLRenderCommandEncoder renderCommandEncoder)
{
MTLDepthStencilState state = _depthStencilCache.GetOrCreate(_currentState.DepthStencilUid);
@ -1171,7 +1185,42 @@ namespace Ryujinx.Graphics.Metal
}
break;
case MetalRenderer.ImageSetIndex:
// TODO: Images
if (!segment.IsArray)
{
for (int i = 0; i < count; i++)
{
int index = binding + i;
ref var image = ref _currentState.ImageRefs[index];
var storage = image.Storage;
if (storage == null)
{
continue;
}
var mtlTexture = storage.GetHandle();
MTLRenderStages renderStages = 0;
if ((segment.Stages & ResourceStages.Vertex) != 0)
{
vertResourceIds[vertResourceIdIndex] = mtlTexture.GpuResourceID._impl;
vertResourceIdIndex++;
renderStages |= MTLRenderStages.RenderStageVertex;
}
if ((segment.Stages & ResourceStages.Fragment) != 0)
{
fragResourceIds[fragResourceIdIndex] = mtlTexture.GpuResourceID._impl;
fragResourceIdIndex++;
renderStages |= MTLRenderStages.RenderStageFragment;
}
renderCommandEncoder.UseResource(new MTLResource(mtlTexture.NativePtr), MTLResourceUsage.Read | MTLResourceUsage.Write, renderStages);
}
}
break;
}
}
@ -1336,7 +1385,34 @@ namespace Ryujinx.Graphics.Metal
}
break;
case MetalRenderer.ImageSetIndex:
// TODO: Images
if (!segment.IsArray)
{
if (segment.Type != ResourceType.BufferTexture)
{
for (int i = 0; i < count; i++)
{
int index = binding + i;
ref var image = ref _currentState.ImageRefs[index];
var storage = image.Storage;
if (storage == null)
{
continue;
}
var mtlTexture = storage.GetHandle();
if (segment.Stages.HasFlag(ResourceStages.Compute))
{
computeCommandEncoder.UseResource(new MTLResource(mtlTexture.NativePtr), MTLResourceUsage.Read | MTLResourceUsage.Write);
resourceIds[resourceIdIndex] = mtlTexture.GpuResourceID._impl;
resourceIdIndex++;
}
}
}
}
break;
}
}
@ -1356,7 +1432,7 @@ namespace Ryujinx.Graphics.Metal
MetalRenderer.UniformSetIndex => Constants.ConstantBuffersIndex,
MetalRenderer.StorageSetIndex => Constants.StorageBuffersIndex,
MetalRenderer.TextureSetIndex => Constants.TexturesIndex,
MetalRenderer.ImageSetIndex => Constants.ImagessIndex,
MetalRenderer.ImageSetIndex => Constants.ImagesIndex,
};
}

View file

@ -497,7 +497,12 @@ namespace Ryujinx.Graphics.Metal
public void SetImage(ShaderStage stage, int binding, ITexture texture, Format imageFormat)
{
Logger.Warning?.Print(LogClass.Gpu, "Not Implemented!");
if (texture is TextureBase tex)
{
var index = (ulong)binding;
_encoderStateManager.UpdateImage(stage, index, tex);
}
}
public void SetImageArray(ShaderStage stage, int binding, IImageArray array)