aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Engine/Methods.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/Methods.cs')
-rw-r--r--Ryujinx.Graphics.Gpu/Engine/Methods.cs82
1 files changed, 60 insertions, 22 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index 18fd7e70..5388c86d 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -86,7 +86,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateShaderState(state);
}
- UpdateRenderTargetStateIfNeeded(state);
+ if (state.QueryModified(MethodOffset.RtColorState,
+ MethodOffset.RtDepthStencilState,
+ MethodOffset.RtControl,
+ MethodOffset.RtDepthStencilSize,
+ MethodOffset.RtDepthStencilEnable))
+ {
+ UpdateRenderTargetState(state, useControl: true);
+ }
if (state.QueryModified(MethodOffset.DepthTestEnable,
MethodOffset.DepthWriteEnable,
@@ -155,7 +162,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateFaceState(state);
}
- if (state.QueryModified(MethodOffset.RtColorMask))
+ if (state.QueryModified(MethodOffset.RtColorMaskShared, MethodOffset.RtColorMask))
{
UpdateRtColorMask(state);
}
@@ -210,19 +217,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
}
}
- private void UpdateRenderTargetStateIfNeeded(GpuState state)
+ private void UpdateRenderTargetState(GpuState state, bool useControl)
{
- if (state.QueryModified(MethodOffset.RtColorState,
- MethodOffset.RtDepthStencilState,
- MethodOffset.RtDepthStencilSize,
- MethodOffset.RtDepthStencilEnable))
- {
- UpdateRenderTargetState(state);
- }
- }
+ var rtControl = state.Get<RtControl>(MethodOffset.RtControl);
+
+ int count = useControl ? rtControl.UnpackCount() : Constants.TotalRenderTargets;
- private void UpdateRenderTargetState(GpuState state)
- {
var msaaMode = state.Get<TextureMsaaMode>(MethodOffset.RtMsaaMode);
int samplesInX = msaaMode.SamplesInX();
@@ -230,9 +230,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
- var colorState = state.Get<RtColorState>(MethodOffset.RtColorState, index);
+ int rtIndex = useControl ? rtControl.UnpackPermutationIndex(index) : index;
- if (!IsRtEnabled(colorState))
+ var colorState = state.Get<RtColorState>(MethodOffset.RtColorState, rtIndex);
+
+ if (index >= count || !IsRtEnabled(colorState))
{
_textureManager.SetRenderTargetColor(index, null);
@@ -292,6 +294,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
private void UpdateViewportTransform(GpuState state)
{
+ bool transformEnable = GetViewportTransformEnable(state);
+
bool flipY = (state.Get<int>(MethodOffset.YControl) & 1) != 0;
float yFlip = flipY ? -1 : 1;
@@ -303,13 +307,35 @@ namespace Ryujinx.Graphics.Gpu.Engine
var transform = state.Get<ViewportTransform>(MethodOffset.ViewportTransform, index);
var extents = state.Get<ViewportExtents> (MethodOffset.ViewportExtents, index);
- float x = transform.TranslateX - MathF.Abs(transform.ScaleX);
- float y = transform.TranslateY - MathF.Abs(transform.ScaleY);
+ RectangleF region;
- float width = transform.ScaleX * 2;
- float height = transform.ScaleY * 2 * yFlip;
+ if (transformEnable)
+ {
+ float x = transform.TranslateX - MathF.Abs(transform.ScaleX);
+ float y = transform.TranslateY - MathF.Abs(transform.ScaleY);
- RectangleF region = new RectangleF(x, y, width, height);
+ float width = transform.ScaleX * 2;
+ float height = transform.ScaleY * 2 * yFlip;
+
+ region = new RectangleF(x, y, width, height);
+ }
+ else
+ {
+ // It's not possible to fully disable viewport transform, at least with the most
+ // common graphics APIs, but we can effectively disable it with a dummy transform.
+ // The transform is defined as: xw = (width / 2) * xndc + x + (width / 2)
+ // By setting x to -(width / 2), we effectively remove the translation.
+ // By setting the width to 2, we remove the scale since 2 / 2 = 1.
+ // Now, the only problem is the viewport clipping, that we also can't disable.
+ // To prevent the values from being clipped, we multiply (-1, -1, 2, 2) by
+ // the maximum supported viewport dimensions.
+ // This must be compensated on the shader, by dividing the vertex position
+ // by the maximum viewport dimensions.
+ float maxSize = (float)_context.Capabilities.MaximumViewportDimensions;
+ float halfMaxSize = (float)_context.Capabilities.MaximumViewportDimensions * 0.5f;
+
+ region = new RectangleF(-halfMaxSize, -halfMaxSize, maxSize, maxSize * yFlip);
+ }
viewports[index] = new Viewport(
region,
@@ -537,11 +563,13 @@ namespace Ryujinx.Graphics.Gpu.Engine
private void UpdateRtColorMask(GpuState state)
{
+ bool rtColorMaskShared = state.Get<Boolean32>(MethodOffset.RtColorMaskShared);
+
uint[] componentMasks = new uint[Constants.TotalRenderTargets];
for (int index = 0; index < Constants.TotalRenderTargets; index++)
{
- var colorMask = state.Get<RtColorMask>(MethodOffset.RtColorMask, index);
+ var colorMask = state.Get<RtColorMask>(MethodOffset.RtColorMask, rtColorMaskShared ? 0 : index);
uint componentMask = 0;
@@ -634,7 +662,9 @@ namespace Ryujinx.Graphics.Gpu.Engine
addressesArray[index] = baseAddress + shader.Offset;
}
- GraphicsShader gs = _shaderCache.GetGraphicsShader(addresses);
+ bool viewportTransformEnable = GetViewportTransformEnable(state);
+
+ GraphicsShader gs = _shaderCache.GetGraphicsShader(addresses, !viewportTransformEnable);
_vsUsesInstanceId = gs.Shader[0].Program.Info.UsesInstanceId;
@@ -695,6 +725,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
_context.Renderer.Pipeline.BindProgram(gs.HostProgram);
}
+ private bool GetViewportTransformEnable(GpuState state)
+ {
+ // FIXME: We should read ViewportTransformEnable, but it seems that some games writes 0 there?
+ // return state.Get<Boolean32>(MethodOffset.ViewportTransformEnable) != 0;
+
+ return true;
+ }
+
private static Target GetTarget(SamplerType type)
{
type &= ~(SamplerType.Indexed | SamplerType.Shadow);