Clone the state & flip viewport vertically (#16)

* implement texture get data

* reset all state before blit & clone state

* format

* support blit regions

* implement source region for blit

* replace bottom with top

* account for 0 size

* support image flipping

* revert presentation fixes & y flip

* revert

* flip viewport vertically

* switch face winding

* comment

* use SetBytes for texture clear

* implement missing compute builtins

* change storage and texture buffer alignment

* correct compute builtins

* don't use nullable for textures and samplers

* remove incorrect texture get data implementation

* Cleanup IntPtrs

---------

Co-authored-by: Isaac Marovitz <isaacryu@icloud.com>
This commit is contained in:
SamoZ256 2024-05-27 13:58:03 +02:00 committed by Isaac Marovitz
parent 20b1f6a6ee
commit 1f91c74a95
8 changed files with 91 additions and 69 deletions

View file

@ -44,9 +44,16 @@ namespace Ryujinx.Graphics.Metal
_depthStencilCache.Dispose();
}
public readonly void SaveState()
public void SaveState()
{
_backStates.Push(_currentState);
_currentState = _currentState.Clone();
}
public void SaveAndResetState()
{
_backStates.Push(_currentState);
_currentState = new();
}
public void RestoreState()
@ -65,6 +72,9 @@ namespace Ryujinx.Graphics.Metal
SetBuffers(renderCommandEncoder, _currentState.StorageBuffers, true);
SetCullMode(renderCommandEncoder);
SetFrontFace(renderCommandEncoder);
// Mark the other state as dirty
_currentState.Dirty.MarkAll();
}
else
{
@ -184,8 +194,9 @@ namespace Ryujinx.Graphics.Metal
pipelineAttachment.SourceRGBBlendFactor = MTLBlendFactor.SourceAlpha;
pipelineAttachment.DestinationRGBBlendFactor = MTLBlendFactor.OneMinusSourceAlpha;
if (_currentState.BlendDescriptors.TryGetValue(i, out BlendDescriptor blendDescriptor))
if (_currentState.BlendDescriptors[i] != null)
{
var blendDescriptor = _currentState.BlendDescriptors[i].Value;
pipelineAttachment.SetBlendingEnabled(blendDescriptor.Enable);
pipelineAttachment.AlphaBlendOperation = blendDescriptor.AlphaOp.Convert();
pipelineAttachment.RgbBlendOperation = blendDescriptor.ColorOp.Convert();
@ -469,12 +480,13 @@ namespace Ryujinx.Graphics.Metal
for (int i = 0; i < viewports.Length; i++)
{
var viewport = viewports[i];
// Y coordinate is inverted
_currentState.Viewports[i] = new MTLViewport
{
originX = viewport.Region.X,
originY = viewport.Region.Y,
originY = viewport.Region.Y + viewport.Region.Height,
width = viewport.Region.Width,
height = viewport.Region.Height,
height = -viewport.Region.Height,
znear = Clamp(viewport.DepthNear),
zfar = Clamp(viewport.DepthFar)
};
@ -708,31 +720,39 @@ namespace Ryujinx.Graphics.Metal
renderCommandEncoder.SetFrontFacingWinding(_currentState.Winding);
}
private static void SetTextureAndSampler(MTLRenderCommandEncoder renderCommandEncoder, ShaderStage stage, Dictionary<ulong, MTLTexture> textures, Dictionary<ulong, MTLSamplerState> samplers)
private static void SetTextureAndSampler(MTLRenderCommandEncoder renderCommandEncoder, ShaderStage stage, MTLTexture[] textures, MTLSamplerState[] samplers)
{
foreach (var texture in textures)
for (int i = 0; i < textures.Length; i++)
{
switch (stage)
var texture = textures[i];
if (texture != IntPtr.Zero)
{
case ShaderStage.Vertex:
renderCommandEncoder.SetVertexTexture(texture.Value, texture.Key);
break;
case ShaderStage.Fragment:
renderCommandEncoder.SetFragmentTexture(texture.Value, texture.Key);
break;
switch (stage)
{
case ShaderStage.Vertex:
renderCommandEncoder.SetVertexTexture(texture, (ulong)i);
break;
case ShaderStage.Fragment:
renderCommandEncoder.SetFragmentTexture(texture, (ulong)i);
break;
}
}
}
foreach (var sampler in samplers)
for (int i = 0; i < samplers.Length; i++)
{
switch (stage)
var sampler = samplers[i];
if (sampler != IntPtr.Zero)
{
case ShaderStage.Vertex:
renderCommandEncoder.SetVertexSamplerState(sampler.Value, sampler.Key);
break;
case ShaderStage.Fragment:
renderCommandEncoder.SetFragmentSamplerState(sampler.Value, sampler.Key);
break;
switch (stage)
{
case ShaderStage.Vertex:
renderCommandEncoder.SetVertexSamplerState(sampler, (ulong)i);
break;
case ShaderStage.Fragment:
renderCommandEncoder.SetFragmentSamplerState(sampler, (ulong)i);
break;
}
}
}
}