diff --git a/Ryujinx.Graphics.GAL/Format.cs b/Ryujinx.Graphics.GAL/Format.cs
index db944844..f6abacaf 100644
--- a/Ryujinx.Graphics.GAL/Format.cs
+++ b/Ryujinx.Graphics.GAL/Format.cs
@@ -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;
}
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;
+
///
/// Creates a new instance of the state updater.
///
@@ -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();
+ }
}
///
@@ -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);
- }
- else
- {
- bool enable = _state.State.BlendEnable[0];
- var blend = _state.State.BlendStateCommon;
+ FilterBlendFactor(blend.AlphaSrcFactor, index),
+ FilterBlendFactor(blend.AlphaDstFactor, index));
- 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);
}
-
- _pipeline.BlendDescriptors[index] = descriptor;
- _context.Renderer.Pipeline.SetBlendState(index, descriptor);
}
+ 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++)
+ {
+ _pipeline.BlendDescriptors[index] = descriptor;
+ _context.Renderer.Pipeline.SetBlendState(index, descriptor);
+ }
+ }
+ }
+
+ ///
+ /// Gets a blend factor for the color target currently.
+ /// This will return 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.
+ ///
+ /// Input factor
+ /// Color target index
+ /// New blend factor
+ 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;
}
///
@@ -1242,6 +1293,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_channel.BufferManager.SetGraphicsUniformBufferBindings(stage, info.CBuffers);
}
+ ///
+ /// Gets the current texture pool state.
+ ///
+ /// Texture pool state
private GpuChannelPoolState GetPoolState()
{
return new GpuChannelPoolState(
@@ -1286,6 +1341,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
ref attributeTypes);
}
+ ///
+ /// Gets the depth mode that is currently being used (zero to one or minus one to one).
+ ///
+ /// Current depth mode
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
};
}
+
+ ///
+ /// Checks if a format has an alpha component.
+ ///
+ /// Format to be checked
+ /// True if the format has no alpha component (RGBX), false if it does (RGBA)
+ 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
diff --git a/Ryujinx.Graphics.OpenGL/FormatTable.cs b/Ryujinx.Graphics.OpenGL/FormatTable.cs
index e6717eb4..25043077 100644
--- a/Ryujinx.Graphics.OpenGL/FormatTable.cs
+++ b/Ryujinx.Graphics.OpenGL/FormatTable.cs
@@ -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);
diff --git a/Ryujinx.Graphics.Vulkan/FormatTable.cs b/Ryujinx.Graphics.Vulkan/FormatTable.cs
index 439d492c..446fea0a 100644
--- a/Ryujinx.Graphics.Vulkan/FormatTable.cs
+++ b/Ryujinx.Graphics.Vulkan/FormatTable.cs
@@ -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);
}