Compare commits

..

No commits in common. "e194f9124558563bbaab35f95c0f7f862307495c" and "66d4257740b719168068cb4209d45fba3f9bc28e" have entirely different histories.

3 changed files with 130 additions and 54 deletions

View file

@ -54,10 +54,10 @@ namespace Ryujinx.Graphics.Metal
record struct TextureRef record struct TextureRef
{ {
public ShaderStage Stage; public ShaderStage Stage;
public TextureBase Storage; public Texture Storage;
public Sampler Sampler; public Sampler Sampler;
public TextureRef(ShaderStage stage, TextureBase storage, Sampler sampler) public TextureRef(ShaderStage stage, Texture storage, Sampler sampler)
{ {
Stage = stage; Stage = stage;
Storage = storage; Storage = storage;

View file

@ -805,9 +805,13 @@ namespace Ryujinx.Graphics.Metal
public readonly void UpdateTextureAndSampler(ShaderStage stage, ulong binding, TextureBase texture, Sampler sampler) public readonly void UpdateTextureAndSampler(ShaderStage stage, ulong binding, TextureBase texture, Sampler sampler)
{ {
if (texture != null) if (texture is TextureBuffer)
{ {
_currentState.TextureRefs[binding] = new(stage, texture, sampler); // TODO: Texture buffers
}
else if (texture is Texture view)
{
_currentState.TextureRefs[binding] = new(stage, view, sampler);
} }
else else
{ {
@ -1120,52 +1124,59 @@ namespace Ryujinx.Graphics.Metal
case MetalRenderer.TextureSetIndex: case MetalRenderer.TextureSetIndex:
if (!segment.IsArray) if (!segment.IsArray)
{ {
for (int i = 0; i < count; i++) if (segment.Type != ResourceType.BufferTexture)
{ {
int index = binding + i; for (int i = 0; i < count; i++)
ref var texture = ref _currentState.TextureRefs[index];
var storage = texture.Storage;
if (storage == null)
{ {
continue; int index = binding + i;
}
var mtlTexture = storage.GetHandle(); ref var texture = ref _currentState.TextureRefs[index];
MTLRenderStages renderStages = 0; var storage = texture.Storage;
if ((segment.Stages & ResourceStages.Vertex) != 0) if (storage == null)
{
vertResourceIds[vertResourceIdIndex] = mtlTexture.GpuResourceID._impl;
vertResourceIdIndex++;
if (texture.Sampler != null)
{ {
vertResourceIds[vertResourceIdIndex] = texture.Sampler.GetSampler().GpuResourceID._impl; continue;
}
var mtlTexture = storage.GetHandle();
MTLRenderStages renderStages = 0;
if ((segment.Stages & ResourceStages.Vertex) != 0)
{
vertResourceIds[vertResourceIdIndex] = mtlTexture.GpuResourceID._impl;
vertResourceIdIndex++; vertResourceIdIndex++;
if (texture.Sampler != null)
{
vertResourceIds[vertResourceIdIndex] = texture.Sampler.GetSampler().GpuResourceID._impl;
vertResourceIdIndex++;
}
renderStages |= MTLRenderStages.RenderStageVertex;
} }
renderStages |= MTLRenderStages.RenderStageVertex; if ((segment.Stages & ResourceStages.Fragment) != 0)
}
if ((segment.Stages & ResourceStages.Fragment) != 0)
{
fragResourceIds[fragResourceIdIndex] = mtlTexture.GpuResourceID._impl;
fragResourceIdIndex++;
if (texture.Sampler != null)
{ {
fragResourceIds[fragResourceIdIndex] = texture.Sampler.GetSampler().GpuResourceID._impl; fragResourceIds[fragResourceIdIndex] = mtlTexture.GpuResourceID._impl;
fragResourceIdIndex++; fragResourceIdIndex++;
if (texture.Sampler != null)
{
fragResourceIds[fragResourceIdIndex] = texture.Sampler.GetSampler().GpuResourceID._impl;
fragResourceIdIndex++;
}
renderStages |= MTLRenderStages.RenderStageFragment;
} }
renderStages |= MTLRenderStages.RenderStageFragment; renderCommandEncoder.UseResource(new MTLResource(mtlTexture.NativePtr), MTLResourceUsage.Read, renderStages);
} }
}
renderCommandEncoder.UseResource(new MTLResource(mtlTexture.NativePtr), MTLResourceUsage.Read, renderStages); else
{
// TODO: Buffer textures
} }
} }
else else
@ -1332,34 +1343,41 @@ namespace Ryujinx.Graphics.Metal
case MetalRenderer.TextureSetIndex: case MetalRenderer.TextureSetIndex:
if (!segment.IsArray) if (!segment.IsArray)
{ {
for (int i = 0; i < count; i++) if (segment.Type != ResourceType.BufferTexture)
{ {
int index = binding + i; for (int i = 0; i < count; i++)
ref var texture = ref _currentState.TextureRefs[index];
var storage = texture.Storage;
if (storage == null)
{ {
continue; int index = binding + i;
}
var mtlTexture = storage.GetHandle(); ref var texture = ref _currentState.TextureRefs[index];
if (segment.Stages.HasFlag(ResourceStages.Compute)) var storage = texture.Storage;
{
computeCommandEncoder.UseResource(new MTLResource(mtlTexture.NativePtr), MTLResourceUsage.Read);
resourceIds[resourceIdIndex] = mtlTexture.GpuResourceID._impl;
resourceIdIndex++;
if (texture.Sampler != null) if (storage == null)
{ {
resourceIds[resourceIdIndex] = texture.Sampler.GetSampler().GpuResourceID._impl; continue;
}
var mtlTexture = storage.GetHandle();
if (segment.Stages.HasFlag(ResourceStages.Compute))
{
computeCommandEncoder.UseResource(new MTLResource(mtlTexture.NativePtr), MTLResourceUsage.Read);
resourceIds[resourceIdIndex] = mtlTexture.GpuResourceID._impl;
resourceIdIndex++; resourceIdIndex++;
if (texture.Sampler != null)
{
resourceIds[resourceIdIndex] = texture.Sampler.GetSampler().GpuResourceID._impl;
resourceIdIndex++;
}
} }
} }
} }
else
{
// TODO: Buffer textures
}
} }
else else
{ {

View file

@ -28,6 +28,7 @@ namespace Ryujinx.Graphics.Metal
private MTLComputePipelineState? _computePipelineCache; private MTLComputePipelineState? _computePipelineCache;
private bool _firstBackgroundUse; private bool _firstBackgroundUse;
public ResourceBindingSegment[][] ClearSegments { get; }
public ResourceBindingSegment[][] BindingSegments { get; } public ResourceBindingSegment[][] BindingSegments { get; }
// Argument buffer sizes for Vertex or Compute stages // Argument buffer sizes for Vertex or Compute stages
public int[] ArgumentBufferSizes { get; } public int[] ArgumentBufferSizes { get; }
@ -52,6 +53,7 @@ namespace Ryujinx.Graphics.Metal
_handles[i] = device.NewLibrary(StringHelper.NSString(shader.Code), compileOptions, (library, error) => CompilationResultHandler(library, error, index)); _handles[i] = device.NewLibrary(StringHelper.NSString(shader.Code), compileOptions, (library, error) => CompilationResultHandler(library, error, index));
} }
ClearSegments = BuildClearSegments(resourceLayout.Sets);
(BindingSegments, ArgumentBufferSizes, FragArgumentBufferSizes) = BuildBindingSegments(resourceLayout.SetUsages); (BindingSegments, ArgumentBufferSizes, FragArgumentBufferSizes) = BuildBindingSegments(resourceLayout.SetUsages);
} }
@ -96,6 +98,62 @@ namespace Ryujinx.Graphics.Metal
} }
} }
private static ResourceBindingSegment[][] BuildClearSegments(ReadOnlyCollection<ResourceDescriptorCollection> sets)
{
ResourceBindingSegment[][] segments = new ResourceBindingSegment[sets.Count][];
for (int setIndex = 0; setIndex < sets.Count; setIndex++)
{
List<ResourceBindingSegment> currentSegments = new();
ResourceDescriptor currentDescriptor = default;
int currentCount = 0;
for (int index = 0; index < sets[setIndex].Descriptors.Count; index++)
{
ResourceDescriptor descriptor = sets[setIndex].Descriptors[index];
if (currentDescriptor.Binding + currentCount != descriptor.Binding ||
currentDescriptor.Type != descriptor.Type ||
currentDescriptor.Stages != descriptor.Stages ||
currentDescriptor.Count > 1 ||
descriptor.Count > 1)
{
if (currentCount != 0)
{
currentSegments.Add(new ResourceBindingSegment(
currentDescriptor.Binding,
currentCount,
currentDescriptor.Type,
currentDescriptor.Stages,
currentDescriptor.Count > 1));
}
currentDescriptor = descriptor;
currentCount = descriptor.Count;
}
else
{
currentCount += descriptor.Count;
}
}
if (currentCount != 0)
{
currentSegments.Add(new ResourceBindingSegment(
currentDescriptor.Binding,
currentCount,
currentDescriptor.Type,
currentDescriptor.Stages,
currentDescriptor.Count > 1));
}
segments[setIndex] = currentSegments.ToArray();
}
return segments;
}
private static (ResourceBindingSegment[][], int[], int[]) BuildBindingSegments(ReadOnlyCollection<ResourceUsageCollection> setUsages) private static (ResourceBindingSegment[][], int[], int[]) BuildBindingSegments(ReadOnlyCollection<ResourceUsageCollection> setUsages)
{ {
ResourceBindingSegment[][] segments = new ResourceBindingSegment[setUsages.Count][]; ResourceBindingSegment[][] segments = new ResourceBindingSegment[setUsages.Count][];