diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs | 287 |
1 files changed, 177 insertions, 110 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 2f5d4fc5..ccbccca1 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -1,4 +1,5 @@ using Ryujinx.Common.Logging; +using Ryujinx.Common.Memory; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Engine.Types; using Ryujinx.Graphics.Gpu.Image; @@ -15,11 +16,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// </summary> class StateUpdater { - public const int ShaderStateIndex = 0; - public const int RasterizerStateIndex = 1; - public const int ScissorStateIndex = 2; - public const int VertexBufferStateIndex = 3; - public const int PrimitiveRestartStateIndex = 4; + public const int ShaderStateIndex = 16; + public const int RasterizerStateIndex = 15; + public const int ScissorStateIndex = 18; + public const int VertexBufferStateIndex = 0; + public const int PrimitiveRestartStateIndex = 12; private readonly GpuContext _context; private readonly GpuChannel _channel; @@ -31,6 +32,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed private readonly ShaderProgramInfo[] _currentProgramInfo; private ShaderSpecializationState _shaderSpecState; + private ProgramPipelineState _pipeline; + private bool _vtgWritesRtLayer; private byte _vsClipDistancesWritten; @@ -54,7 +57,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed _drawState = drawState; _currentProgramInfo = new ShaderProgramInfo[Constants.ShaderStages]; - // ShaderState must be the first, as other state updates depends on information from the currently bound shader. + // ShaderState must be updated after other state updates, as pipeline state is sent to the backend when compiling new shaders. + // Render target state must appear after shader state as it depends on information from the currently bound shader. // Rasterizer and scissor states are checked by render target clear, their indexes // must be updated on the constants "RasterizerStateIndex" and "ScissorStateIndex" if modified. // The vertex buffer state may be forced dirty when a indexed draw starts, the "VertexBufferStateIndex" @@ -62,53 +66,39 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed // The order of the other state updates doesn't matter. _updateTracker = new StateUpdateTracker<ThreedClassState>(new[] { - new StateUpdateCallbackEntry(UpdateShaderState, - nameof(ThreedClassState.ShaderBaseAddress), - nameof(ThreedClassState.ShaderState)), - - new StateUpdateCallbackEntry(UpdateRasterizerState, nameof(ThreedClassState.RasterizeEnable)), - - new StateUpdateCallbackEntry(UpdateScissorState, - nameof(ThreedClassState.ScissorState), - nameof(ThreedClassState.ScreenScissorState)), - new StateUpdateCallbackEntry(UpdateVertexBufferState, nameof(ThreedClassState.VertexBufferDrawState), nameof(ThreedClassState.VertexBufferInstanced), nameof(ThreedClassState.VertexBufferState), nameof(ThreedClassState.VertexBufferEndAddress)), - new StateUpdateCallbackEntry(UpdatePrimitiveRestartState, - nameof(ThreedClassState.PrimitiveRestartDrawArrays), - nameof(ThreedClassState.PrimitiveRestartState)), - - new StateUpdateCallbackEntry(UpdateTessellationState, - nameof(ThreedClassState.TessOuterLevel), - nameof(ThreedClassState.TessInnerLevel), - nameof(ThreedClassState.PatchVertices)), - - new StateUpdateCallbackEntry(UpdateTfBufferState, nameof(ThreedClassState.TfBufferState)), - new StateUpdateCallbackEntry(UpdateUserClipState, nameof(ThreedClassState.ClipDistanceEnable)), + new StateUpdateCallbackEntry(UpdateVertexAttribState, nameof(ThreedClassState.VertexAttribState)), - new StateUpdateCallbackEntry(UpdateRenderTargetState, - nameof(ThreedClassState.RtColorState), - nameof(ThreedClassState.RtDepthStencilState), - nameof(ThreedClassState.RtControl), - nameof(ThreedClassState.RtDepthStencilSize), - nameof(ThreedClassState.RtDepthStencilEnable)), + new StateUpdateCallbackEntry(UpdateBlendState, + nameof(ThreedClassState.BlendIndependent), + nameof(ThreedClassState.BlendConstant), + nameof(ThreedClassState.BlendStateCommon), + nameof(ThreedClassState.BlendEnableCommon), + nameof(ThreedClassState.BlendEnable), + nameof(ThreedClassState.BlendState)), - new StateUpdateCallbackEntry(UpdateDepthClampState, nameof(ThreedClassState.ViewVolumeClipControl)), + new StateUpdateCallbackEntry(UpdateFaceState, nameof(ThreedClassState.FaceState)), - new StateUpdateCallbackEntry(UpdateAlphaTestState, - nameof(ThreedClassState.AlphaTestEnable), - nameof(ThreedClassState.AlphaTestRef), - nameof(ThreedClassState.AlphaTestFunc)), + new StateUpdateCallbackEntry(UpdateStencilTestState, + nameof(ThreedClassState.StencilBackMasks), + nameof(ThreedClassState.StencilTestState), + nameof(ThreedClassState.StencilBackTestState)), new StateUpdateCallbackEntry(UpdateDepthTestState, nameof(ThreedClassState.DepthTestEnable), nameof(ThreedClassState.DepthWriteEnable), nameof(ThreedClassState.DepthTestFunc)), + new StateUpdateCallbackEntry(UpdateTessellationState, + nameof(ThreedClassState.TessOuterLevel), + nameof(ThreedClassState.TessInnerLevel), + nameof(ThreedClassState.PatchVertices)), + new StateUpdateCallbackEntry(UpdateViewportTransform, nameof(ThreedClassState.DepthMode), nameof(ThreedClassState.ViewportTransform), @@ -116,6 +106,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed nameof(ThreedClassState.YControl), nameof(ThreedClassState.ViewportTransformEnable)), + new StateUpdateCallbackEntry(UpdateLogicOpState, nameof(ThreedClassState.LogicOpState)), + + new StateUpdateCallbackEntry(UpdateDepthClampState, nameof(ThreedClassState.ViewVolumeClipControl)), + new StateUpdateCallbackEntry(UpdatePolygonMode, nameof(ThreedClassState.PolygonModeFront), nameof(ThreedClassState.PolygonModeBack)), @@ -126,21 +120,46 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed nameof(ThreedClassState.DepthBiasUnits), nameof(ThreedClassState.DepthBiasClamp)), - new StateUpdateCallbackEntry(UpdateStencilTestState, - nameof(ThreedClassState.StencilBackMasks), - nameof(ThreedClassState.StencilTestState), - nameof(ThreedClassState.StencilBackTestState)), + new StateUpdateCallbackEntry(UpdatePrimitiveRestartState, nameof(ThreedClassState.PrimitiveRestartState)), + + new StateUpdateCallbackEntry(UpdateLineState, + nameof(ThreedClassState.LineWidthSmooth), + nameof(ThreedClassState.LineSmoothEnable)), + + new StateUpdateCallbackEntry(UpdateRtColorMask, + nameof(ThreedClassState.RtColorMaskShared), + nameof(ThreedClassState.RtColorMask)), + + new StateUpdateCallbackEntry(UpdateRasterizerState, nameof(ThreedClassState.RasterizeEnable)), + + new StateUpdateCallbackEntry(UpdateShaderState, + nameof(ThreedClassState.ShaderBaseAddress), + nameof(ThreedClassState.ShaderState)), + + new StateUpdateCallbackEntry(UpdateRenderTargetState, + nameof(ThreedClassState.RtColorState), + nameof(ThreedClassState.RtDepthStencilState), + nameof(ThreedClassState.RtControl), + nameof(ThreedClassState.RtDepthStencilSize), + nameof(ThreedClassState.RtDepthStencilEnable)), + + new StateUpdateCallbackEntry(UpdateScissorState, + nameof(ThreedClassState.ScissorState), + nameof(ThreedClassState.ScreenScissorState)), + + new StateUpdateCallbackEntry(UpdateTfBufferState, nameof(ThreedClassState.TfBufferState)), + new StateUpdateCallbackEntry(UpdateUserClipState, nameof(ThreedClassState.ClipDistanceEnable)), + + new StateUpdateCallbackEntry(UpdateAlphaTestState, + nameof(ThreedClassState.AlphaTestEnable), + nameof(ThreedClassState.AlphaTestRef), + nameof(ThreedClassState.AlphaTestFunc)), new StateUpdateCallbackEntry(UpdateSamplerPoolState, nameof(ThreedClassState.SamplerPoolState), nameof(ThreedClassState.SamplerIndex)), new StateUpdateCallbackEntry(UpdateTexturePoolState, nameof(ThreedClassState.TexturePoolState)), - new StateUpdateCallbackEntry(UpdateVertexAttribState, nameof(ThreedClassState.VertexAttribState)), - - new StateUpdateCallbackEntry(UpdateLineState, - nameof(ThreedClassState.LineWidthSmooth), - nameof(ThreedClassState.LineSmoothEnable)), new StateUpdateCallbackEntry(UpdatePointState, nameof(ThreedClassState.PointSize), @@ -152,22 +171,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed nameof(ThreedClassState.IndexBufferState), nameof(ThreedClassState.IndexBufferCount)), - new StateUpdateCallbackEntry(UpdateFaceState, nameof(ThreedClassState.FaceState)), - - new StateUpdateCallbackEntry(UpdateRtColorMask, - nameof(ThreedClassState.RtColorMaskShared), - nameof(ThreedClassState.RtColorMask)), - - new StateUpdateCallbackEntry(UpdateBlendState, - nameof(ThreedClassState.BlendIndependent), - nameof(ThreedClassState.BlendConstant), - nameof(ThreedClassState.BlendStateCommon), - nameof(ThreedClassState.BlendEnableCommon), - nameof(ThreedClassState.BlendEnable), - nameof(ThreedClassState.BlendState)), - - new StateUpdateCallbackEntry(UpdateLogicOpState, nameof(ThreedClassState.LogicOpState)), - new StateUpdateCallbackEntry(UpdateMultisampleState, nameof(ThreedClassState.AlphaToCoverageDitherEnable), nameof(ThreedClassState.MultisampleControl)) @@ -324,6 +327,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// </summary> private void UpdateTessellationState() { + _pipeline.PatchControlPoints = (uint)_state.State.PatchVertices; + _context.Renderer.Pipeline.SetPatchParameters( _state.State.PatchVertices, _state.State.TessOuterLevel.ToSpan(), @@ -356,6 +361,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed private void UpdateRasterizerState() { bool enable = _state.State.RasterizeEnable; + _pipeline.RasterizerDiscard = !enable; _context.Renderer.Pipeline.SetRasterizerDiscard(!enable); } @@ -497,11 +503,21 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// </summary> public void UpdateScissorState() { + const int MinX = 0; + const int MinY = 0; + const int MaxW = 0xffff; + const int MaxH = 0xffff; + + Span<Rectangle<int>> regions = stackalloc Rectangle<int>[Constants.TotalViewports]; + for (int index = 0; index < Constants.TotalViewports; index++) { ScissorState scissor = _state.State.ScissorState[index]; - bool enable = scissor.Enable && (scissor.X1 != 0 || scissor.Y1 != 0 || scissor.X2 != 0xffff || scissor.Y2 != 0xffff); + bool enable = scissor.Enable && (scissor.X1 != MinX || + scissor.Y1 != MinY || + scissor.X2 != MaxW || + scissor.Y2 != MaxH); if (enable) { @@ -531,13 +547,15 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed height = (int)MathF.Ceiling(height * scale); } - _context.Renderer.Pipeline.SetScissor(index, true, x, y, width, height); + regions[index] = new Rectangle<int>(x, y, width, height); } else { - _context.Renderer.Pipeline.SetScissor(index, false, 0, 0, 0, 0); + regions[index] = new Rectangle<int>(MinX, MinY, MaxW, MaxH); } } + + _context.Renderer.Pipeline.SetScissors(regions); } /// <summary> @@ -547,7 +565,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed private void UpdateDepthClampState() { ViewVolumeClipControl clip = _state.State.ViewVolumeClipControl; - _context.Renderer.Pipeline.SetDepthClamp((clip & ViewVolumeClipControl.DepthClampDisabled) == 0); + bool clamp = (clip & ViewVolumeClipControl.DepthClampDisabled) == 0; + + _pipeline.DepthClampEnable = clamp; + _context.Renderer.Pipeline.SetDepthClamp(clamp); } /// <summary> @@ -566,10 +587,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// </summary> private void UpdateDepthTestState() { - _context.Renderer.Pipeline.SetDepthTest(new DepthTestDescriptor( + DepthTestDescriptor descriptor = new DepthTestDescriptor( _state.State.DepthTestEnable, _state.State.DepthWriteEnable, - _state.State.DepthTestFunc)); + _state.State.DepthTestFunc); + + _pipeline.DepthTest = descriptor; + _context.Renderer.Pipeline.SetDepthTest(descriptor); } /// <summary> @@ -596,7 +620,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed ref var scissor = ref _state.State.ScreenScissorState; float rScale = _channel.TextureManager.RenderTargetScale; - var scissorRect = new RectangleF(0, 0, (scissor.X + scissor.Width) * rScale, (scissor.Y + scissor.Height) * rScale); + var scissorRect = new Rectangle<float>(0, 0, (scissor.X + scissor.Width) * rScale, (scissor.Y + scissor.Height) * rScale); viewports[index] = new Viewport(scissorRect, ViewportSwizzle.PositiveX, ViewportSwizzle.PositiveY, ViewportSwizzle.PositiveZ, ViewportSwizzle.PositiveW, 0, 1); continue; @@ -633,7 +657,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed height *= scale; } - RectangleF region = new RectangleF(x, y, width, height); + Rectangle<float> region = new Rectangle<float>(x, y, width, height); ViewportSwizzle swizzleX = transform.UnpackSwizzleX(); ViewportSwizzle swizzleY = transform.UnpackSwizzleY(); @@ -653,7 +677,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed viewports[index] = new Viewport(region, swizzleX, swizzleY, swizzleZ, swizzleW, depthNear, depthFar); } - _context.Renderer.Pipeline.SetViewports(0, viewports, disableTransform); + _context.Renderer.Pipeline.SetDepthMode(GetDepthMode()); + _context.Renderer.Pipeline.SetViewports(viewports, disableTransform); } /// <summary> @@ -661,37 +686,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// </summary> private void UpdateDepthMode() { - ref var transform = ref _state.State.ViewportTransform[0]; - ref var extents = ref _state.State.ViewportExtents[0]; - - DepthMode depthMode; - - if (!float.IsInfinity(extents.DepthNear) && - !float.IsInfinity(extents.DepthFar) && - (extents.DepthFar - extents.DepthNear) != 0) - { - // Try to guess the depth mode being used on the high level API - // based on current transform. - // It is setup like so by said APIs: - // If depth mode is ZeroToOne: - // TranslateZ = Near - // ScaleZ = Far - Near - // If depth mode is MinusOneToOne: - // TranslateZ = (Near + Far) / 2 - // ScaleZ = (Far - Near) / 2 - // DepthNear/Far are sorted such as that Near is always less than Far. - depthMode = extents.DepthNear != transform.TranslateZ && - extents.DepthFar != transform.TranslateZ - ? DepthMode.MinusOneToOne - : DepthMode.ZeroToOne; - } - else - { - // If we can't guess from the viewport transform, then just use the depth mode register. - depthMode = (DepthMode)(_state.State.DepthMode & 1); - } - - _context.Renderer.Pipeline.SetDepthMode(depthMode); + _context.Renderer.Pipeline.SetDepthMode(GetDepthMode()); } /// <summary> @@ -719,6 +714,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed enables |= (depthBias.LineEnable ? PolygonModeMask.Line : 0); enables |= (depthBias.FillEnable ? PolygonModeMask.Fill : 0); + _pipeline.BiasEnable = enables; _context.Renderer.Pipeline.SetDepthBias(enables, factor, units / 2f, clamp); } @@ -760,7 +756,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed backMask = test.FrontMask; } - _context.Renderer.Pipeline.SetStencilTest(new StencilTestDescriptor( + StencilTestDescriptor descriptor = new StencilTestDescriptor( test.Enable, test.FrontFunc, test.FrontSFail, @@ -775,7 +771,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed backDpFail, backFuncRef, backFuncMask, - backMask)); + backMask); + + _pipeline.StencilTest = descriptor; + _context.Renderer.Pipeline.SetStencilTest(descriptor); } /// <summary> @@ -844,6 +843,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed format); } + _pipeline.SetVertexAttribs(vertexAttribs); _context.Renderer.Pipeline.SetVertexAttribs(vertexAttribs); } @@ -855,6 +855,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed float width = _state.State.LineWidthSmooth; bool smooth = _state.State.LineSmoothEnable; + _pipeline.LineWidth = width; _context.Renderer.Pipeline.SetLineParameters(width, smooth); } @@ -881,6 +882,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed PrimitiveRestartState primitiveRestart = _state.State.PrimitiveRestartState; bool enable = primitiveRestart.Enable && (_drawState.DrawIndexed || _state.State.PrimitiveRestartDrawArrays); + _pipeline.PrimitiveRestartEnable = enable; _context.Renderer.Pipeline.SetPrimitiveRestart(enable, primitiveRestart.Index); } @@ -927,6 +929,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed if (!vertexBuffer.UnpackEnable()) { + _pipeline.VertexBuffers[index] = new BufferPipelineDescriptor(false, 0, 0); _channel.BufferManager.SetVertexBuffer(index, 0, 0, 0, 0); continue; @@ -944,6 +947,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed _drawState.IsAnyVbInstanced |= divisor != 0; + ulong vbSize = endAddress.Pack() - address + 1; ulong size; if (_drawState.IbStreamer.HasInlineIndexData || _drawState.DrawIndexed || stride == 0 || instanced) @@ -951,7 +955,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed // This size may be (much) larger than the real vertex buffer size. // Avoid calculating it this way, unless we don't have any other option. - size = endAddress.Pack() - address + 1; + size = vbSize; if (stride > 0 && indexTypeSmall && _drawState.DrawIndexed && !instanced) { @@ -975,9 +979,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed var drawState = _state.State.VertexBufferDrawState; - size = (ulong)((firstInstance + drawState.First + drawState.Count) * stride); + size = Math.Min(vbSize, (ulong)((firstInstance + drawState.First + drawState.Count) * stride)); } + _pipeline.VertexBuffers[index] = new BufferPipelineDescriptor(_channel.MemoryManager.IsMapped(address), stride, divisor); _channel.BufferManager.SetVertexBuffer(index, address, size, stride, divisor); } } @@ -990,6 +995,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed var yControl = _state.State.YControl; var face = _state.State.FaceState; + _pipeline.CullEnable = face.CullEnable; + _pipeline.CullMode = face.CullFace; _context.Renderer.Pipeline.SetFaceCulling(face.CullEnable, face.CullFace); UpdateFrontFace(yControl, face.FrontFace); @@ -1009,6 +1016,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed frontFace = frontFace == FrontFace.CounterClockwise ? FrontFace.Clockwise : FrontFace.CounterClockwise; } + _pipeline.FrontFace = frontFace; _context.Renderer.Pipeline.SetFrontFace(frontFace); } @@ -1034,6 +1042,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed componentMask |= (colorMask.UnpackAlpha() ? 8u : 0u); componentMasks[index] = componentMask; + _pipeline.ColorWriteMask[index] = componentMask; } _context.Renderer.Pipeline.SetRenderTargetColorMasks(componentMasks); @@ -1082,6 +1091,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed blend.AlphaDstFactor); } + _pipeline.BlendDescriptors[index] = descriptor; _context.Renderer.Pipeline.SetBlendState(index, descriptor); } } @@ -1093,6 +1103,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed { LogicalOpState logicOpState = _state.State.LogicOpState; + _pipeline.SetLogicOpState(logicOpState.Enable, logicOpState.LogicalOp); _context.Renderer.Pipeline.SetLogicOpState(logicOpState.Enable, logicOpState.LogicalOp); } @@ -1138,7 +1149,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed GpuChannelPoolState poolState = GetPoolState(); GpuChannelGraphicsState graphicsState = GetGraphicsState(); - CachedShaderProgram gs = shaderCache.GetGraphicsShader(ref _state.State, _channel, poolState, graphicsState, addresses); + CachedShaderProgram gs = shaderCache.GetGraphicsShader(ref _state.State, ref _pipeline, _channel, poolState, graphicsState, addresses); _shaderSpecState = gs.SpecializationState; @@ -1245,13 +1256,69 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed /// <returns>Current GPU channel state</returns> private GpuChannelGraphicsState GetGraphicsState() { + ref var vertexAttribState = ref _state.State.VertexAttribState; + + Array32<AttributeType> attributeTypes = new Array32<AttributeType>(); + + for (int location = 0; location < attributeTypes.Length; location++) + { + attributeTypes[location] = vertexAttribState[location].UnpackType() switch + { + 3 => AttributeType.Sint, + 4 => AttributeType.Uint, + _ => AttributeType.Float + }; + } + return new GpuChannelGraphicsState( _state.State.EarlyZForce, _drawState.Topology, _state.State.TessMode, - _state.State.ViewportTransformEnable == 0, (_state.State.MultisampleControl & 1) != 0, - _state.State.AlphaToCoverageDitherEnable); + _state.State.AlphaToCoverageDitherEnable, + _state.State.ViewportTransformEnable == 0, + GetDepthMode() == DepthMode.MinusOneToOne, + _state.State.VertexProgramPointSize, + _state.State.PointSize, + _state.State.AlphaTestEnable, + _state.State.AlphaTestFunc, + _state.State.AlphaTestRef, + ref attributeTypes); + } + + private DepthMode GetDepthMode() + { + ref var transform = ref _state.State.ViewportTransform[0]; + ref var extents = ref _state.State.ViewportExtents[0]; + + DepthMode depthMode; + + if (!float.IsInfinity(extents.DepthNear) && + !float.IsInfinity(extents.DepthFar) && + (extents.DepthFar - extents.DepthNear) != 0) + { + // Try to guess the depth mode being used on the high level API + // based on current transform. + // It is setup like so by said APIs: + // If depth mode is ZeroToOne: + // TranslateZ = Near + // ScaleZ = Far - Near + // If depth mode is MinusOneToOne: + // TranslateZ = (Near + Far) / 2 + // ScaleZ = (Far - Near) / 2 + // DepthNear/Far are sorted such as that Near is always less than Far. + depthMode = extents.DepthNear != transform.TranslateZ && + extents.DepthFar != transform.TranslateZ + ? DepthMode.MinusOneToOne + : DepthMode.ZeroToOne; + } + else + { + // If we can't guess from the viewport transform, then just use the depth mode register. + depthMode = (DepthMode)(_state.State.DepthMode & 1); + } + + return depthMode; } /// <summary> |