Add support for advanced blend (part 1/2) (#2801)
* Add blend microcode registers * Add advanced blend support using host extension * Remove debug message * Use pre-generated table for blend functions * XML docs * Rename AdvancedBlendMode to AdvancedBlendOp for consistency * Remove redundant code * Fix some advanced blend related issues on Vulkan * Formatting
This commit is contained in:
parent
6bf460e104
commit
7aa430f1a5
27 changed files with 5605 additions and 14 deletions
|
@ -0,0 +1,115 @@
|
|||
using Ryujinx.Common;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Engine.Threed.Blender
|
||||
{
|
||||
/// <summary>
|
||||
/// Advanced blend manager.
|
||||
/// </summary>
|
||||
class AdvancedBlendManager
|
||||
{
|
||||
private const int InstructionRamSize = 128;
|
||||
private const int InstructionRamSizeMask = InstructionRamSize - 1;
|
||||
|
||||
private readonly DeviceStateWithShadow<ThreedClassState> _state;
|
||||
|
||||
private readonly uint[] _code;
|
||||
private int _ip;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the advanced blend manager.
|
||||
/// </summary>
|
||||
/// <param name="state">GPU state of the channel owning this manager</param>
|
||||
public AdvancedBlendManager(DeviceStateWithShadow<ThreedClassState> state)
|
||||
{
|
||||
_state = state;
|
||||
_code = new uint[InstructionRamSize];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the start offset of the blend microcode in memory.
|
||||
/// </summary>
|
||||
/// <param name="argument">Method call argument</param>
|
||||
public void LoadBlendUcodeStart(int argument)
|
||||
{
|
||||
_ip = argument;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pushes one word of blend microcode.
|
||||
/// </summary>
|
||||
/// <param name="argument">Method call argument</param>
|
||||
public void LoadBlendUcodeInstruction(int argument)
|
||||
{
|
||||
_code[_ip++ & InstructionRamSizeMask] = (uint)argument;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to identify the current advanced blend function being used,
|
||||
/// given the current state and microcode that was uploaded.
|
||||
/// </summary>
|
||||
/// <param name="descriptor">Advanced blend descriptor</param>
|
||||
/// <returns>True if the function was found, false otherwise</returns>
|
||||
public bool TryGetAdvancedBlend(out AdvancedBlendDescriptor descriptor)
|
||||
{
|
||||
Span<uint> currentCode = new Span<uint>(_code);
|
||||
byte codeLength = (byte)_state.State.BlendUcodeSize;
|
||||
|
||||
if (currentCode.Length > codeLength)
|
||||
{
|
||||
currentCode = currentCode.Slice(0, codeLength);
|
||||
}
|
||||
|
||||
Hash128 hash = XXHash128.ComputeHash(MemoryMarshal.Cast<uint, byte>(currentCode));
|
||||
|
||||
descriptor = default;
|
||||
|
||||
if (!AdvancedBlendPreGenTable.Entries.TryGetValue(hash, out var entry))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.Constants != null)
|
||||
{
|
||||
bool constantsMatch = true;
|
||||
|
||||
for (int i = 0; i < entry.Constants.Length; i++)
|
||||
{
|
||||
RgbFloat constant = entry.Constants[i];
|
||||
RgbHalf constant2 = _state.State.BlendUcodeConstants[i];
|
||||
|
||||
if ((Half)constant.R != constant2.UnpackR() ||
|
||||
(Half)constant.G != constant2.UnpackG() ||
|
||||
(Half)constant.B != constant2.UnpackB())
|
||||
{
|
||||
constantsMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!constantsMatch)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.Alpha.Enable != _state.State.BlendUcodeEnable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.Alpha.Enable == BlendUcodeEnable.EnableRGBA &&
|
||||
(entry.Alpha.AlphaOp != _state.State.BlendStateCommon.AlphaOp ||
|
||||
entry.Alpha.AlphaSrcFactor != _state.State.BlendStateCommon.AlphaSrcFactor ||
|
||||
entry.Alpha.AlphaDstFactor != _state.State.BlendStateCommon.AlphaDstFactor))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
descriptor = new AdvancedBlendDescriptor(entry.Op, entry.Overlap, entry.SrcPreMultiplied);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue