diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2022-08-11 18:23:25 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-08-11 18:23:25 -0300 |
| commit | ad47bd2d4ef72e4489f037056ead0a5d021694cc (patch) | |
| tree | 6548c08ee3be5e0f6784e0e408d3a7e903802251 /Ryujinx.Graphics.Gpu/Engine | |
| parent | a5ff0024fb33964c802e1712e5b11a52390603e7 (diff) | |
Fix blend with RGBX color formats (#3553)
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine')
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs | 107 | ||||
| -rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs | 33 |
2 files changed, 115 insertions, 25 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs index 10d5cd8c..bb43309b 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdater.cs @@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed private uint _prevFirstVertex; private bool _prevTfEnable; + private uint _prevRtNoAlphaMask; + /// <summary> /// Creates a new instance of the state updater. /// </summary> @@ -398,6 +400,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed int clipRegionHeight = int.MaxValue; bool changedScale = false; + uint rtNoAlphaMask = 0; for (int index = 0; index < Constants.TotalRenderTargets; index++) { @@ -412,6 +415,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed continue; } + if (colorState.Format.NoAlpha()) + { + rtNoAlphaMask |= 1u << index; + } + Image.Texture color = memoryManager.Physical.TextureCache.FindOrCreateTexture( memoryManager, colorState, @@ -485,6 +493,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed } _channel.TextureManager.SetClipRegion(clipRegionWidth, clipRegionHeight); + + if (useControl && _prevRtNoAlphaMask != rtNoAlphaMask) + { + _prevRtNoAlphaMask = rtNoAlphaMask; + + UpdateBlendState(); + } } /// <summary> @@ -1056,44 +1071,80 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed bool blendIndependent = _state.State.BlendIndependent; ColorF blendConstant = _state.State.BlendConstant; - for (int index = 0; index < Constants.TotalRenderTargets; index++) + if (blendIndependent) { - BlendDescriptor descriptor; - - if (blendIndependent) + for (int index = 0; index < Constants.TotalRenderTargets; index++) { bool enable = _state.State.BlendEnable[index]; var blend = _state.State.BlendState[index]; - descriptor = new BlendDescriptor( + var descriptor = new BlendDescriptor( enable, blendConstant, blend.ColorOp, - blend.ColorSrcFactor, - blend.ColorDstFactor, + FilterBlendFactor(blend.ColorSrcFactor, index), + FilterBlendFactor(blend.ColorDstFactor, index), blend.AlphaOp, - blend.AlphaSrcFactor, - blend.AlphaDstFactor); + FilterBlendFactor(blend.AlphaSrcFactor, index), + FilterBlendFactor(blend.AlphaDstFactor, index)); + + _pipeline.BlendDescriptors[index] = descriptor; + _context.Renderer.Pipeline.SetBlendState(index, descriptor); } - else + } + else + { + bool enable = _state.State.BlendEnable[0]; + var blend = _state.State.BlendStateCommon; + + var descriptor = new BlendDescriptor( + enable, + blendConstant, + blend.ColorOp, + FilterBlendFactor(blend.ColorSrcFactor, 0), + FilterBlendFactor(blend.ColorDstFactor, 0), + blend.AlphaOp, + FilterBlendFactor(blend.AlphaSrcFactor, 0), + FilterBlendFactor(blend.AlphaDstFactor, 0)); + + for (int index = 0; index < Constants.TotalRenderTargets; index++) { - bool enable = _state.State.BlendEnable[0]; - var blend = _state.State.BlendStateCommon; - - descriptor = new BlendDescriptor( - enable, - blendConstant, - blend.ColorOp, - blend.ColorSrcFactor, - blend.ColorDstFactor, - blend.AlphaOp, - blend.AlphaSrcFactor, - blend.AlphaDstFactor); + _pipeline.BlendDescriptors[index] = descriptor; + _context.Renderer.Pipeline.SetBlendState(index, descriptor); } + } + } + + /// <summary> + /// Gets a blend factor for the color target currently. + /// This will return <paramref name="factor"/> unless the target format has no alpha component, + /// in which case it will replace destination alpha factor with a constant factor of one or zero. + /// </summary> + /// <param name="factor">Input factor</param> + /// <param name="index">Color target index</param> + /// <returns>New blend factor</returns> + private BlendFactor FilterBlendFactor(BlendFactor factor, int index) + { + // If any color target format without alpha is being used, we need to make sure that + // if blend is active, it will not use destination alpha as a factor. + // That is required because RGBX formats are emulated using host RGBA formats. - _pipeline.BlendDescriptors[index] = descriptor; - _context.Renderer.Pipeline.SetBlendState(index, descriptor); + if (_state.State.RtColorState[index].Format.NoAlpha()) + { + switch (factor) + { + case BlendFactor.DstAlpha: + case BlendFactor.DstAlphaGl: + factor = BlendFactor.One; + break; + case BlendFactor.OneMinusDstAlpha: + case BlendFactor.OneMinusDstAlphaGl: + factor = BlendFactor.Zero; + break; + } } + + return factor; } /// <summary> @@ -1242,6 +1293,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed _channel.BufferManager.SetGraphicsUniformBufferBindings(stage, info.CBuffers); } + /// <summary> + /// Gets the current texture pool state. + /// </summary> + /// <returns>Texture pool state</returns> private GpuChannelPoolState GetPoolState() { return new GpuChannelPoolState( @@ -1286,6 +1341,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed ref attributeTypes); } + /// <summary> + /// Gets the depth mode that is currently being used (zero to one or minus one to one). + /// </summary> + /// <returns>Current depth mode</returns> private DepthMode GetDepthMode() { ref var transform = ref _state.State.ViewportTransform[0]; diff --git a/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs b/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs index e780ec23..889b5c8b 100644 --- a/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs +++ b/Ryujinx.Graphics.Gpu/Engine/Types/ColorFormat.cs @@ -124,11 +124,42 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types ColorFormat.R8Snorm => new FormatInfo(Format.R8Snorm, 1, 1, 1, 1), ColorFormat.R8Sint => new FormatInfo(Format.R8Sint, 1, 1, 1, 1), ColorFormat.R8Uint => new FormatInfo(Format.R8Uint, 1, 1, 1, 1), - ColorFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5X1Unorm, 1, 1, 2, 4), + ColorFormat.B5G5R5X1Unorm => new FormatInfo(Format.B5G5R5A1Unorm, 1, 1, 2, 4), ColorFormat.R8G8B8X8Unorm => new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4), ColorFormat.R8G8B8X8Srgb => new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4), _ => FormatInfo.Default }; } + + /// <summary> + /// Checks if a format has an alpha component. + /// </summary> + /// <param name="format">Format to be checked</param> + /// <returns>True if the format has no alpha component (RGBX), false if it does (RGBA)</returns> + public static bool NoAlpha(this ColorFormat format) + { + switch (format) + { + case ColorFormat.R32G32B32X32Float: + case ColorFormat.R32G32B32X32Sint: + case ColorFormat.R32G32B32X32Uint: + case ColorFormat.R16G16B16X16Unorm: + case ColorFormat.R16G16B16X16Snorm: + case ColorFormat.R16G16B16X16Sint: + case ColorFormat.R16G16B16X16Uint: + case ColorFormat.R16G16B16X16Float: + case ColorFormat.R8G8B8X8Snorm: + case ColorFormat.R8G8B8X8Sint: + case ColorFormat.R8G8B8X8Uint: + case ColorFormat.B8G8R8X8Unorm: + case ColorFormat.B8G8R8X8Srgb: + case ColorFormat.B5G5R5X1Unorm: + case ColorFormat.R8G8B8X8Unorm: + case ColorFormat.R8G8B8X8Srgb: + return true; + } + + return false; + } } }
\ No newline at end of file |
