| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877 |
- using Ryujinx.Common.Logging;
- using Ryujinx.Graphics.GAL;
- using Ryujinx.Graphics.Shader;
- using SharpMetal.Foundation;
- using SharpMetal.Metal;
- using SharpMetal.QuartzCore;
- using System;
- using System.Runtime.Versioning;
- namespace Ryujinx.Graphics.Metal
- {
- public enum EncoderType
- {
- Blit,
- Compute,
- Render,
- None
- }
- [SupportedOSPlatform("macos")]
- class Pipeline : IPipeline, IEncoderFactory, IDisposable
- {
- private const ulong MinByteWeightForFlush = 256 * 1024 * 1024; // MiB
- private readonly MTLDevice _device;
- private readonly MetalRenderer _renderer;
- private EncoderStateManager _encoderStateManager;
- private ulong _byteWeight;
- public MTLCommandBuffer CommandBuffer;
- public IndexBufferPattern QuadsToTrisPattern;
- public IndexBufferPattern TriFanToTrisPattern;
- internal CommandBufferScoped? PreloadCbs { get; private set; }
- internal CommandBufferScoped Cbs { get; private set; }
- internal CommandBufferEncoder Encoders => Cbs.Encoders;
- internal EncoderType CurrentEncoderType => Encoders.CurrentEncoderType;
- public Pipeline(MTLDevice device, MetalRenderer renderer)
- {
- _device = device;
- _renderer = renderer;
- renderer.CommandBufferPool.Initialize(this);
- CommandBuffer = (Cbs = _renderer.CommandBufferPool.Rent()).CommandBuffer;
- }
- internal void InitEncoderStateManager(BufferManager bufferManager)
- {
- _encoderStateManager = new EncoderStateManager(_device, bufferManager, this);
- QuadsToTrisPattern = new IndexBufferPattern(_renderer, 4, 6, 0, [0, 1, 2, 0, 2, 3], 4, false);
- TriFanToTrisPattern = new IndexBufferPattern(_renderer, 3, 3, 2, [int.MinValue, -1, 0], 1, true);
- }
- public EncoderState SwapState(EncoderState state, DirtyFlags flags = DirtyFlags.All, bool endRenderPass = true)
- {
- if (endRenderPass && CurrentEncoderType == EncoderType.Render)
- {
- EndCurrentPass();
- }
- return _encoderStateManager.SwapState(state, flags);
- }
- public PredrawState SavePredrawState()
- {
- return _encoderStateManager.SavePredrawState();
- }
- public void RestorePredrawState(PredrawState state)
- {
- _encoderStateManager.RestorePredrawState(state);
- }
- public void SetClearLoadAction(bool clear)
- {
- _encoderStateManager.SetClearLoadAction(clear);
- }
- public MTLRenderCommandEncoder GetOrCreateRenderEncoder(bool forDraw = false)
- {
- // Mark all state as dirty to ensure it is set on the new encoder
- if (Cbs.Encoders.CurrentEncoderType != EncoderType.Render)
- {
- _encoderStateManager.SignalRenderDirty();
- }
- if (forDraw)
- {
- _encoderStateManager.RenderResourcesPrepass();
- }
- MTLRenderCommandEncoder renderCommandEncoder = Cbs.Encoders.EnsureRenderEncoder();
- if (forDraw)
- {
- _encoderStateManager.RebindRenderState(renderCommandEncoder);
- }
- return renderCommandEncoder;
- }
- public MTLBlitCommandEncoder GetOrCreateBlitEncoder()
- {
- return Cbs.Encoders.EnsureBlitEncoder();
- }
- public MTLComputeCommandEncoder GetOrCreateComputeEncoder(bool forDispatch = false)
- {
- // Mark all state as dirty to ensure it is set on the new encoder
- if (Cbs.Encoders.CurrentEncoderType != EncoderType.Compute)
- {
- _encoderStateManager.SignalComputeDirty();
- }
- if (forDispatch)
- {
- _encoderStateManager.ComputeResourcesPrepass();
- }
- MTLComputeCommandEncoder computeCommandEncoder = Cbs.Encoders.EnsureComputeEncoder();
- if (forDispatch)
- {
- _encoderStateManager.RebindComputeState(computeCommandEncoder);
- }
- return computeCommandEncoder;
- }
- public void EndCurrentPass()
- {
- Cbs.Encoders.EndCurrentPass();
- }
- public MTLRenderCommandEncoder CreateRenderCommandEncoder()
- {
- return _encoderStateManager.CreateRenderCommandEncoder();
- }
- public MTLComputeCommandEncoder CreateComputeCommandEncoder()
- {
- return _encoderStateManager.CreateComputeCommandEncoder();
- }
- public void Present(CAMetalDrawable drawable, Texture src, Extents2D srcRegion, Extents2D dstRegion, bool isLinear)
- {
- // TODO: Clean this up
- TextureCreateInfo textureInfo = new((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);
- Texture dst = new(_device, _renderer, this, textureInfo, drawable.Texture, 0, 0);
- _renderer.HelperShader.BlitColor(Cbs, src, dst, srcRegion, dstRegion, isLinear, true);
- EndCurrentPass();
- Cbs.CommandBuffer.PresentDrawable(drawable);
- FlushCommandsImpl();
- // TODO: Auto flush counting
- _renderer.SyncManager.GetAndResetWaitTicks();
- // Cleanup
- dst.Dispose();
- }
- public CommandBufferScoped GetPreloadCommandBuffer()
- {
- PreloadCbs ??= _renderer.CommandBufferPool.Rent();
- return PreloadCbs.Value;
- }
- public void FlushCommandsIfWeightExceeding(IAuto disposedResource, ulong byteWeight)
- {
- bool usedByCurrentCb = disposedResource.HasCommandBufferDependency(Cbs);
- if (PreloadCbs != null && !usedByCurrentCb)
- {
- usedByCurrentCb = disposedResource.HasCommandBufferDependency(PreloadCbs.Value);
- }
- if (usedByCurrentCb)
- {
- // Since we can only free memory after the command buffer that uses a given resource was executed,
- // keeping the command buffer might cause a high amount of memory to be in use.
- // To prevent that, we force submit command buffers if the memory usage by resources
- // in use by the current command buffer is above a given limit, and those resources were disposed.
- _byteWeight += byteWeight;
- if (_byteWeight >= MinByteWeightForFlush)
- {
- FlushCommandsImpl();
- }
- }
- }
- public void FlushCommandsImpl()
- {
- EndCurrentPass();
- _byteWeight = 0;
- if (PreloadCbs != null)
- {
- PreloadCbs.Value.Dispose();
- PreloadCbs = null;
- }
- CommandBuffer = (Cbs = _renderer.CommandBufferPool.ReturnAndRent(Cbs)).CommandBuffer;
- _renderer.RegisterFlush();
- }
- public void DirtyTextures()
- {
- _encoderStateManager.DirtyTextures();
- }
- public void DirtyImages()
- {
- _encoderStateManager.DirtyImages();
- }
- public void Blit(
- Texture src,
- Texture dst,
- Extents2D srcRegion,
- Extents2D dstRegion,
- bool isDepthOrStencil,
- bool linearFilter)
- {
- if (isDepthOrStencil)
- {
- _renderer.HelperShader.BlitDepthStencil(Cbs, src, dst, srcRegion, dstRegion);
- }
- else
- {
- _renderer.HelperShader.BlitColor(Cbs, src, dst, srcRegion, dstRegion, linearFilter);
- }
- }
- public void Barrier()
- {
- switch (CurrentEncoderType)
- {
- case EncoderType.Render:
- {
- MTLBarrierScope scope = MTLBarrierScope.Buffers | MTLBarrierScope.Textures | MTLBarrierScope.RenderTargets;
- MTLRenderStages stages = MTLRenderStages.RenderStageVertex | MTLRenderStages.RenderStageFragment;
- Encoders.RenderEncoder.MemoryBarrier(scope, stages, stages);
- break;
- }
- case EncoderType.Compute:
- {
- MTLBarrierScope scope = MTLBarrierScope.Buffers | MTLBarrierScope.Textures | MTLBarrierScope.RenderTargets;
- Encoders.ComputeEncoder.MemoryBarrier(scope);
- break;
- }
- }
- }
- public void ClearBuffer(BufferHandle destination, int offset, int size, uint value)
- {
- MTLBlitCommandEncoder blitCommandEncoder = GetOrCreateBlitEncoder();
- MTLBuffer mtlBuffer = _renderer.BufferManager.GetBuffer(destination, offset, size, true).Get(Cbs, offset, size, true).Value;
- // Might need a closer look, range's count, lower, and upper bound
- // must be a multiple of 4
- blitCommandEncoder.FillBuffer(mtlBuffer,
- new NSRange
- {
- location = (ulong)offset,
- length = (ulong)size
- },
- (byte)value);
- }
- public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color)
- {
- float[] colors = [color.Red, color.Green, color.Blue, color.Alpha];
- Texture dst = _encoderStateManager.RenderTargets[index];
- // TODO: Remove workaround for Wonder which has an invalid texture due to unsupported format
- if (dst == null)
- {
- Logger.Warning?.PrintMsg(LogClass.Gpu, "Attempted to clear invalid render target!");
- return;
- }
- _renderer.HelperShader.ClearColor(index, colors, componentMask, dst.Width, dst.Height, dst.Info.Format);
- }
- public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask)
- {
- Texture depthStencil = _encoderStateManager.DepthStencil;
- if (depthStencil == null)
- {
- return;
- }
- _renderer.HelperShader.ClearDepthStencil(depthValue, depthMask, stencilValue, stencilMask, depthStencil.Width, depthStencil.Height);
- }
- public void CommandBufferBarrier()
- {
- Barrier();
- }
- public void CopyBuffer(BufferHandle src, BufferHandle dst, int srcOffset, int dstOffset, int size)
- {
- Auto<DisposableBuffer> srcBuffer = _renderer.BufferManager.GetBuffer(src, srcOffset, size, false);
- Auto<DisposableBuffer> dstBuffer = _renderer.BufferManager.GetBuffer(dst, dstOffset, size, true);
- BufferHolder.Copy(Cbs, srcBuffer, dstBuffer, srcOffset, dstOffset, size);
- }
- public void PushDebugGroup(string name)
- {
- MTLCommandEncoder? encoder = Encoders.CurrentEncoder;
- NSString debugGroupName = StringHelper.NSString(name);
- if (encoder == null)
- {
- return;
- }
- switch (Encoders.CurrentEncoderType)
- {
- case EncoderType.Render:
- encoder.Value.PushDebugGroup(debugGroupName);
- break;
- case EncoderType.Blit:
- encoder.Value.PushDebugGroup(debugGroupName);
- break;
- case EncoderType.Compute:
- encoder.Value.PushDebugGroup(debugGroupName);
- break;
- }
- }
- public void PopDebugGroup()
- {
- MTLCommandEncoder? encoder = Encoders.CurrentEncoder;
- if (encoder == null)
- {
- return;
- }
- switch (Encoders.CurrentEncoderType)
- {
- case EncoderType.Render:
- encoder.Value.PopDebugGroup();
- break;
- case EncoderType.Blit:
- encoder.Value.PopDebugGroup();
- break;
- case EncoderType.Compute:
- encoder.Value.PopDebugGroup();
- break;
- }
- }
- public void DispatchCompute(int groupsX, int groupsY, int groupsZ)
- {
- DispatchCompute(groupsX, groupsY, groupsZ, String.Empty);
- }
- public void DispatchCompute(int groupsX, int groupsY, int groupsZ, string debugGroupName)
- {
- MTLComputeCommandEncoder computeCommandEncoder = GetOrCreateComputeEncoder(true);
- ComputeSize localSize = _encoderStateManager.ComputeLocalSize;
- if (debugGroupName != String.Empty)
- {
- PushDebugGroup(debugGroupName);
- }
- computeCommandEncoder.DispatchThreadgroups(
- new MTLSize { width = (ulong)groupsX, height = (ulong)groupsY, depth = (ulong)groupsZ },
- new MTLSize { width = (ulong)localSize.X, height = (ulong)localSize.Y, depth = (ulong)localSize.Z });
- if (debugGroupName != String.Empty)
- {
- PopDebugGroup();
- }
- }
- public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance)
- {
- Draw(vertexCount, instanceCount, firstVertex, firstInstance, String.Empty);
- }
- public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance, string debugGroupName)
- {
- if (vertexCount == 0)
- {
- return;
- }
- MTLPrimitiveType primitiveType = TopologyRemap(_encoderStateManager.Topology).Convert();
- if (TopologyUnsupported(_encoderStateManager.Topology))
- {
- IndexBufferPattern pattern = GetIndexBufferPattern();
- BufferHandle handle = pattern.GetRepeatingBuffer(vertexCount, out int indexCount);
- Auto<DisposableBuffer> buffer = _renderer.BufferManager.GetBuffer(handle, false);
- MTLBuffer mtlBuffer = buffer.Get(Cbs, 0, indexCount * sizeof(int)).Value;
- MTLRenderCommandEncoder renderCommandEncoder = GetOrCreateRenderEncoder(true);
- renderCommandEncoder.DrawIndexedPrimitives(
- primitiveType,
- (ulong)indexCount,
- MTLIndexType.UInt32,
- mtlBuffer,
- 0);
- }
- else
- {
- MTLRenderCommandEncoder renderCommandEncoder = GetOrCreateRenderEncoder(true);
- if (debugGroupName != String.Empty)
- {
- PushDebugGroup(debugGroupName);
- }
- renderCommandEncoder.DrawPrimitives(
- primitiveType,
- (ulong)firstVertex,
- (ulong)vertexCount,
- (ulong)instanceCount,
- (ulong)firstInstance);
- if (debugGroupName != String.Empty)
- {
- PopDebugGroup();
- }
- }
- }
- private IndexBufferPattern GetIndexBufferPattern()
- {
- return _encoderStateManager.Topology switch
- {
- PrimitiveTopology.Quads => QuadsToTrisPattern,
- PrimitiveTopology.TriangleFan or PrimitiveTopology.Polygon => TriFanToTrisPattern,
- _ => throw new NotSupportedException($"Unsupported topology: {_encoderStateManager.Topology}"),
- };
- }
- private PrimitiveTopology TopologyRemap(PrimitiveTopology topology)
- {
- return topology switch
- {
- PrimitiveTopology.Quads => PrimitiveTopology.Triangles,
- PrimitiveTopology.QuadStrip => PrimitiveTopology.TriangleStrip,
- PrimitiveTopology.TriangleFan or PrimitiveTopology.Polygon => PrimitiveTopology.Triangles,
- _ => topology,
- };
- }
- private bool TopologyUnsupported(PrimitiveTopology topology)
- {
- return topology switch
- {
- PrimitiveTopology.Quads or PrimitiveTopology.TriangleFan or PrimitiveTopology.Polygon => true,
- _ => false,
- };
- }
- public void DrawIndexed(int indexCount, int instanceCount, int firstIndex, int firstVertex, int firstInstance)
- {
- if (indexCount == 0)
- {
- return;
- }
- MTLBuffer mtlBuffer;
- int offset;
- MTLIndexType type;
- int finalIndexCount = indexCount;
- MTLPrimitiveType primitiveType = TopologyRemap(_encoderStateManager.Topology).Convert();
- if (TopologyUnsupported(_encoderStateManager.Topology))
- {
- IndexBufferPattern pattern = GetIndexBufferPattern();
- int convertedCount = pattern.GetConvertedCount(indexCount);
- finalIndexCount = convertedCount;
- (mtlBuffer, offset, type) = _encoderStateManager.IndexBuffer.GetConvertedIndexBuffer(_renderer, Cbs, firstIndex, indexCount, convertedCount, pattern);
- }
- else
- {
- (mtlBuffer, offset, type) = _encoderStateManager.IndexBuffer.GetIndexBuffer(_renderer, Cbs);
- }
- if (mtlBuffer.NativePtr != IntPtr.Zero)
- {
- MTLRenderCommandEncoder renderCommandEncoder = GetOrCreateRenderEncoder(true);
- renderCommandEncoder.DrawIndexedPrimitives(
- primitiveType,
- (ulong)finalIndexCount,
- type,
- mtlBuffer,
- (ulong)offset,
- (ulong)instanceCount,
- firstVertex,
- (ulong)firstInstance);
- }
- }
- public void DrawIndexedIndirect(BufferRange indirectBuffer)
- {
- DrawIndexedIndirectOffset(indirectBuffer);
- }
- public void DrawIndexedIndirectOffset(BufferRange indirectBuffer, int offset = 0)
- {
- // TODO: Reindex unsupported topologies
- if (TopologyUnsupported(_encoderStateManager.Topology))
- {
- Logger.Warning?.Print(LogClass.Gpu, $"Drawing indexed with unsupported topology: {_encoderStateManager.Topology}");
- }
- MTLBuffer buffer = _renderer.BufferManager
- .GetBuffer(indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false)
- .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
- MTLPrimitiveType primitiveType = TopologyRemap(_encoderStateManager.Topology).Convert();
- (MTLBuffer indexBuffer, int indexOffset, MTLIndexType type) = _encoderStateManager.IndexBuffer.GetIndexBuffer(_renderer, Cbs);
- if (indexBuffer.NativePtr != IntPtr.Zero && buffer.NativePtr != IntPtr.Zero)
- {
- MTLRenderCommandEncoder renderCommandEncoder = GetOrCreateRenderEncoder(true);
- renderCommandEncoder.DrawIndexedPrimitives(
- primitiveType,
- type,
- indexBuffer,
- (ulong)indexOffset,
- buffer,
- (ulong)(indirectBuffer.Offset + offset));
- }
- }
- public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
- {
- for (int i = 0; i < maxDrawCount; i++)
- {
- DrawIndexedIndirectOffset(indirectBuffer, stride * i);
- }
- }
- public void DrawIndirect(BufferRange indirectBuffer)
- {
- DrawIndirectOffset(indirectBuffer);
- }
- public void DrawIndirectOffset(BufferRange indirectBuffer, int offset = 0)
- {
- if (TopologyUnsupported(_encoderStateManager.Topology))
- {
- // TODO: Reindex unsupported topologies
- Logger.Warning?.Print(LogClass.Gpu, $"Drawing indirect with unsupported topology: {_encoderStateManager.Topology}");
- }
- MTLBuffer buffer = _renderer.BufferManager
- .GetBuffer(indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, false)
- .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
- MTLPrimitiveType primitiveType = TopologyRemap(_encoderStateManager.Topology).Convert();
- MTLRenderCommandEncoder renderCommandEncoder = GetOrCreateRenderEncoder(true);
- renderCommandEncoder.DrawPrimitives(
- primitiveType,
- buffer,
- (ulong)(indirectBuffer.Offset + offset));
- }
- public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride)
- {
- for (int i = 0; i < maxDrawCount; i++)
- {
- DrawIndirectOffset(indirectBuffer, stride * i);
- }
- }
- public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion)
- {
- _renderer.HelperShader.DrawTexture(texture, sampler, srcRegion, dstRegion);
- }
- public void SetAlphaTest(bool enable, float reference, CompareOp op)
- {
- // This is currently handled using shader specialization, as Metal does not support alpha test.
- // In the future, we may want to use this to write the reference value into the support buffer,
- // to avoid creating one version of the shader per reference value used.
- }
- public void SetBlendState(AdvancedBlendDescriptor blend)
- {
- // Metal does not support advanced blend.
- }
- public void SetBlendState(int index, BlendDescriptor blend)
- {
- _encoderStateManager.UpdateBlendDescriptors(index, blend);
- }
- public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
- {
- if (enables == 0)
- {
- _encoderStateManager.UpdateDepthBias(0, 0, 0);
- }
- else
- {
- _encoderStateManager.UpdateDepthBias(units, factor, clamp);
- }
- }
- public void SetDepthClamp(bool clamp)
- {
- _encoderStateManager.UpdateDepthClamp(clamp);
- }
- public void SetDepthMode(DepthMode mode)
- {
- // Metal does not support depth clip control.
- }
- public void SetDepthTest(DepthTestDescriptor depthTest)
- {
- _encoderStateManager.UpdateDepthState(depthTest);
- }
- public void SetFaceCulling(bool enable, Face face)
- {
- _encoderStateManager.UpdateCullMode(enable, face);
- }
- public void SetFrontFace(FrontFace frontFace)
- {
- _encoderStateManager.UpdateFrontFace(frontFace);
- }
- public void SetIndexBuffer(BufferRange buffer, IndexType type)
- {
- _encoderStateManager.UpdateIndexBuffer(buffer, type);
- }
- public void SetImage(ShaderStage stage, int binding, ITexture image)
- {
- if (image is TextureBase img)
- {
- _encoderStateManager.UpdateImage(stage, binding, img);
- }
- }
- public void SetImageArray(ShaderStage stage, int binding, IImageArray array)
- {
- if (array is ImageArray imageArray)
- {
- _encoderStateManager.UpdateImageArray(stage, binding, imageArray);
- }
- }
- public void SetImageArraySeparate(ShaderStage stage, int setIndex, IImageArray array)
- {
- if (array is ImageArray imageArray)
- {
- _encoderStateManager.UpdateImageArraySeparate(stage, setIndex, imageArray);
- }
- }
- public void SetLineParameters(float width, bool smooth)
- {
- // Metal does not support wide-lines.
- }
- public void SetLogicOpState(bool enable, LogicalOp op)
- {
- _encoderStateManager.UpdateLogicOpState(enable, op);
- }
- public void SetMultisampleState(MultisampleDescriptor multisample)
- {
- _encoderStateManager.UpdateMultisampleState(multisample);
- }
- public void SetPatchParameters(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel)
- {
- Logger.Warning?.Print(LogClass.Gpu, "Not Implemented!");
- }
- public void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin)
- {
- Logger.Warning?.Print(LogClass.Gpu, "Not Implemented!");
- }
- public void SetPolygonMode(PolygonMode frontMode, PolygonMode backMode)
- {
- // Metal does not support polygon mode.
- }
- public void SetPrimitiveRestart(bool enable, int index)
- {
- // Always active for LineStrip and TriangleStrip
- // https://github.com/gpuweb/gpuweb/issues/1220#issuecomment-732483263
- // https://developer.apple.com/documentation/metal/mtlrendercommandencoder/1515520-drawindexedprimitives
- // https://stackoverflow.com/questions/70813665/how-to-render-multiple-trianglestrips-using-metal
- // Emulating disabling this is very difficult. It's unlikely for an index buffer to use the largest possible index,
- // so it's fine nearly all of the time.
- }
- public void SetPrimitiveTopology(PrimitiveTopology topology)
- {
- _encoderStateManager.UpdatePrimitiveTopology(topology);
- }
- public void SetProgram(IProgram program)
- {
- _encoderStateManager.UpdateProgram(program);
- }
- public void SetRasterizerDiscard(bool discard)
- {
- _encoderStateManager.UpdateRasterizerDiscard(discard);
- }
- public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMask)
- {
- _encoderStateManager.UpdateRenderTargetColorMasks(componentMask);
- }
- public void SetRenderTargets(ITexture[] colors, ITexture depthStencil)
- {
- _encoderStateManager.UpdateRenderTargets(colors, depthStencil);
- }
- public void SetScissors(ReadOnlySpan<Rectangle<int>> regions)
- {
- _encoderStateManager.UpdateScissors(regions);
- }
- public void SetStencilTest(StencilTestDescriptor stencilTest)
- {
- _encoderStateManager.UpdateStencilState(stencilTest);
- }
- public void SetUniformBuffers(ReadOnlySpan<BufferAssignment> buffers)
- {
- _encoderStateManager.UpdateUniformBuffers(buffers);
- }
- public void SetStorageBuffers(ReadOnlySpan<BufferAssignment> buffers)
- {
- _encoderStateManager.UpdateStorageBuffers(buffers);
- }
- internal void SetStorageBuffers(int first, ReadOnlySpan<Auto<DisposableBuffer>> buffers)
- {
- _encoderStateManager.UpdateStorageBuffers(first, buffers);
- }
- public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler)
- {
- if (texture is TextureBase tex)
- {
- if (sampler == null || sampler is SamplerHolder)
- {
- _encoderStateManager.UpdateTextureAndSampler(stage, binding, tex, (SamplerHolder)sampler);
- }
- }
- }
- public void SetTextureArray(ShaderStage stage, int binding, ITextureArray array)
- {
- if (array is TextureArray textureArray)
- {
- _encoderStateManager.UpdateTextureArray(stage, binding, textureArray);
- }
- }
- public void SetTextureArraySeparate(ShaderStage stage, int setIndex, ITextureArray array)
- {
- if (array is TextureArray textureArray)
- {
- _encoderStateManager.UpdateTextureArraySeparate(stage, setIndex, textureArray);
- }
- }
- public void SetUserClipDistance(int index, bool enableClip)
- {
- // TODO. Same as Vulkan
- }
- public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs)
- {
- _encoderStateManager.UpdateVertexAttribs(vertexAttribs);
- }
- public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
- {
- _encoderStateManager.UpdateVertexBuffers(vertexBuffers);
- }
- public void SetViewports(ReadOnlySpan<Viewport> viewports)
- {
- _encoderStateManager.UpdateViewports(viewports);
- }
- public void TextureBarrier()
- {
- if (CurrentEncoderType == EncoderType.Render)
- {
- Encoders.RenderEncoder.MemoryBarrier(MTLBarrierScope.Textures, MTLRenderStages.RenderStageFragment, MTLRenderStages.RenderStageFragment);
- }
- }
- public void TextureBarrierTiled()
- {
- TextureBarrier();
- }
- public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual)
- {
- // TODO: Implementable via indirect draw commands
- return false;
- }
- public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual)
- {
- // TODO: Implementable via indirect draw commands
- return false;
- }
- public void EndHostConditionalRendering()
- {
- // TODO: Implementable via indirect draw commands
- }
- public void BeginTransformFeedback(PrimitiveTopology topology)
- {
- // Metal does not support transform feedback.
- }
- public void EndTransformFeedback()
- {
- // Metal does not support transform feedback.
- }
- public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
- {
- // Metal does not support transform feedback.
- }
- public void Dispose()
- {
- EndCurrentPass();
- _encoderStateManager.Dispose();
- }
- }
- }
|