0
0
Fork 0
mirror of https://github.com/GreemDev/Ryujinx.git synced 2024-12-23 04:35:46 +00:00

implement save and restore state system

This commit is contained in:
Samuliak 2024-05-24 15:09:06 +02:00 committed by Isaac Marovitz
parent 295845e6e3
commit b475a44941
3 changed files with 45 additions and 19 deletions

View file

@ -17,8 +17,8 @@ namespace Ryujinx.Graphics.Metal
private readonly RenderPipelineCache _renderPipelineCache; private readonly RenderPipelineCache _renderPipelineCache;
private readonly DepthStencilCache _depthStencilCache; private readonly DepthStencilCache _depthStencilCache;
private EncoderState _currentState = new(); public EncoderState _currentState = new();
private EncoderState _backState = new(); public List<EncoderState> _backStates = new();
public readonly MTLBuffer IndexBuffer => _currentState.IndexBuffer; public readonly MTLBuffer IndexBuffer => _currentState.IndexBuffer;
public readonly MTLIndexType IndexType => _currentState.IndexType; public readonly MTLIndexType IndexType => _currentState.IndexType;
@ -34,13 +34,20 @@ namespace Ryujinx.Graphics.Metal
_depthStencilCache = new(device); _depthStencilCache = new(device);
} }
public void SwapStates() public void SaveState()
{ {
(_currentState, _backState) = (_backState, _currentState); _backStates.Add(_currentState);
}
if (_pipeline.CurrentEncoderType == EncoderType.Render) public void RestoreState()
{
if (_backStates.Count > 0)
{ {
_pipeline.EndCurrentPass(); _currentState = _backStates[_backStates.Count - 1];
_backStates.RemoveAt(_backStates.Count - 1);
} else
{
Logger.Error?.Print(LogClass.Gpu, "No state to restore");
} }
} }

View file

@ -64,12 +64,17 @@ namespace Ryujinx.Graphics.Metal
MipFilter = MTLSamplerMipFilter.NotMipmapped MipFilter = MTLSamplerMipFilter.NotMipmapped
}); });
// Save current state
_pipeline.SaveState();
_pipeline.SetProgram(_programColorBlit); _pipeline.SetProgram(_programColorBlit);
_pipeline.SetRenderTargets([destination], null); _pipeline.SetRenderTargets([destination], null);
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, source, new Sampler(sampler)); _pipeline.SetTextureAndSampler(ShaderStage.Fragment, 0, source, new Sampler(sampler));
_pipeline.SetPrimitiveTopology(PrimitiveTopology.Triangles); _pipeline.SetPrimitiveTopology(PrimitiveTopology.Triangles);
_pipeline.Draw(6, 1, 0, 0); _pipeline.Draw(6, 1, 0, 0);
_pipeline.Finish();
// Restore previous state
_pipeline.RestoreState();
} }
public unsafe void ClearColor( public unsafe void ClearColor(
@ -91,6 +96,9 @@ namespace Ryujinx.Graphics.Metal
var handle = buffer.NativePtr; var handle = buffer.NativePtr;
var range = new BufferRange(Unsafe.As<IntPtr, BufferHandle>(ref handle), 0, ClearColorBufferSize); var range = new BufferRange(Unsafe.As<IntPtr, BufferHandle>(ref handle), 0, ClearColorBufferSize);
// Save current state
_pipeline.SaveState();
_pipeline.SetUniformBuffers([new BufferAssignment(0, range)]); _pipeline.SetUniformBuffers([new BufferAssignment(0, range)]);
_pipeline.SetProgram(_programColorClear); _pipeline.SetProgram(_programColorClear);
@ -98,7 +106,9 @@ namespace Ryujinx.Graphics.Metal
// _pipeline.SetRenderTargetColorMasks([componentMask]); // _pipeline.SetRenderTargetColorMasks([componentMask]);
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
_pipeline.Draw(4, 1, 0, 0); _pipeline.Draw(4, 1, 0, 0);
_pipeline.Finish();
// Restore previous state
_pipeline.RestoreState();
} }
public unsafe void ClearDepthStencil( public unsafe void ClearDepthStencil(
@ -123,15 +133,19 @@ namespace Ryujinx.Graphics.Metal
var handle = buffer.NativePtr; var handle = buffer.NativePtr;
var range = new BufferRange(Unsafe.As<IntPtr, BufferHandle>(ref handle), 0, ClearColorBufferSize); var range = new BufferRange(Unsafe.As<IntPtr, BufferHandle>(ref handle), 0, ClearColorBufferSize);
// Save current state
_pipeline.SaveState();
_pipeline.SetUniformBuffers([new BufferAssignment(0, range)]); _pipeline.SetUniformBuffers([new BufferAssignment(0, range)]);
_pipeline.SetProgram(_programDepthStencilClear); _pipeline.SetProgram(_programDepthStencilClear);
_pipeline.SetRenderTargets([], dst);
_pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip); _pipeline.SetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
_pipeline.SetDepthTest(new DepthTestDescriptor(true, depthMask, CompareOp.Always)); _pipeline.SetDepthTest(new DepthTestDescriptor(true, depthMask, CompareOp.Always));
// _pipeline.SetStencilTest(CreateStencilTestDescriptor(stencilMask != 0, stencilValue, 0xFF, stencilMask)); // _pipeline.SetStencilTest(CreateStencilTestDescriptor(stencilMask != 0, stencilValue, 0xFF, stencilMask));
_pipeline.Draw(4, 1, 0, 0); _pipeline.Draw(4, 1, 0, 0);
_pipeline.Finish();
// Restore previous state
_pipeline.RestoreState();
} }
private static StencilTestDescriptor CreateStencilTestDescriptor( private static StencilTestDescriptor CreateStencilTestDescriptor(

View file

@ -46,6 +46,16 @@ namespace Ryujinx.Graphics.Metal
_encoderStateManager = new EncoderStateManager(_device, this); _encoderStateManager = new EncoderStateManager(_device, this);
} }
public void SaveState()
{
_encoderStateManager.SaveState();
}
public void RestoreState()
{
_encoderStateManager.RestoreState();
}
public MTLRenderCommandEncoder GetOrCreateRenderEncoder() public MTLRenderCommandEncoder GetOrCreateRenderEncoder()
{ {
MTLRenderCommandEncoder renderCommandEncoder; MTLRenderCommandEncoder renderCommandEncoder;
@ -161,7 +171,7 @@ namespace Ryujinx.Graphics.Metal
EndCurrentPass(); EndCurrentPass();
_encoderStateManager.SwapStates(); SaveState();
// TODO: Clean this up // TODO: Clean this up
var textureInfo = new TextureCreateInfo((int)drawable.Texture.Width, (int)drawable.Texture.Height, (int)drawable.Texture.Depth, (int)drawable.Texture.MipmapLevelCount, (int)drawable.Texture.SampleCount, 0, 0, 0, Format.B8G8R8A8Unorm, 0, Target.Texture2D, SwizzleComponent.Red, SwizzleComponent.Green, SwizzleComponent.Blue, SwizzleComponent.Alpha); var textureInfo = new TextureCreateInfo((int)drawable.Texture.Width, (int)drawable.Texture.Height, (int)drawable.Texture.Depth, (int)drawable.Texture.MipmapLevelCount, (int)drawable.Texture.SampleCount, 0, 0, 0, Format.B8G8R8A8Unorm, 0, Target.Texture2D, SwizzleComponent.Red, SwizzleComponent.Green, SwizzleComponent.Blue, SwizzleComponent.Alpha);
@ -169,15 +179,14 @@ namespace Ryujinx.Graphics.Metal
_helperShader.BlitColor(tex, dest); _helperShader.BlitColor(tex, dest);
EndCurrentPass();
_commandBuffer.PresentDrawable(drawable); _commandBuffer.PresentDrawable(drawable);
_commandBuffer.Commit(); _commandBuffer.Commit();
_commandBuffer = _commandQueue.CommandBuffer(); _commandBuffer = _commandQueue.CommandBuffer();
}
public void Finish() RestoreState();
{
_encoderStateManager.SwapStates();
} }
public void Barrier() public void Barrier()
@ -207,8 +216,6 @@ namespace Ryujinx.Graphics.Metal
Texture target = _encoderStateManager.RenderTargets[index]; Texture target = _encoderStateManager.RenderTargets[index];
_encoderStateManager.SwapStates();
_helperShader.ClearColor(target, colors); _helperShader.ClearColor(target, colors);
} }
@ -216,8 +223,6 @@ namespace Ryujinx.Graphics.Metal
{ {
Texture target = _encoderStateManager.DepthStencil; Texture target = _encoderStateManager.DepthStencil;
_encoderStateManager.SwapStates();
_helperShader.ClearDepthStencil(target, [depthValue], depthMask, stencilValue, stencilMask); _helperShader.ClearDepthStencil(target, [depthValue], depthMask, stencilValue, stencilMask);
} }