diff options
Diffstat (limited to 'Ryujinx.Graphics.OpenGL/Pipeline.cs')
| -rw-r--r-- | Ryujinx.Graphics.OpenGL/Pipeline.cs | 1770 |
1 files changed, 0 insertions, 1770 deletions
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs deleted file mode 100644 index 6b6d0289..00000000 --- a/Ryujinx.Graphics.OpenGL/Pipeline.cs +++ /dev/null @@ -1,1770 +0,0 @@ -using OpenTK.Graphics.OpenGL; -using Ryujinx.Common.Logging; -using Ryujinx.Graphics.GAL; -using Ryujinx.Graphics.OpenGL.Image; -using Ryujinx.Graphics.OpenGL.Queries; -using Ryujinx.Graphics.Shader; -using System; -using System.Runtime.CompilerServices; - -namespace Ryujinx.Graphics.OpenGL -{ - class Pipeline : IPipeline, IDisposable - { - private const int SavedImages = 2; - - private readonly DrawTextureEmulation _drawTexture; - - internal ulong DrawCount { get; private set; } - - private Program _program; - - private bool _rasterizerDiscard; - - private VertexArray _vertexArray; - private Framebuffer _framebuffer; - - private IntPtr _indexBaseOffset; - - private DrawElementsType _elementsType; - - private PrimitiveType _primitiveType; - - private int _stencilFrontMask; - private bool _depthMask; - private bool _depthTestEnable; - private bool _stencilTestEnable; - private bool _cullEnable; - - private float[] _viewportArray = Array.Empty<float>(); - private double[] _depthRangeArray = Array.Empty<double>(); - - private int _boundDrawFramebuffer; - private int _boundReadFramebuffer; - - private CounterQueueEvent _activeConditionalRender; - - private Vector4<int>[] _fpIsBgra = new Vector4<int>[SupportBuffer.FragmentIsBgraCount]; - private Vector4<float>[] _renderScale = new Vector4<float>[73]; - private int _fragmentScaleCount; - - private (TextureBase, Format)[] _images; - private TextureBase _unit0Texture; - private Sampler _unit0Sampler; - - private FrontFaceDirection _frontFace; - private ClipOrigin _clipOrigin; - private ClipDepthMode _clipDepthMode; - - private uint _fragmentOutputMap; - private uint _componentMasks; - private uint _currentComponentMasks; - private bool _advancedBlendEnable; - - private uint _scissorEnables; - - private bool _tfEnabled; - private TransformFeedbackPrimitiveType _tfTopology; - - private SupportBufferUpdater _supportBuffer; - private readonly BufferHandle[] _tfbs; - private readonly BufferRange[] _tfbTargets; - - private ColorF _blendConstant; - - internal Pipeline() - { - _drawTexture = new DrawTextureEmulation(); - _rasterizerDiscard = false; - _clipOrigin = ClipOrigin.LowerLeft; - _clipDepthMode = ClipDepthMode.NegativeOneToOne; - - _fragmentOutputMap = uint.MaxValue; - _componentMasks = uint.MaxValue; - - _images = new (TextureBase, Format)[SavedImages]; - - var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f }; - new Span<Vector4<float>>(_renderScale).Fill(defaultScale); - - _tfbs = new BufferHandle[Constants.MaxTransformFeedbackBuffers]; - _tfbTargets = new BufferRange[Constants.MaxTransformFeedbackBuffers]; - } - - public void Initialize(OpenGLRenderer renderer) - { - _supportBuffer = new SupportBufferUpdater(renderer); - GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, Unsafe.As<BufferHandle, int>(ref _supportBuffer.Handle)); - - _supportBuffer.UpdateFragmentIsBgra(_fpIsBgra, 0, SupportBuffer.FragmentIsBgraCount); - _supportBuffer.UpdateRenderScale(_renderScale, 0, SupportBuffer.RenderScaleMaxCount); - } - - public void Barrier() - { - GL.MemoryBarrier(MemoryBarrierFlags.AllBarrierBits); - } - - public void BeginTransformFeedback(PrimitiveTopology topology) - { - GL.BeginTransformFeedback(_tfTopology = topology.ConvertToTfType()); - _tfEnabled = true; - } - - public void ClearBuffer(BufferHandle destination, int offset, int size, uint value) - { - Buffer.Clear(destination, offset, size, value); - } - - public void ClearRenderTargetColor(int index, int layer, int layerCount, uint componentMask, ColorF color) - { - EnsureFramebuffer(); - - GL.ColorMask( - index, - (componentMask & 1) != 0, - (componentMask & 2) != 0, - (componentMask & 4) != 0, - (componentMask & 8) != 0); - - float[] colors = new float[] { color.Red, color.Green, color.Blue, color.Alpha }; - - if (layer != 0 || layerCount != _framebuffer.GetColorLayerCount(index)) - { - for (int l = layer; l < layer + layerCount; l++) - { - _framebuffer.AttachColorLayerForClear(index, l); - - GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Color, index, colors); - } - - _framebuffer.DetachColorLayerForClear(index); - } - else - { - GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Color, index, colors); - } - - RestoreComponentMask(index); - } - - public void ClearRenderTargetDepthStencil(int layer, int layerCount, float depthValue, bool depthMask, int stencilValue, int stencilMask) - { - EnsureFramebuffer(); - - bool stencilMaskChanged = - stencilMask != 0 && - stencilMask != _stencilFrontMask; - - bool depthMaskChanged = depthMask && depthMask != _depthMask; - - if (stencilMaskChanged) - { - GL.StencilMaskSeparate(StencilFace.Front, stencilMask); - } - - if (depthMaskChanged) - { - GL.DepthMask(depthMask); - } - - if (layer != 0 || layerCount != _framebuffer.GetDepthStencilLayerCount()) - { - for (int l = layer; l < layer + layerCount; l++) - { - _framebuffer.AttachDepthStencilLayerForClear(l); - - ClearDepthStencil(depthValue, depthMask, stencilValue, stencilMask); - } - - _framebuffer.DetachDepthStencilLayerForClear(); - } - else - { - ClearDepthStencil(depthValue, depthMask, stencilValue, stencilMask); - } - - if (stencilMaskChanged) - { - GL.StencilMaskSeparate(StencilFace.Front, _stencilFrontMask); - } - - if (depthMaskChanged) - { - GL.DepthMask(_depthMask); - } - } - - private static void ClearDepthStencil(float depthValue, bool depthMask, int stencilValue, int stencilMask) - { - if (depthMask && stencilMask != 0) - { - GL.ClearBuffer(ClearBufferCombined.DepthStencil, 0, depthValue, stencilValue); - } - else if (depthMask) - { - GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Depth, 0, ref depthValue); - } - else if (stencilMask != 0) - { - GL.ClearBuffer(OpenTK.Graphics.OpenGL.ClearBuffer.Stencil, 0, ref stencilValue); - } - } - - public void CommandBufferBarrier() - { - GL.MemoryBarrier(MemoryBarrierFlags.CommandBarrierBit); - } - - public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) - { - Buffer.Copy(source, destination, srcOffset, dstOffset, size); - } - - public void DispatchCompute(int groupsX, int groupsY, int groupsZ) - { - if (!_program.IsLinked) - { - Logger.Debug?.Print(LogClass.Gpu, "Dispatch error, shader not linked."); - return; - } - - PrepareForDispatch(); - - GL.DispatchCompute(groupsX, groupsY, groupsZ); - } - - public void Draw(int vertexCount, int instanceCount, int firstVertex, int firstInstance) - { - if (!_program.IsLinked) - { - Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked."); - return; - } - - PreDraw(vertexCount); - - if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads) - { - DrawQuadsImpl(vertexCount, instanceCount, firstVertex, firstInstance); - } - else if (_primitiveType == PrimitiveType.QuadStrip && !HwCapabilities.SupportsQuads) - { - DrawQuadStripImpl(vertexCount, instanceCount, firstVertex, firstInstance); - } - else - { - DrawImpl(vertexCount, instanceCount, firstVertex, firstInstance); - } - - PostDraw(); - } - - private void DrawQuadsImpl( - int vertexCount, - int instanceCount, - int firstVertex, - int firstInstance) - { - // TODO: Instanced rendering. - int quadsCount = vertexCount / 4; - - int[] firsts = new int[quadsCount]; - int[] counts = new int[quadsCount]; - - for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) - { - firsts[quadIndex] = firstVertex + quadIndex * 4; - counts[quadIndex] = 4; - } - - GL.MultiDrawArrays( - PrimitiveType.TriangleFan, - firsts, - counts, - quadsCount); - } - - private void DrawQuadStripImpl( - int vertexCount, - int instanceCount, - int firstVertex, - int firstInstance) - { - int quadsCount = (vertexCount - 2) / 2; - - if (firstInstance != 0 || instanceCount != 1) - { - for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) - { - GL.DrawArraysInstancedBaseInstance(PrimitiveType.TriangleFan, firstVertex + quadIndex * 2, 4, instanceCount, firstInstance); - } - } - else - { - int[] firsts = new int[quadsCount]; - int[] counts = new int[quadsCount]; - - firsts[0] = firstVertex; - counts[0] = 4; - - for (int quadIndex = 1; quadIndex < quadsCount; quadIndex++) - { - firsts[quadIndex] = firstVertex + quadIndex * 2; - counts[quadIndex] = 4; - } - - GL.MultiDrawArrays( - PrimitiveType.TriangleFan, - firsts, - counts, - quadsCount); - } - } - - private void DrawImpl( - int vertexCount, - int instanceCount, - int firstVertex, - int firstInstance) - { - if (firstInstance == 0 && instanceCount == 1) - { - GL.DrawArrays(_primitiveType, firstVertex, vertexCount); - } - else if (firstInstance == 0) - { - GL.DrawArraysInstanced(_primitiveType, firstVertex, vertexCount, instanceCount); - } - else - { - GL.DrawArraysInstancedBaseInstance( - _primitiveType, - firstVertex, - vertexCount, - instanceCount, - firstInstance); - } - } - - public void DrawIndexed( - int indexCount, - int instanceCount, - int firstIndex, - int firstVertex, - int firstInstance) - { - if (!_program.IsLinked) - { - Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked."); - return; - } - - PreDrawVbUnbounded(); - - int indexElemSize = 1; - - switch (_elementsType) - { - case DrawElementsType.UnsignedShort: indexElemSize = 2; break; - case DrawElementsType.UnsignedInt: indexElemSize = 4; break; - } - - IntPtr indexBaseOffset = _indexBaseOffset + firstIndex * indexElemSize; - - if (_primitiveType == PrimitiveType.Quads && !HwCapabilities.SupportsQuads) - { - DrawQuadsIndexedImpl( - indexCount, - instanceCount, - indexBaseOffset, - indexElemSize, - firstVertex, - firstInstance); - } - else if (_primitiveType == PrimitiveType.QuadStrip && !HwCapabilities.SupportsQuads) - { - DrawQuadStripIndexedImpl( - indexCount, - instanceCount, - indexBaseOffset, - indexElemSize, - firstVertex, - firstInstance); - } - else - { - DrawIndexedImpl( - indexCount, - instanceCount, - indexBaseOffset, - firstVertex, - firstInstance); - } - - PostDraw(); - } - - private void DrawQuadsIndexedImpl( - int indexCount, - int instanceCount, - IntPtr indexBaseOffset, - int indexElemSize, - int firstVertex, - int firstInstance) - { - int quadsCount = indexCount / 4; - - if (firstInstance != 0 || instanceCount != 1) - { - if (firstVertex != 0 && firstInstance != 0) - { - for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) - { - GL.DrawElementsInstancedBaseVertexBaseInstance( - PrimitiveType.TriangleFan, - 4, - _elementsType, - indexBaseOffset + quadIndex * 4 * indexElemSize, - instanceCount, - firstVertex, - firstInstance); - } - } - else if (firstInstance != 0) - { - for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) - { - GL.DrawElementsInstancedBaseInstance( - PrimitiveType.TriangleFan, - 4, - _elementsType, - indexBaseOffset + quadIndex * 4 * indexElemSize, - instanceCount, - firstInstance); - } - } - else - { - for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) - { - GL.DrawElementsInstanced( - PrimitiveType.TriangleFan, - 4, - _elementsType, - indexBaseOffset + quadIndex * 4 * indexElemSize, - instanceCount); - } - } - } - else - { - IntPtr[] indices = new IntPtr[quadsCount]; - - int[] counts = new int[quadsCount]; - - int[] baseVertices = new int[quadsCount]; - - for (int quadIndex = 0; quadIndex < quadsCount; quadIndex++) - { - indices[quadIndex] = indexBaseOffset + quadIndex * 4 * indexElemSize; - - counts[quadIndex] = 4; - - baseVertices[quadIndex] = firstVertex; - } - - GL.MultiDrawElementsBaseVertex( - PrimitiveType.TriangleFan, - counts, - _elementsType, - indices, - quadsCount, - baseVertices); - } - } - - private void DrawQuadStripIndexedImpl( - int indexCount, - int instanceCount, - IntPtr indexBaseOffset, - int indexElemSize, - int firstVertex, - int firstInstance) - { - // TODO: Instanced rendering. - int quadsCount = (indexCount - 2) / 2; - - IntPtr[] indices = new IntPtr[quadsCount]; - - int[] counts = new int[quadsCount]; - - int[] baseVertices = new int[quadsCount]; - - indices[0] = indexBaseOffset; - - counts[0] = 4; - - baseVertices[0] = firstVertex; - - for (int quadIndex = 1; quadIndex < quadsCount; quadIndex++) - { - indices[quadIndex] = indexBaseOffset + quadIndex * 2 * indexElemSize; - - counts[quadIndex] = 4; - - baseVertices[quadIndex] = firstVertex; - } - - GL.MultiDrawElementsBaseVertex( - PrimitiveType.TriangleFan, - counts, - _elementsType, - indices, - quadsCount, - baseVertices); - } - - private void DrawIndexedImpl( - int indexCount, - int instanceCount, - IntPtr indexBaseOffset, - int firstVertex, - int firstInstance) - { - if (firstInstance == 0 && firstVertex == 0 && instanceCount == 1) - { - GL.DrawElements(_primitiveType, indexCount, _elementsType, indexBaseOffset); - } - else if (firstInstance == 0 && instanceCount == 1) - { - GL.DrawElementsBaseVertex( - _primitiveType, - indexCount, - _elementsType, - indexBaseOffset, - firstVertex); - } - else if (firstInstance == 0 && firstVertex == 0) - { - GL.DrawElementsInstanced( - _primitiveType, - indexCount, - _elementsType, - indexBaseOffset, - instanceCount); - } - else if (firstInstance == 0) - { - GL.DrawElementsInstancedBaseVertex( - _primitiveType, - indexCount, - _elementsType, - indexBaseOffset, - instanceCount, - firstVertex); - } - else if (firstVertex == 0) - { - GL.DrawElementsInstancedBaseInstance( - _primitiveType, - indexCount, - _elementsType, - indexBaseOffset, - instanceCount, - firstInstance); - } - else - { - GL.DrawElementsInstancedBaseVertexBaseInstance( - _primitiveType, - indexCount, - _elementsType, - indexBaseOffset, - instanceCount, - firstVertex, - firstInstance); - } - } - - public void DrawIndexedIndirect(BufferRange indirectBuffer) - { - if (!_program.IsLinked) - { - Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked."); - return; - } - - PreDrawVbUnbounded(); - - _vertexArray.SetRangeOfIndexBuffer(); - - GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32()); - - GL.DrawElementsIndirect(_primitiveType, _elementsType, (IntPtr)indirectBuffer.Offset); - - _vertexArray.RestoreIndexBuffer(); - - PostDraw(); - } - - public void DrawIndexedIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) - { - if (!_program.IsLinked) - { - Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked."); - return; - } - - PreDrawVbUnbounded(); - - _vertexArray.SetRangeOfIndexBuffer(); - - GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32()); - GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32()); - - GL.MultiDrawElementsIndirectCount( - _primitiveType, - (All)_elementsType, - (IntPtr)indirectBuffer.Offset, - (IntPtr)parameterBuffer.Offset, - maxDrawCount, - stride); - - _vertexArray.RestoreIndexBuffer(); - - PostDraw(); - } - - public void DrawIndirect(BufferRange indirectBuffer) - { - if (!_program.IsLinked) - { - Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked."); - return; - } - - PreDrawVbUnbounded(); - - GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32()); - - GL.DrawArraysIndirect(_primitiveType, (IntPtr)indirectBuffer.Offset); - - PostDraw(); - } - - public void DrawIndirectCount(BufferRange indirectBuffer, BufferRange parameterBuffer, int maxDrawCount, int stride) - { - if (!_program.IsLinked) - { - Logger.Debug?.Print(LogClass.Gpu, "Draw error, shader not linked."); - return; - } - - PreDrawVbUnbounded(); - - GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32()); - GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32()); - - GL.MultiDrawArraysIndirectCount( - _primitiveType, - (IntPtr)indirectBuffer.Offset, - (IntPtr)parameterBuffer.Offset, - maxDrawCount, - stride); - - PostDraw(); - } - - public void DrawTexture(ITexture texture, ISampler sampler, Extents2DF srcRegion, Extents2DF dstRegion) - { - if (texture is TextureView view && sampler is Sampler samp) - { - _supportBuffer.Commit(); - - if (HwCapabilities.SupportsDrawTexture) - { - GL.NV.DrawTexture( - view.Handle, - samp.Handle, - dstRegion.X1, - dstRegion.Y1, - dstRegion.X2, - dstRegion.Y2, - 0, - srcRegion.X1 / view.Width, - srcRegion.Y1 / view.Height, - srcRegion.X2 / view.Width, - srcRegion.Y2 / view.Height); - } - else - { - static void Disable(EnableCap cap, bool enabled) - { - if (enabled) - { - GL.Disable(cap); - } - } - - static void Enable(EnableCap cap, bool enabled) - { - if (enabled) - { - GL.Enable(cap); - } - } - - Disable(EnableCap.CullFace, _cullEnable); - Disable(EnableCap.StencilTest, _stencilTestEnable); - Disable(EnableCap.DepthTest, _depthTestEnable); - - if (_depthMask) - { - GL.DepthMask(false); - } - - if (_tfEnabled) - { - GL.EndTransformFeedback(); - } - - GL.ClipControl(ClipOrigin.UpperLeft, ClipDepthMode.NegativeOneToOne); - - _drawTexture.Draw( - view, - samp, - dstRegion.X1, - dstRegion.Y1, - dstRegion.X2, - dstRegion.Y2, - srcRegion.X1 / view.Width, - srcRegion.Y1 / view.Height, - srcRegion.X2 / view.Width, - srcRegion.Y2 / view.Height); - - _program?.Bind(); - _unit0Sampler?.Bind(0); - - RestoreViewport0(); - - Enable(EnableCap.CullFace, _cullEnable); - Enable(EnableCap.StencilTest, _stencilTestEnable); - Enable(EnableCap.DepthTest, _depthTestEnable); - - if (_depthMask) - { - GL.DepthMask(true); - } - - if (_tfEnabled) - { - GL.BeginTransformFeedback(_tfTopology); - } - - RestoreClipControl(); - } - } - } - - public void EndTransformFeedback() - { - GL.EndTransformFeedback(); - _tfEnabled = false; - } - - public double GetCounterDivisor(CounterType type) - { - if (type == CounterType.SamplesPassed) - { - return _renderScale[0].X * _renderScale[0].X; - } - - return 1; - } - - public void SetAlphaTest(bool enable, float reference, CompareOp op) - { - if (!enable) - { - GL.Disable(EnableCap.AlphaTest); - return; - } - - GL.AlphaFunc((AlphaFunction)op.Convert(), reference); - GL.Enable(EnableCap.AlphaTest); - } - - public void SetBlendState(AdvancedBlendDescriptor blend) - { - if (HwCapabilities.SupportsBlendEquationAdvanced) - { - GL.BlendEquation((BlendEquationMode)blend.Op.Convert()); - GL.NV.BlendParameter(NvBlendEquationAdvanced.BlendOverlapNv, (int)blend.Overlap.Convert()); - GL.NV.BlendParameter(NvBlendEquationAdvanced.BlendPremultipliedSrcNv, blend.SrcPreMultiplied ? 1 : 0); - GL.Enable(EnableCap.Blend); - _advancedBlendEnable = true; - } - } - - public void SetBlendState(int index, BlendDescriptor blend) - { - if (_advancedBlendEnable) - { - GL.Disable(EnableCap.Blend); - _advancedBlendEnable = false; - } - - if (!blend.Enable) - { - GL.Disable(IndexedEnableCap.Blend, index); - return; - } - - GL.BlendEquationSeparate( - index, - blend.ColorOp.Convert(), - blend.AlphaOp.Convert()); - - GL.BlendFuncSeparate( - index, - (BlendingFactorSrc)blend.ColorSrcFactor.Convert(), - (BlendingFactorDest)blend.ColorDstFactor.Convert(), - (BlendingFactorSrc)blend.AlphaSrcFactor.Convert(), - (BlendingFactorDest)blend.AlphaDstFactor.Convert()); - - EnsureFramebuffer(); - - _framebuffer.SetDualSourceBlend( - blend.ColorSrcFactor.IsDualSource() || - blend.ColorDstFactor.IsDualSource() || - blend.AlphaSrcFactor.IsDualSource() || - blend.AlphaDstFactor.IsDualSource()); - - if (_blendConstant != blend.BlendConstant) - { - _blendConstant = blend.BlendConstant; - - GL.BlendColor( - blend.BlendConstant.Red, - blend.BlendConstant.Green, - blend.BlendConstant.Blue, - blend.BlendConstant.Alpha); - } - - GL.Enable(IndexedEnableCap.Blend, index); - } - - public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp) - { - if ((enables & PolygonModeMask.Point) != 0) - { - GL.Enable(EnableCap.PolygonOffsetPoint); - } - else - { - GL.Disable(EnableCap.PolygonOffsetPoint); - } - - if ((enables & PolygonModeMask.Line) != 0) - { - GL.Enable(EnableCap.PolygonOffsetLine); - } - else - { - GL.Disable(EnableCap.PolygonOffsetLine); - } - - if ((enables & PolygonModeMask.Fill) != 0) - { - GL.Enable(EnableCap.PolygonOffsetFill); - } - else - { - GL.Disable(EnableCap.PolygonOffsetFill); - } - - if (enables == 0) - { - return; - } - - if (HwCapabilities.SupportsPolygonOffsetClamp) - { - GL.PolygonOffsetClamp(factor, units, clamp); - } - else - { - GL.PolygonOffset(factor, units); - } - } - - public void SetDepthClamp(bool clamp) - { - if (!clamp) - { - GL.Disable(EnableCap.DepthClamp); - return; - } - - GL.Enable(EnableCap.DepthClamp); - } - - public void SetDepthMode(DepthMode mode) - { - ClipDepthMode depthMode = mode.Convert(); - - if (_clipDepthMode != depthMode) - { - _clipDepthMode = depthMode; - - GL.ClipControl(_clipOrigin, depthMode); - } - } - - public void SetDepthTest(DepthTestDescriptor depthTest) - { - if (depthTest.TestEnable) - { - GL.Enable(EnableCap.DepthTest); - GL.DepthFunc((DepthFunction)depthTest.Func.Convert()); - } - else - { - GL.Disable(EnableCap.DepthTest); - } - - GL.DepthMask(depthTest.WriteEnable); - _depthMask = depthTest.WriteEnable; - _depthTestEnable = depthTest.TestEnable; - } - - public void SetFaceCulling(bool enable, Face face) - { - _cullEnable = enable; - - if (!enable) - { - GL.Disable(EnableCap.CullFace); - return; - } - - GL.CullFace(face.Convert()); - - GL.Enable(EnableCap.CullFace); - } - - public void SetFrontFace(FrontFace frontFace) - { - SetFrontFace(_frontFace = frontFace.Convert()); - } - - public void SetImage(int binding, ITexture texture, Format imageFormat) - { - if ((uint)binding < SavedImages) - { - _images[binding] = (texture as TextureBase, imageFormat); - } - - if (texture == null) - { - GL.BindImageTexture(binding, 0, 0, true, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); - return; - } - - TextureBase texBase = (TextureBase)texture; - - SizedInternalFormat format = FormatTable.GetImageFormat(imageFormat); - - if (format != 0) - { - GL.BindImageTexture(binding, texBase.Handle, 0, true, 0, TextureAccess.ReadWrite, format); - } - } - - public void SetIndexBuffer(BufferRange buffer, IndexType type) - { - _elementsType = type.Convert(); - - _indexBaseOffset = (IntPtr)buffer.Offset; - - EnsureVertexArray(); - - _vertexArray.SetIndexBuffer(buffer); - } - - public void SetLogicOpState(bool enable, LogicalOp op) - { - if (enable) - { - GL.Enable(EnableCap.ColorLogicOp); - - GL.LogicOp((LogicOp)op.Convert()); - } - else - { - GL.Disable(EnableCap.ColorLogicOp); - } - } - - public void SetMultisampleState(MultisampleDescriptor multisample) - { - if (multisample.AlphaToCoverageEnable) - { - GL.Enable(EnableCap.SampleAlphaToCoverage); - - if (multisample.AlphaToOneEnable) - { - GL.Enable(EnableCap.SampleAlphaToOne); - } - else - { - GL.Disable(EnableCap.SampleAlphaToOne); - } - - if (HwCapabilities.SupportsAlphaToCoverageDitherControl) - { - GL.NV.AlphaToCoverageDitherControl(multisample.AlphaToCoverageDitherEnable - ? NvAlphaToCoverageDitherControl.AlphaToCoverageDitherEnableNv - : NvAlphaToCoverageDitherControl.AlphaToCoverageDitherDisableNv); - } - } - else - { - GL.Disable(EnableCap.SampleAlphaToCoverage); - } - } - - public void SetLineParameters(float width, bool smooth) - { - if (smooth) - { - GL.Enable(EnableCap.LineSmooth); - } - else - { - GL.Disable(EnableCap.LineSmooth); - } - - GL.LineWidth(width); - } - - public unsafe void SetPatchParameters(int vertices, ReadOnlySpan<float> defaultOuterLevel, ReadOnlySpan<float> defaultInnerLevel) - { - GL.PatchParameter(PatchParameterInt.PatchVertices, vertices); - - fixed (float* pOuterLevel = defaultOuterLevel) - { - GL.PatchParameter(PatchParameterFloat.PatchDefaultOuterLevel, pOuterLevel); - } - - fixed (float* pInnerLevel = defaultInnerLevel) - { - GL.PatchParameter(PatchParameterFloat.PatchDefaultInnerLevel, pInnerLevel); - } - } - - public void SetPointParameters(float size, bool isProgramPointSize, bool enablePointSprite, Origin origin) - { - // GL_POINT_SPRITE was deprecated in core profile 3.2+ and causes GL_INVALID_ENUM when set. - // As we don't know if the current context is core or compat, it's safer to keep this code. - if (enablePointSprite) - { - GL.Enable(EnableCap.PointSprite); - } - else - { - GL.Disable(EnableCap.PointSprite); - } - - if (isProgramPointSize) - { - GL.Enable(EnableCap.ProgramPointSize); - } - else - { - GL.Disable(EnableCap.ProgramPointSize); - } - - GL.PointParameter(origin == Origin.LowerLeft - ? PointSpriteCoordOriginParameter.LowerLeft - : PointSpriteCoordOriginParameter.UpperLeft); - - // Games seem to set point size to 0 which generates a GL_INVALID_VALUE - // From the spec, GL_INVALID_VALUE is generated if size is less than or equal to 0. - GL.PointSize(Math.Max(float.Epsilon, size)); - } - - public void SetPolygonMode(GAL.PolygonMode frontMode, GAL.PolygonMode backMode) - { - if (frontMode == backMode) - { - GL.PolygonMode(MaterialFace.FrontAndBack, frontMode.Convert()); - } - else - { - GL.PolygonMode(MaterialFace.Front, frontMode.Convert()); - GL.PolygonMode(MaterialFace.Back, backMode.Convert()); - } - } - - public void SetPrimitiveRestart(bool enable, int index) - { - if (!enable) - { - GL.Disable(EnableCap.PrimitiveRestart); - return; - } - - GL.PrimitiveRestartIndex(index); - - GL.Enable(EnableCap.PrimitiveRestart); - } - - public void SetPrimitiveTopology(PrimitiveTopology topology) - { - _primitiveType = topology.Convert(); - } - - public void SetProgram(IProgram program) - { - Program prg = (Program)program; - - if (_tfEnabled) - { - GL.EndTransformFeedback(); - prg.Bind(); - GL.BeginTransformFeedback(_tfTopology); - } - else - { - prg.Bind(); - } - - if (prg.HasFragmentShader && _fragmentOutputMap != (uint)prg.FragmentOutputMap) - { - _fragmentOutputMap = (uint)prg.FragmentOutputMap; - - for (int index = 0; index < Constants.MaxRenderTargets; index++) - { - RestoreComponentMask(index, force: false); - } - } - - _program = prg; - } - - public void SetRasterizerDiscard(bool discard) - { - if (discard) - { - GL.Enable(EnableCap.RasterizerDiscard); - } - else - { - GL.Disable(EnableCap.RasterizerDiscard); - } - - _rasterizerDiscard = discard; - } - - public void SetRenderTargetScale(float scale) - { - _renderScale[0].X = scale; - _supportBuffer.UpdateRenderScale(_renderScale, 0, 1); // Just the first element. - } - - public void SetRenderTargetColorMasks(ReadOnlySpan<uint> componentMasks) - { - _componentMasks = 0; - - for (int index = 0; index < componentMasks.Length; index++) - { - _componentMasks |= componentMasks[index] << (index * 4); - - RestoreComponentMask(index, force: false); - } - } - - public void SetRenderTargets(ITexture[] colors, ITexture depthStencil) - { - EnsureFramebuffer(); - - bool isBgraChanged = false; - - for (int index = 0; index < colors.Length; index++) - { - TextureView color = (TextureView)colors[index]; - - _framebuffer.AttachColor(index, color); - - if (color != null) - { - int isBgra = color.Format.IsBgr() ? 1 : 0; - - if (_fpIsBgra[index].X != isBgra) - { - _fpIsBgra[index].X = isBgra; - isBgraChanged = true; - - RestoreComponentMask(index); - } - } - } - - if (isBgraChanged) - { - _supportBuffer.UpdateFragmentIsBgra(_fpIsBgra, 0, SupportBuffer.FragmentIsBgraCount); - } - - TextureView depthStencilView = (TextureView)depthStencil; - - _framebuffer.AttachDepthStencil(depthStencilView); - _framebuffer.SetDrawBuffers(colors.Length); - } - - public void SetScissors(ReadOnlySpan<Rectangle<int>> regions) - { - int count = Math.Min(regions.Length, Constants.MaxViewports); - - Span<int> v = stackalloc int[count * 4]; - - for (int index = 0; index < count; index++) - { - int vIndex = index * 4; - - var region = regions[index]; - - bool enabled = (region.X | region.Y) != 0 || region.Width != 0xffff || region.Height != 0xffff; - uint mask = 1u << index; - - if (enabled) - { - v[vIndex] = region.X; - v[vIndex + 1] = region.Y; - v[vIndex + 2] = region.Width; - v[vIndex + 3] = region.Height; - - if ((_scissorEnables & mask) == 0) - { - _scissorEnables |= mask; - GL.Enable(IndexedEnableCap.ScissorTest, index); - } - } - else - { - if ((_scissorEnables & mask) != 0) - { - _scissorEnables &= ~mask; - GL.Disable(IndexedEnableCap.ScissorTest, index); - } - } - } - - GL.ScissorArray(0, count, ref v[0]); - } - - public void SetStencilTest(StencilTestDescriptor stencilTest) - { - _stencilTestEnable = stencilTest.TestEnable; - - if (!stencilTest.TestEnable) - { - GL.Disable(EnableCap.StencilTest); - return; - } - - GL.StencilOpSeparate( - StencilFace.Front, - stencilTest.FrontSFail.Convert(), - stencilTest.FrontDpFail.Convert(), - stencilTest.FrontDpPass.Convert()); - - GL.StencilFuncSeparate( - StencilFace.Front, - (StencilFunction)stencilTest.FrontFunc.Convert(), - stencilTest.FrontFuncRef, - stencilTest.FrontFuncMask); - - GL.StencilMaskSeparate(StencilFace.Front, stencilTest.FrontMask); - - GL.StencilOpSeparate( - StencilFace.Back, - stencilTest.BackSFail.Convert(), - stencilTest.BackDpFail.Convert(), - stencilTest.BackDpPass.Convert()); - - GL.StencilFuncSeparate( - StencilFace.Back, - (StencilFunction)stencilTest.BackFunc.Convert(), - stencilTest.BackFuncRef, - stencilTest.BackFuncMask); - - GL.StencilMaskSeparate(StencilFace.Back, stencilTest.BackMask); - - GL.Enable(EnableCap.StencilTest); - - _stencilFrontMask = stencilTest.FrontMask; - } - - public void SetStorageBuffers(ReadOnlySpan<BufferAssignment> buffers) - { - SetBuffers(buffers, isStorage: true); - } - - public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler) - { - if (texture != null) - { - if (binding == 0) - { - _unit0Texture = (TextureBase)texture; - } - else - { - ((TextureBase)texture).Bind(binding); - } - } - else - { - TextureBase.ClearBinding(binding); - } - - Sampler glSampler = (Sampler)sampler; - - glSampler?.Bind(binding); - - if (binding == 0) - { - _unit0Sampler = glSampler; - } - } - - - public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers) - { - if (_tfEnabled) - { - GL.EndTransformFeedback(); - } - - int count = Math.Min(buffers.Length, Constants.MaxTransformFeedbackBuffers); - - for (int i = 0; i < count; i++) - { - BufferRange buffer = buffers[i]; - _tfbTargets[i] = buffer; - - if (buffer.Handle == BufferHandle.Null) - { - GL.BindBufferBase(BufferRangeTarget.TransformFeedbackBuffer, i, 0); - continue; - } - - if (_tfbs[i] == BufferHandle.Null) - { - _tfbs[i] = Buffer.Create(); - } - - Buffer.Resize(_tfbs[i], buffer.Size); - Buffer.Copy(buffer.Handle, _tfbs[i], buffer.Offset, 0, buffer.Size); - GL.BindBufferBase(BufferRangeTarget.TransformFeedbackBuffer, i, _tfbs[i].ToInt32()); - } - - if (_tfEnabled) - { - GL.BeginTransformFeedback(_tfTopology); - } - } - - public void SetUniformBuffers(ReadOnlySpan<BufferAssignment> buffers) - { - SetBuffers(buffers, isStorage: false); - } - - public void SetUserClipDistance(int index, bool enableClip) - { - if (!enableClip) - { - GL.Disable(EnableCap.ClipDistance0 + index); - return; - } - - GL.Enable(EnableCap.ClipDistance0 + index); - } - - public void SetVertexAttribs(ReadOnlySpan<VertexAttribDescriptor> vertexAttribs) - { - EnsureVertexArray(); - - _vertexArray.SetVertexAttributes(vertexAttribs); - } - - public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers) - { - EnsureVertexArray(); - - _vertexArray.SetVertexBuffers(vertexBuffers); - } - - public void SetViewports(ReadOnlySpan<Viewport> viewports, bool disableTransform) - { - Array.Resize(ref _viewportArray, viewports.Length * 4); - Array.Resize(ref _depthRangeArray, viewports.Length * 2); - - float[] viewportArray = _viewportArray; - double[] depthRangeArray = _depthRangeArray; - - for (int index = 0; index < viewports.Length; index++) - { - int viewportElemIndex = index * 4; - - Viewport viewport = viewports[index]; - - viewportArray[viewportElemIndex + 0] = viewport.Region.X; - viewportArray[viewportElemIndex + 1] = viewport.Region.Y + (viewport.Region.Height < 0 ? viewport.Region.Height : 0); - viewportArray[viewportElemIndex + 2] = viewport.Region.Width; - viewportArray[viewportElemIndex + 3] = MathF.Abs(viewport.Region.Height); - - if (HwCapabilities.SupportsViewportSwizzle) - { - GL.NV.ViewportSwizzle( - index, - viewport.SwizzleX.Convert(), - viewport.SwizzleY.Convert(), - viewport.SwizzleZ.Convert(), - viewport.SwizzleW.Convert()); - } - - depthRangeArray[index * 2 + 0] = viewport.DepthNear; - depthRangeArray[index * 2 + 1] = viewport.DepthFar; - } - - bool flipY = viewports.Length != 0 && viewports[0].Region.Height < 0; - - SetOrigin(flipY ? ClipOrigin.UpperLeft : ClipOrigin.LowerLeft); - - GL.ViewportArray(0, viewports.Length, viewportArray); - GL.DepthRangeArray(0, viewports.Length, depthRangeArray); - - float disableTransformF = disableTransform ? 1.0f : 0.0f; - if (_supportBuffer.Data.ViewportInverse.W != disableTransformF || disableTransform) - { - float scale = _renderScale[0].X; - _supportBuffer.UpdateViewportInverse(new Vector4<float> - { - X = scale * 2f / viewports[0].Region.Width, - Y = scale * 2f / viewports[0].Region.Height, - Z = 1, - W = disableTransformF - }); - } - } - - public void TextureBarrier() - { - GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit); - } - - public void TextureBarrierTiled() - { - GL.MemoryBarrier(MemoryBarrierFlags.TextureFetchBarrierBit); - } - - private void SetBuffers(ReadOnlySpan<BufferAssignment> buffers, bool isStorage) - { - BufferRangeTarget target = isStorage ? BufferRangeTarget.ShaderStorageBuffer : BufferRangeTarget.UniformBuffer; - - for (int index = 0; index < buffers.Length; index++) - { - BufferAssignment assignment = buffers[index]; - BufferRange buffer = assignment.Range; - - if (buffer.Handle == BufferHandle.Null) - { - GL.BindBufferRange(target, assignment.Binding, 0, IntPtr.Zero, 0); - continue; - } - - GL.BindBufferRange(target, assignment.Binding, buffer.Handle.ToInt32(), (IntPtr)buffer.Offset, buffer.Size); - } - } - - private void SetOrigin(ClipOrigin origin) - { - if (_clipOrigin != origin) - { - _clipOrigin = origin; - - GL.ClipControl(origin, _clipDepthMode); - - SetFrontFace(_frontFace); - } - } - - private void SetFrontFace(FrontFaceDirection frontFace) - { - // Changing clip origin will also change the front face to compensate - // for the flipped viewport, we flip it again here to compensate as - // this effect is undesirable for us. - if (_clipOrigin == ClipOrigin.UpperLeft) - { - frontFace = frontFace == FrontFaceDirection.Ccw ? FrontFaceDirection.Cw : FrontFaceDirection.Ccw; - } - - GL.FrontFace(frontFace); - } - - private void EnsureVertexArray() - { - if (_vertexArray == null) - { - _vertexArray = new VertexArray(); - - _vertexArray.Bind(); - } - } - - private void EnsureFramebuffer() - { - if (_framebuffer == null) - { - _framebuffer = new Framebuffer(); - - int boundHandle = _framebuffer.Bind(); - _boundDrawFramebuffer = _boundReadFramebuffer = boundHandle; - - GL.Enable(EnableCap.FramebufferSrgb); - } - } - - internal (int drawHandle, int readHandle) GetBoundFramebuffers() - { - if (BackgroundContextWorker.InBackground) - { - return (0, 0); - } - - return (_boundDrawFramebuffer, _boundReadFramebuffer); - } - - public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount) - { - bool changed = false; - - for (int index = 0; index < totalCount; index++) - { - if (_renderScale[1 + index].X != scales[index]) - { - _renderScale[1 + index].X = scales[index]; - changed = true; - } - } - - // Only update fragment count if there are scales after it for the vertex stage. - if (fragmentCount != totalCount && fragmentCount != _fragmentScaleCount) - { - _fragmentScaleCount = fragmentCount; - _supportBuffer.UpdateFragmentRenderScaleCount(_fragmentScaleCount); - } - - if (changed) - { - _supportBuffer.UpdateRenderScale(_renderScale, 0, 1 + totalCount); - } - } - - private void PrepareForDispatch() - { - _unit0Texture?.Bind(0); - _supportBuffer.Commit(); - } - - private void PreDraw(int vertexCount) - { - _vertexArray.PreDraw(vertexCount); - PreDraw(); - } - - private void PreDrawVbUnbounded() - { - _vertexArray.PreDrawVbUnbounded(); - PreDraw(); - } - - private void PreDraw() - { - DrawCount++; - - _unit0Texture?.Bind(0); - _supportBuffer.Commit(); - } - - private void PostDraw() - { - if (_tfEnabled) - { - for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++) - { - if (_tfbTargets[i].Handle != BufferHandle.Null) - { - Buffer.Copy(_tfbs[i], _tfbTargets[i].Handle, 0, _tfbTargets[i].Offset, _tfbTargets[i].Size); - } - } - } - } - - public void RestoreComponentMask(int index, bool force = true) - { - // If the bound render target is bgra, swap the red and blue masks. - uint redMask = _fpIsBgra[index].X == 0 ? 1u : 4u; - uint blueMask = _fpIsBgra[index].X == 0 ? 4u : 1u; - - int shift = index * 4; - uint componentMask = _componentMasks & _fragmentOutputMap; - uint checkMask = 0xfu << shift; - uint componentMaskAtIndex = componentMask & checkMask; - - if (!force && componentMaskAtIndex == (_currentComponentMasks & checkMask)) - { - return; - } - - componentMask >>= shift; - componentMask &= 0xfu; - - GL.ColorMask( - index, - (componentMask & redMask) != 0, - (componentMask & 2u) != 0, - (componentMask & blueMask) != 0, - (componentMask & 8u) != 0); - - _currentComponentMasks &= ~checkMask; - _currentComponentMasks |= componentMaskAtIndex; - } - - public void RestoreClipControl() - { - GL.ClipControl(_clipOrigin, _clipDepthMode); - } - - public void RestoreScissor0Enable() - { - if ((_scissorEnables & 1u) != 0) - { - GL.Enable(IndexedEnableCap.ScissorTest, 0); - } - } - - public void RestoreRasterizerDiscard() - { - if (_rasterizerDiscard) - { - GL.Enable(EnableCap.RasterizerDiscard); - } - } - - public void RestoreViewport0() - { - if (_viewportArray.Length > 0) - { - GL.ViewportArray(0, 1, _viewportArray); - } - } - - public void RestoreProgram() - { - _program?.Bind(); - } - - public void RestoreImages1And2() - { - for (int i = 0; i < SavedImages; i++) - { - (TextureBase texBase, Format imageFormat) = _images[i]; - - if (texBase != null) - { - SizedInternalFormat format = FormatTable.GetImageFormat(imageFormat); - - if (format != 0) - { - GL.BindImageTexture(i, texBase.Handle, 0, true, 0, TextureAccess.ReadWrite, format); - continue; - } - } - - GL.BindImageTexture(i, 0, 0, true, 0, TextureAccess.ReadWrite, SizedInternalFormat.Rgba8); - } - } - - public bool TryHostConditionalRendering(ICounterEvent value, ulong compare, bool isEqual) - { - if (value is CounterQueueEvent) - { - // Compare an event and a constant value. - CounterQueueEvent evt = (CounterQueueEvent)value; - - // Easy host conditional rendering when the check matches what GL can do: - // - Event is of type samples passed. - // - Result is not a combination of multiple queries. - // - Comparing against 0. - // - Event has not already been flushed. - - if (compare == 0 && evt.Type == QueryTarget.SamplesPassed && evt.ClearCounter) - { - if (!value.ReserveForHostAccess()) - { - // If the event has been flushed, then just use the values on the CPU. - // The query object may already be repurposed for another draw (eg. begin + end). - return false; - } - - GL.BeginConditionalRender(evt.Query, isEqual ? ConditionalRenderType.QueryNoWaitInverted : ConditionalRenderType.QueryNoWait); - _activeConditionalRender = evt; - - return true; - } - } - - // The GPU will flush the queries to CPU and evaluate the condition there instead. - - GL.Flush(); // The thread will be stalled manually flushing the counter, so flush GL commands now. - return false; - } - - public bool TryHostConditionalRendering(ICounterEvent value, ICounterEvent compare, bool isEqual) - { - GL.Flush(); // The GPU thread will be stalled manually flushing the counter, so flush GL commands now. - return false; // We don't currently have a way to compare two counters for conditional rendering. - } - - public void EndHostConditionalRendering() - { - GL.EndConditionalRender(); - - _activeConditionalRender?.ReleaseHostAccess(); - _activeConditionalRender = null; - } - - public void Dispose() - { - _supportBuffer?.Dispose(); - - for (int i = 0; i < Constants.MaxTransformFeedbackBuffers; i++) - { - if (_tfbs[i] != BufferHandle.Null) - { - Buffer.Delete(_tfbs[i]); - _tfbs[i] = BufferHandle.Null; - } - } - - _activeConditionalRender?.ReleaseHostAccess(); - _framebuffer?.Dispose(); - _vertexArray?.Dispose(); - _drawTexture.Dispose(); - } - } -} |
