implement save and restore state system
This commit is contained in:
parent
295845e6e3
commit
b475a44941
3 changed files with 45 additions and 19 deletions
|
@ -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()
|
||||||
{
|
{
|
||||||
_pipeline.EndCurrentPass();
|
if (_backStates.Count > 0)
|
||||||
|
{
|
||||||
|
_currentState = _backStates[_backStates.Count - 1];
|
||||||
|
_backStates.RemoveAt(_backStates.Count - 1);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Gpu, "No state to restore");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue