Fix blend with RGBX color formats (#3553)
This commit is contained in:
parent
a5ff0024fb
commit
ad47bd2d4e
5 changed files with 117 additions and 85 deletions
|
@ -56,7 +56,6 @@ namespace Ryujinx.Graphics.GAL
|
|||
D32Float,
|
||||
D24UnormS8Uint,
|
||||
D32FloatS8Uint,
|
||||
R8G8B8X8Srgb,
|
||||
R8G8B8A8Srgb,
|
||||
R4G4Unorm,
|
||||
R4G4B4A4Unorm,
|
||||
|
@ -113,18 +112,6 @@ namespace Ryujinx.Graphics.GAL
|
|||
R10G10B10A2Sint,
|
||||
R10G10B10A2Uscaled,
|
||||
R10G10B10A2Sscaled,
|
||||
R8G8B8X8Unorm,
|
||||
R8G8B8X8Snorm,
|
||||
R8G8B8X8Uint,
|
||||
R8G8B8X8Sint,
|
||||
R16G16B16X16Float,
|
||||
R16G16B16X16Unorm,
|
||||
R16G16B16X16Snorm,
|
||||
R16G16B16X16Uint,
|
||||
R16G16B16X16Sint,
|
||||
R32G32B32X32Float,
|
||||
R32G32B32X32Uint,
|
||||
R32G32B32X32Sint,
|
||||
Astc4x4Unorm,
|
||||
Astc5x4Unorm,
|
||||
Astc5x5Unorm,
|
||||
|
@ -154,12 +141,9 @@ namespace Ryujinx.Graphics.GAL
|
|||
Astc12x10Srgb,
|
||||
Astc12x12Srgb,
|
||||
B5G6R5Unorm,
|
||||
B5G5R5X1Unorm,
|
||||
B5G5R5A1Unorm,
|
||||
A1B5G5R5Unorm,
|
||||
B8G8R8X8Unorm,
|
||||
B8G8R8A8Unorm,
|
||||
B8G8R8X8Srgb,
|
||||
B8G8R8A8Srgb
|
||||
}
|
||||
|
||||
|
@ -272,7 +256,6 @@ namespace Ryujinx.Graphics.GAL
|
|||
case Format.R8Snorm:
|
||||
case Format.R8Sint:
|
||||
case Format.R8Uint:
|
||||
case Format.B5G5R5X1Unorm:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -357,11 +340,8 @@ namespace Ryujinx.Graphics.GAL
|
|||
switch (format)
|
||||
{
|
||||
case Format.B5G6R5Unorm:
|
||||
case Format.B5G5R5X1Unorm:
|
||||
case Format.B5G5R5A1Unorm:
|
||||
case Format.B8G8R8X8Unorm:
|
||||
case Format.B8G8R8A8Unorm:
|
||||
case Format.B8G8R8X8Srgb:
|
||||
case Format.B8G8R8A8Srgb:
|
||||
return true;
|
||||
}
|
||||
|
@ -412,9 +392,6 @@ namespace Ryujinx.Graphics.GAL
|
|||
case Format.R16G16B16A16Uint:
|
||||
case Format.R32G32B32A32Uint:
|
||||
case Format.R10G10B10A2Uint:
|
||||
case Format.R8G8B8X8Uint:
|
||||
case Format.R16G16B16X16Uint:
|
||||
case Format.R32G32B32X32Uint:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -443,9 +420,6 @@ namespace Ryujinx.Graphics.GAL
|
|||
case Format.R16G16B16A16Sint:
|
||||
case Format.R32G32B32A32Sint:
|
||||
case Format.R10G10B10A2Sint:
|
||||
case Format.R8G8B8X8Sint:
|
||||
case Format.R16G16B16X16Sint:
|
||||
case Format.R32G32B32X32Sint:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,45 +1071,81 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
bool blendIndependent = _state.State.BlendIndependent;
|
||||
ColorF blendConstant = _state.State.BlendConstant;
|
||||
|
||||
for (int index = 0; index < Constants.TotalRenderTargets; index++)
|
||||
{
|
||||
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
|
||||
{
|
||||
bool enable = _state.State.BlendEnable[0];
|
||||
var blend = _state.State.BlendStateCommon;
|
||||
|
||||
descriptor = new BlendDescriptor(
|
||||
var descriptor = new BlendDescriptor(
|
||||
enable,
|
||||
blendConstant,
|
||||
blend.ColorOp,
|
||||
blend.ColorSrcFactor,
|
||||
blend.ColorDstFactor,
|
||||
FilterBlendFactor(blend.ColorSrcFactor, 0),
|
||||
FilterBlendFactor(blend.ColorDstFactor, 0),
|
||||
blend.AlphaOp,
|
||||
blend.AlphaSrcFactor,
|
||||
blend.AlphaDstFactor);
|
||||
}
|
||||
FilterBlendFactor(blend.AlphaSrcFactor, 0),
|
||||
FilterBlendFactor(blend.AlphaDstFactor, 0));
|
||||
|
||||
for (int index = 0; index < Constants.TotalRenderTargets; index++)
|
||||
{
|
||||
_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.
|
||||
|
||||
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>
|
||||
/// Updates host logical operation state, based on guest state.
|
||||
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,7 +70,6 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
Add(Format.D32Float, new FormatInfo(1, false, false, All.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float));
|
||||
Add(Format.D24UnormS8Uint, new FormatInfo(1, false, false, All.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248));
|
||||
Add(Format.D32FloatS8Uint, new FormatInfo(1, false, false, All.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev));
|
||||
Add(Format.R8G8B8X8Srgb, new FormatInfo(4, false, false, All.Srgb8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||
Add(Format.R8G8B8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||
Add(Format.R4G4B4A4Unorm, new FormatInfo(4, true, false, All.Rgba4, PixelFormat.Rgba, PixelType.UnsignedShort4444Reversed));
|
||||
Add(Format.R5G5B5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Rgb, PixelType.UnsignedShort1555Reversed));
|
||||
|
@ -124,18 +123,6 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
Add(Format.R10G10B10A2Sint, new FormatInfo(4, false, false, All.Rgb10A2, PixelFormat.RgbaInteger, (PixelType)All.Int2101010Rev));
|
||||
Add(Format.R10G10B10A2Uscaled, new FormatInfo(4, false, true, All.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
|
||||
Add(Format.R10G10B10A2Sscaled, new FormatInfo(4, false, true, All.Rgb10A2, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed));
|
||||
Add(Format.R8G8B8X8Unorm, new FormatInfo(4, true, false, All.Rgb8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||
Add(Format.R8G8B8X8Snorm, new FormatInfo(4, true, false, All.Rgb8Snorm, PixelFormat.Rgba, PixelType.Byte));
|
||||
Add(Format.R8G8B8X8Uint, new FormatInfo(4, false, false, All.Rgb8ui, PixelFormat.RgbaInteger, PixelType.UnsignedByte));
|
||||
Add(Format.R8G8B8X8Sint, new FormatInfo(4, false, false, All.Rgb8i, PixelFormat.RgbaInteger, PixelType.Byte));
|
||||
Add(Format.R16G16B16X16Float, new FormatInfo(4, false, false, All.Rgb16f, PixelFormat.Rgba, PixelType.HalfFloat));
|
||||
Add(Format.R16G16B16X16Unorm, new FormatInfo(4, true, false, All.Rgb16, PixelFormat.Rgba, PixelType.UnsignedShort));
|
||||
Add(Format.R16G16B16X16Snorm, new FormatInfo(4, true, false, All.Rgb16Snorm, PixelFormat.Rgba, PixelType.Short));
|
||||
Add(Format.R16G16B16X16Uint, new FormatInfo(4, false, false, All.Rgb16ui, PixelFormat.RgbaInteger, PixelType.UnsignedShort));
|
||||
Add(Format.R16G16B16X16Sint, new FormatInfo(4, false, false, All.Rgb16i, PixelFormat.RgbaInteger, PixelType.Short));
|
||||
Add(Format.R32G32B32X32Float, new FormatInfo(4, false, false, All.Rgb32f, PixelFormat.Rgba, PixelType.Float));
|
||||
Add(Format.R32G32B32X32Uint, new FormatInfo(4, false, false, All.Rgb32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt));
|
||||
Add(Format.R32G32B32X32Sint, new FormatInfo(4, false, false, All.Rgb32i, PixelFormat.RgbaInteger, PixelType.Int));
|
||||
Add(Format.Astc4x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc4X4Khr));
|
||||
Add(Format.Astc5x4Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X4Khr));
|
||||
Add(Format.Astc5x5Unorm, new FormatInfo(4, true, false, All.CompressedRgbaAstc5X5Khr));
|
||||
|
@ -165,12 +152,9 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
Add(Format.Astc12x10Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X10Khr));
|
||||
Add(Format.Astc12x12Srgb, new FormatInfo(4, false, false, All.CompressedSrgb8Alpha8Astc12X12Khr));
|
||||
Add(Format.B5G6R5Unorm, new FormatInfo(3, true, false, All.Rgb565, PixelFormat.Rgb, PixelType.UnsignedShort565Reversed));
|
||||
Add(Format.B5G5R5X1Unorm, new FormatInfo(4, true, false, All.Rgb5, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed));
|
||||
Add(Format.B5G5R5A1Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed));
|
||||
Add(Format.A1B5G5R5Unorm, new FormatInfo(4, true, false, All.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551));
|
||||
Add(Format.B8G8R8X8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||
Add(Format.B8G8R8A8Unorm, new FormatInfo(4, true, false, All.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||
Add(Format.B8G8R8X8Srgb, new FormatInfo(4, false, false, All.Srgb8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||
Add(Format.B8G8R8A8Srgb, new FormatInfo(4, false, false, All.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte));
|
||||
|
||||
Add(Format.R8Unorm, SizedInternalFormat.R8);
|
||||
|
|
|
@ -66,7 +66,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
Add(Format.D32Float, VkFormat.D32Sfloat);
|
||||
Add(Format.D24UnormS8Uint, VkFormat.D24UnormS8Uint);
|
||||
Add(Format.D32FloatS8Uint, VkFormat.D32SfloatS8Uint);
|
||||
Add(Format.R8G8B8X8Srgb, VkFormat.R8G8B8Srgb);
|
||||
Add(Format.R8G8B8A8Srgb, VkFormat.R8G8B8A8Srgb);
|
||||
Add(Format.R4G4Unorm, VkFormat.R4G4UnormPack8);
|
||||
Add(Format.R4G4B4A4Unorm, VkFormat.R4G4B4A4UnormPack16);
|
||||
|
@ -119,18 +118,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
Add(Format.R10G10B10A2Sint, VkFormat.A2B10G10R10SintPack32);
|
||||
Add(Format.R10G10B10A2Uscaled, VkFormat.A2B10G10R10UscaledPack32);
|
||||
Add(Format.R10G10B10A2Sscaled, VkFormat.A2B10G10R10SscaledPack32);
|
||||
Add(Format.R8G8B8X8Unorm, VkFormat.R8G8B8Unorm);
|
||||
Add(Format.R8G8B8X8Snorm, VkFormat.R8G8B8SNorm);
|
||||
Add(Format.R8G8B8X8Uint, VkFormat.R8G8B8Uint);
|
||||
Add(Format.R8G8B8X8Sint, VkFormat.R8G8B8Sint);
|
||||
Add(Format.R16G16B16X16Float, VkFormat.R16G16B16Sfloat);
|
||||
Add(Format.R16G16B16X16Unorm, VkFormat.R16G16B16Unorm);
|
||||
Add(Format.R16G16B16X16Snorm, VkFormat.R16G16B16SNorm);
|
||||
Add(Format.R16G16B16X16Uint, VkFormat.R16G16B16Uint);
|
||||
Add(Format.R16G16B16X16Sint, VkFormat.R16G16B16Sint);
|
||||
Add(Format.R32G32B32X32Float, VkFormat.R32G32B32Sfloat);
|
||||
Add(Format.R32G32B32X32Uint, VkFormat.R32G32B32Uint);
|
||||
Add(Format.R32G32B32X32Sint, VkFormat.R32G32B32Sint);
|
||||
Add(Format.Astc4x4Unorm, VkFormat.Astc4x4UnormBlock);
|
||||
Add(Format.Astc5x4Unorm, VkFormat.Astc5x4UnormBlock);
|
||||
Add(Format.Astc5x5Unorm, VkFormat.Astc5x5UnormBlock);
|
||||
|
@ -160,12 +147,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
Add(Format.Astc12x10Srgb, VkFormat.Astc12x10SrgbBlock);
|
||||
Add(Format.Astc12x12Srgb, VkFormat.Astc12x12SrgbBlock);
|
||||
Add(Format.B5G6R5Unorm, VkFormat.R5G6B5UnormPack16);
|
||||
Add(Format.B5G5R5X1Unorm, VkFormat.A1R5G5B5UnormPack16);
|
||||
Add(Format.B5G5R5A1Unorm, VkFormat.A1R5G5B5UnormPack16);
|
||||
Add(Format.A1B5G5R5Unorm, VkFormat.R5G5B5A1UnormPack16);
|
||||
Add(Format.B8G8R8X8Unorm, VkFormat.B8G8R8Unorm);
|
||||
Add(Format.B8G8R8A8Unorm, VkFormat.B8G8R8A8Unorm);
|
||||
Add(Format.B8G8R8X8Srgb, VkFormat.B8G8R8Srgb);
|
||||
Add(Format.B8G8R8A8Srgb, VkFormat.B8G8R8A8Srgb);
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue