don't end render pass when not neccessary

This commit is contained in:
Samuliak 2024-05-19 08:08:12 +02:00 committed by Isaac Marovitz
parent 2abadbd649
commit 918e1c16b7
3 changed files with 97 additions and 142 deletions

View file

@ -5,6 +5,19 @@ using System.Runtime.Versioning;
namespace Ryujinx.Graphics.Metal namespace Ryujinx.Graphics.Metal
{ {
// TODO: use this (unused right now)
public struct DirtyFlags
{
public bool Pipeline = false;
public bool DepthStencil = false;
public bool CullMode = false;
public bool Winding = false;
public bool Viewport = false;
public bool Scissor = false;
public DirtyFlags() { }
}
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
public struct EncoderState public struct EncoderState
{ {
@ -52,6 +65,9 @@ namespace Ryujinx.Graphics.Metal
public VertexBufferDescriptor[] VertexBuffers = []; public VertexBufferDescriptor[] VertexBuffers = [];
public VertexAttribDescriptor[] VertexAttribs = []; public VertexAttribDescriptor[] VertexAttribs = [];
// Dirty flags
public DirtyFlags Dirty = new();
public EncoderState() { } public EncoderState() { }
} }
} }

View file

@ -54,7 +54,80 @@ namespace Ryujinx.Graphics.Metal
var passAttachment = renderPassDescriptor.ColorAttachments.Object((ulong)i); var passAttachment = renderPassDescriptor.ColorAttachments.Object((ulong)i);
passAttachment.Texture = _currentState.RenderTargets[i]; passAttachment.Texture = _currentState.RenderTargets[i];
passAttachment.LoadAction = MTLLoadAction.Load; passAttachment.LoadAction = MTLLoadAction.Load;
}
}
var depthAttachment = renderPassDescriptor.DepthAttachment;
var stencilAttachment = renderPassDescriptor.StencilAttachment;
if (_currentState.DepthStencil != IntPtr.Zero)
{
switch (_currentState.DepthStencil.PixelFormat)
{
// Depth Only Attachment
case MTLPixelFormat.Depth16Unorm:
case MTLPixelFormat.Depth32Float:
depthAttachment.Texture = _currentState.DepthStencil;
depthAttachment.LoadAction = MTLLoadAction.Load;
break;
// Stencil Only Attachment
case MTLPixelFormat.Stencil8:
stencilAttachment.Texture = _currentState.DepthStencil;
stencilAttachment.LoadAction = MTLLoadAction.Load;
break;
// Combined Attachment
case MTLPixelFormat.Depth24UnormStencil8:
case MTLPixelFormat.Depth32FloatStencil8:
depthAttachment.Texture = _currentState.DepthStencil;
depthAttachment.LoadAction = MTLLoadAction.Load;
var unpackedFormat = FormatTable.PackedStencilToXFormat(_currentState.DepthStencil.PixelFormat);
var stencilView = _currentState.DepthStencil.NewTextureView(unpackedFormat);
stencilAttachment.Texture = stencilView;
stencilAttachment.LoadAction = MTLLoadAction.Load;
break;
default:
Logger.Error?.PrintMsg(LogClass.Gpu, $"Unsupported Depth/Stencil Format: {_currentState.DepthStencil.PixelFormat}!");
break;
}
}
// Initialise Encoder
var renderCommandEncoder = _pipeline.CommandBuffer.RenderCommandEncoder(renderPassDescriptor);
// TODO: set dirty flags all to true
return renderCommandEncoder;
}
public void RebindState(MTLRenderCommandEncoder renderCommandEncoder)
{
SetPipelineState(renderCommandEncoder);
SetDepthStencilState(renderCommandEncoder, _currentState.DepthStencilState);
SetDepthClamp(renderCommandEncoder, _currentState.DepthClipMode);
SetScissors(renderCommandEncoder, _currentState.Scissors);
SetViewports(renderCommandEncoder, _currentState.Viewports);
SetVertexBuffers(renderCommandEncoder, _currentState.VertexBuffers);
SetBuffers(renderCommandEncoder, _currentState.UniformBuffers, true);
SetBuffers(renderCommandEncoder, _currentState.StorageBuffers, true);
SetCullMode(renderCommandEncoder, _currentState.CullMode);
SetFrontFace(renderCommandEncoder, _currentState.Winding);
SetTextureAndSampler(renderCommandEncoder, ShaderStage.Vertex, _currentState.VertexTextures, _currentState.VertexSamplers);
SetTextureAndSampler(renderCommandEncoder, ShaderStage.Fragment, _currentState.FragmentTextures, _currentState.FragmentSamplers);
_currentState.Dirty = new();
}
private void SetPipelineState(MTLRenderCommandEncoder renderCommandEncoder) {
var renderPipelineDescriptor = new MTLRenderPipelineDescriptor();
for (int i = 0; i < EncoderState.MaxColorAttachments; i++)
{
if (_currentState.RenderTargets[i] != IntPtr.Zero)
{
var pipelineAttachment = renderPipelineDescriptor.ColorAttachments.Object((ulong)i); var pipelineAttachment = renderPipelineDescriptor.ColorAttachments.Object((ulong)i);
pipelineAttachment.PixelFormat = _currentState.RenderTargets[i].PixelFormat; pipelineAttachment.PixelFormat = _currentState.RenderTargets[i].PixelFormat;
pipelineAttachment.SourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha; pipelineAttachment.SourceAlphaBlendFactor = MTLBlendFactor.SourceAlpha;
@ -75,9 +148,6 @@ namespace Ryujinx.Graphics.Metal
} }
} }
var depthAttachment = renderPassDescriptor.DepthAttachment;
var stencilAttachment = renderPassDescriptor.StencilAttachment;
if (_currentState.DepthStencil != IntPtr.Zero) if (_currentState.DepthStencil != IntPtr.Zero)
{ {
switch (_currentState.DepthStencil.PixelFormat) switch (_currentState.DepthStencil.PixelFormat)
@ -85,29 +155,17 @@ namespace Ryujinx.Graphics.Metal
// Depth Only Attachment // Depth Only Attachment
case MTLPixelFormat.Depth16Unorm: case MTLPixelFormat.Depth16Unorm:
case MTLPixelFormat.Depth32Float: case MTLPixelFormat.Depth32Float:
depthAttachment.Texture = _currentState.DepthStencil;
depthAttachment.LoadAction = MTLLoadAction.Load;
renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat;
break; break;
// Stencil Only Attachment // Stencil Only Attachment
case MTLPixelFormat.Stencil8: case MTLPixelFormat.Stencil8:
stencilAttachment.Texture = _currentState.DepthStencil;
stencilAttachment.LoadAction = MTLLoadAction.Load;
renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat;
break; break;
// Combined Attachment // Combined Attachment
case MTLPixelFormat.Depth24UnormStencil8: case MTLPixelFormat.Depth24UnormStencil8:
case MTLPixelFormat.Depth32FloatStencil8: case MTLPixelFormat.Depth32FloatStencil8:
depthAttachment.Texture = _currentState.DepthStencil;
depthAttachment.LoadAction = MTLLoadAction.Load;
var unpackedFormat = FormatTable.PackedStencilToXFormat(_currentState.DepthStencil.PixelFormat);
var stencilView = _currentState.DepthStencil.NewTextureView(unpackedFormat);
stencilAttachment.Texture = stencilView;
stencilAttachment.LoadAction = MTLLoadAction.Load;
renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; renderPipelineDescriptor.DepthAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat;
renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat; renderPipelineDescriptor.StencilAttachmentPixelFormat = _currentState.DepthStencil.PixelFormat;
break; break;
@ -125,7 +183,7 @@ namespace Ryujinx.Graphics.Metal
} }
else else
{ {
return new(IntPtr.Zero); return;
} }
if (_currentState.FragmentFunction != null) if (_currentState.FragmentFunction != null)
@ -140,10 +198,6 @@ namespace Ryujinx.Graphics.Metal
Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to create Render Pipeline State: {StringHelper.String(error.LocalizedDescription)}"); Logger.Error?.PrintMsg(LogClass.Gpu, $"Failed to create Render Pipeline State: {StringHelper.String(error.LocalizedDescription)}");
} }
// Initialise Encoder
var renderCommandEncoder = _pipeline.CommandBuffer.RenderCommandEncoder(renderPassDescriptor);
renderCommandEncoder.SetRenderPipelineState(pipelineState); renderCommandEncoder.SetRenderPipelineState(pipelineState);
renderCommandEncoder.SetBlendColor( renderCommandEncoder.SetBlendColor(
@ -151,20 +205,6 @@ namespace Ryujinx.Graphics.Metal
_currentState.BlendColor.Green, _currentState.BlendColor.Green,
_currentState.BlendColor.Blue, _currentState.BlendColor.Blue,
_currentState.BlendColor.Alpha); _currentState.BlendColor.Alpha);
SetDepthStencilState(renderCommandEncoder, _currentState.DepthStencilState);
SetDepthClamp(renderCommandEncoder, _currentState.DepthClipMode);
SetScissors(renderCommandEncoder, _currentState.Scissors);
SetViewports(renderCommandEncoder, _currentState.Viewports);
SetVertexBuffers(renderCommandEncoder, _currentState.VertexBuffers);
SetBuffers(renderCommandEncoder, _currentState.UniformBuffers, true);
SetBuffers(renderCommandEncoder, _currentState.StorageBuffers, true);
SetCullMode(renderCommandEncoder, _currentState.CullMode);
SetFrontFace(renderCommandEncoder, _currentState.Winding);
SetTextureAndSampler(renderCommandEncoder, ShaderStage.Vertex, _currentState.VertexTextures, _currentState.VertexSamplers);
SetTextureAndSampler(renderCommandEncoder, ShaderStage.Fragment, _currentState.FragmentTextures, _currentState.FragmentSamplers);
return renderCommandEncoder;
} }
public void UpdateIndexBuffer(BufferRange buffer, IndexType type) public void UpdateIndexBuffer(BufferRange buffer, IndexType type)
@ -195,12 +235,6 @@ namespace Ryujinx.Graphics.Metal
_currentState.VertexFunction = prg.VertexFunction; _currentState.VertexFunction = prg.VertexFunction;
_currentState.FragmentFunction = prg.FragmentFunction; _currentState.FragmentFunction = prg.FragmentFunction;
// Requires recreating pipeline
if (_pipeline.CurrentEncoderType == EncoderType.Render)
{
_pipeline.EndCurrentPass();
}
} }
public void UpdateRenderTargets(ITexture[] colors, ITexture depthStencil) public void UpdateRenderTargets(ITexture[] colors, ITexture depthStencil)
@ -232,24 +266,12 @@ namespace Ryujinx.Graphics.Metal
public void UpdateVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs) public void UpdateVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
{ {
_currentState.VertexAttribs = vertexAttribs.ToArray(); _currentState.VertexAttribs = vertexAttribs.ToArray();
// Requires recreating pipeline
if (_pipeline.CurrentEncoderType == EncoderType.Render)
{
_pipeline.EndCurrentPass();
}
} }
public void UpdateBlendDescriptors(int index, BlendDescriptor blend) public void UpdateBlendDescriptors(int index, BlendDescriptor blend)
{ {
_currentState.BlendDescriptors[index] = blend; _currentState.BlendDescriptors[index] = blend;
_currentState.BlendColor = blend.BlendConstant; _currentState.BlendColor = blend.BlendConstant;
// Requires recreating pipeline
if (_pipeline.CurrentEncoderType == EncoderType.Render)
{
_pipeline.EndCurrentPass();
}
} }
// Inlineable // Inlineable
@ -290,14 +312,6 @@ namespace Ryujinx.Graphics.Metal
} }
_currentState.DepthStencilState = _device.NewDepthStencilState(descriptor); _currentState.DepthStencilState = _device.NewDepthStencilState(descriptor);
// Inline Update
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
SetDepthStencilState(renderCommandEncoder, _currentState.DepthStencilState);
}
} }
// Inlineable // Inlineable
@ -319,27 +333,12 @@ namespace Ryujinx.Graphics.Metal
} }
_currentState.DepthStencilState = _device.NewDepthStencilState(descriptor); _currentState.DepthStencilState = _device.NewDepthStencilState(descriptor);
// Inline Update
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
SetDepthStencilState(renderCommandEncoder, _currentState.DepthStencilState);
}
} }
// Inlineable // Inlineable
public void UpdateDepthClamp(bool clamp) public void UpdateDepthClamp(bool clamp)
{ {
_currentState.DepthClipMode = clamp ? MTLDepthClipMode.Clamp : MTLDepthClipMode.Clip; _currentState.DepthClipMode = clamp ? MTLDepthClipMode.Clamp : MTLDepthClipMode.Clip;
// Inline Update
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
}
} }
// Inlineable // Inlineable
@ -366,14 +365,6 @@ namespace Ryujinx.Graphics.Metal
y = (ulong)region.Y y = (ulong)region.Y
}; };
} }
// Inline Update
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
SetScissors(renderCommandEncoder, _currentState.Scissors);
}
} }
// Inlineable // Inlineable
@ -399,25 +390,11 @@ namespace Ryujinx.Graphics.Metal
zfar = Clamp(viewport.DepthFar) zfar = Clamp(viewport.DepthFar)
}; };
} }
// Inline Update
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
SetViewports(renderCommandEncoder, _currentState.Viewports);
}
} }
public void UpdateVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers) public void UpdateVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
{ {
_currentState.VertexBuffers = vertexBuffers.ToArray(); _currentState.VertexBuffers = vertexBuffers.ToArray();
// Requires recreating pipeline
if (_pipeline.CurrentEncoderType == EncoderType.Render)
{
_pipeline.EndCurrentPass();
}
} }
// Inlineable // Inlineable
@ -437,14 +414,6 @@ namespace Ryujinx.Graphics.Metal
}); });
} }
} }
// Inline Update
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
SetBuffers(renderCommandEncoder, _currentState.UniformBuffers, true);
}
} }
// Inlineable // Inlineable
@ -465,42 +434,18 @@ namespace Ryujinx.Graphics.Metal
}); });
} }
} }
// Inline Update
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
SetBuffers(renderCommandEncoder, _currentState.StorageBuffers, true);
}
} }
// Inlineable // Inlineable
public void UpdateCullMode(bool enable, Face face) public void UpdateCullMode(bool enable, Face face)
{ {
_currentState.CullMode = enable ? face.Convert() : MTLCullMode.None; _currentState.CullMode = enable ? face.Convert() : MTLCullMode.None;
// Inline Update
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
SetCullMode(renderCommandEncoder, _currentState.CullMode);
}
} }
// Inlineable // Inlineable
public void UpdateFrontFace(FrontFace frontFace) public void UpdateFrontFace(FrontFace frontFace)
{ {
_currentState.Winding = frontFace.Convert(); _currentState.Winding = frontFace.Convert();
// Inline Update
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
SetFrontFace(renderCommandEncoder, _currentState.Winding);
}
} }
// Inlineable // Inlineable
@ -517,13 +462,6 @@ namespace Ryujinx.Graphics.Metal
_currentState.VertexSamplers[binding] = sampler; _currentState.VertexSamplers[binding] = sampler;
break; break;
} }
if (_pipeline.CurrentEncoderType == EncoderType.Render && _pipeline.CurrentEncoder != null)
{
var renderCommandEncoder = new MTLRenderCommandEncoder(_pipeline.CurrentEncoder.Value);
SetTextureAndSampler(renderCommandEncoder, ShaderStage.Vertex, _currentState.VertexTextures, _currentState.VertexSamplers);
SetTextureAndSampler(renderCommandEncoder, ShaderStage.Fragment, _currentState.FragmentTextures, _currentState.FragmentSamplers);
}
} }
private static void SetDepthStencilState(MTLRenderCommandEncoder renderCommandEncoder, MTLDepthStencilState? depthStencilState) private static void SetDepthStencilState(MTLRenderCommandEncoder renderCommandEncoder, MTLDepthStencilState? depthStencilState)

View file

@ -48,15 +48,16 @@ namespace Ryujinx.Graphics.Metal
public MTLRenderCommandEncoder GetOrCreateRenderEncoder() public MTLRenderCommandEncoder GetOrCreateRenderEncoder()
{ {
if (_currentEncoder != null) if (_currentEncoder == null || _currentEncoderType != EncoderType.Render)
{ {
if (_currentEncoderType == EncoderType.Render) BeginRenderPass();
{
return new MTLRenderCommandEncoder(_currentEncoder.Value);
}
} }
return BeginRenderPass(); var renderCommandEncoder = new MTLRenderCommandEncoder(_currentEncoder.Value);
_encoderStateManager.RebindState(renderCommandEncoder);
return renderCommandEncoder;
} }
public MTLBlitCommandEncoder GetOrCreateBlitEncoder() public MTLBlitCommandEncoder GetOrCreateBlitEncoder()