Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f61b7818c3 | ||
|
a2a97e1b11 | ||
|
8b2625b0be | ||
|
651e24fed9 | ||
|
41b104d0fb |
@@ -31,9 +31,18 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
public bool IsEffectEnabled { get; }
|
public bool IsEffectEnabled { get; }
|
||||||
|
|
||||||
public AuxiliaryBufferCommand(uint bufferOffset, byte inputBufferOffset, byte outputBufferOffset,
|
public AuxiliaryBufferCommand(
|
||||||
ref AuxiliaryBufferAddresses sendBufferInfo, bool isEnabled, uint countMax,
|
uint bufferOffset,
|
||||||
CpuAddress outputBuffer, CpuAddress inputBuffer, uint updateCount, uint writeOffset, int nodeId)
|
byte inputBufferOffset,
|
||||||
|
byte outputBufferOffset,
|
||||||
|
ref AuxiliaryBufferAddresses sendBufferInfo,
|
||||||
|
bool isEnabled,
|
||||||
|
uint countMax,
|
||||||
|
CpuAddress outputBuffer,
|
||||||
|
CpuAddress inputBuffer,
|
||||||
|
uint updateCount,
|
||||||
|
uint writeOffset,
|
||||||
|
int nodeId)
|
||||||
{
|
{
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
NodeId = nodeId;
|
NodeId = nodeId;
|
||||||
|
@@ -21,7 +21,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
private BiquadFilterParameter _parameter;
|
private BiquadFilterParameter _parameter;
|
||||||
|
|
||||||
public BiquadFilterCommand(int baseIndex, ref BiquadFilterParameter filter, Memory<BiquadFilterState> biquadFilterStateMemory, int inputBufferOffset, int outputBufferOffset, bool needInitialization, int nodeId)
|
public BiquadFilterCommand(
|
||||||
|
int baseIndex,
|
||||||
|
ref BiquadFilterParameter filter,
|
||||||
|
Memory<BiquadFilterState> biquadFilterStateMemory,
|
||||||
|
int inputBufferOffset,
|
||||||
|
int outputBufferOffset,
|
||||||
|
bool needInitialization,
|
||||||
|
int nodeId)
|
||||||
{
|
{
|
||||||
_parameter = filter;
|
_parameter = filter;
|
||||||
BiquadFilterState = biquadFilterStateMemory;
|
BiquadFilterState = biquadFilterStateMemory;
|
||||||
|
@@ -77,7 +77,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public unsafe void ClearBuffer(int index)
|
public unsafe void ClearBuffer(int index)
|
||||||
{
|
{
|
||||||
Unsafe.InitBlock((void*)GetBufferPointer(index), 0, SampleCount);
|
Unsafe.InitBlock((void*)GetBufferPointer(index), 0, SampleCount * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -89,7 +89,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public unsafe void CopyBuffer(int outputBufferIndex, int inputBufferIndex)
|
public unsafe void CopyBuffer(int outputBufferIndex, int inputBufferIndex)
|
||||||
{
|
{
|
||||||
Unsafe.CopyBlock((void*)GetBufferPointer(outputBufferIndex), (void*)GetBufferPointer(inputBufferIndex), SampleCount);
|
Unsafe.CopyBlock((void*)GetBufferPointer(outputBufferIndex), (void*)GetBufferPointer(inputBufferIndex), SampleCount * sizeof(float));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
@@ -94,18 +94,18 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
float newMean = inputMovingAverage.Update(FloatingPointHelper.MeanSquare(channelInput), _parameter.InputGain);
|
float newMean = inputMovingAverage.Update(FloatingPointHelper.MeanSquare(channelInput), _parameter.InputGain);
|
||||||
float y = FloatingPointHelper.Log10(newMean) * 10.0f;
|
float y = FloatingPointHelper.Log10(newMean) * 10.0f;
|
||||||
float z = 0.0f;
|
float z = 1.0f;
|
||||||
|
|
||||||
bool unknown10OutOfRange = false;
|
bool unknown10OutOfRange = y >= state.Unknown10;
|
||||||
|
|
||||||
if (newMean < 1.0e-10f)
|
if (newMean < 1.0e-10f)
|
||||||
{
|
{
|
||||||
z = 1.0f;
|
y = -100.0f;
|
||||||
|
|
||||||
unknown10OutOfRange = state.Unknown10 < -100.0f;
|
unknown10OutOfRange = state.Unknown10 <= -100.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y >= state.Unknown10 || unknown10OutOfRange)
|
if (unknown10OutOfRange)
|
||||||
{
|
{
|
||||||
float tmpGain;
|
float tmpGain;
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
tmpGain = (y - state.Unknown10) * ((y - state.Unknown10) * -state.CompressorGainReduction);
|
tmpGain = (y - state.Unknown10) * ((y - state.Unknown10) * -state.CompressorGainReduction);
|
||||||
}
|
}
|
||||||
|
|
||||||
z = FloatingPointHelper.DecibelToLinearExtended(tmpGain);
|
z = FloatingPointHelper.DecibelToLinear(tmpGain);
|
||||||
}
|
}
|
||||||
|
|
||||||
float unknown4New = z;
|
float unknown4New = z;
|
||||||
|
@@ -28,7 +28,14 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
|
|
||||||
private LimiterParameter _parameter;
|
private LimiterParameter _parameter;
|
||||||
|
|
||||||
public LimiterCommandVersion2(uint bufferOffset, LimiterParameter parameter, Memory<LimiterState> state, Memory<EffectResultState> resultState, bool isEnabled, ulong workBuffer, int nodeId)
|
public LimiterCommandVersion2(
|
||||||
|
uint bufferOffset,
|
||||||
|
LimiterParameter parameter,
|
||||||
|
Memory<LimiterState> state,
|
||||||
|
Memory<EffectResultState> resultState,
|
||||||
|
bool isEnabled,
|
||||||
|
ulong workBuffer,
|
||||||
|
int nodeId)
|
||||||
{
|
{
|
||||||
Enabled = true;
|
Enabled = true;
|
||||||
NodeId = nodeId;
|
NodeId = nodeId;
|
||||||
|
@@ -79,7 +79,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ProcessReverbMono(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private void ProcessReverbMono(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
ProcessReverbGeneric(ref state,
|
ProcessReverbGeneric(
|
||||||
|
ref state,
|
||||||
outputBuffers,
|
outputBuffers,
|
||||||
inputBuffers,
|
inputBuffers,
|
||||||
sampleCount,
|
sampleCount,
|
||||||
@@ -92,7 +93,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ProcessReverbStereo(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private void ProcessReverbStereo(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
ProcessReverbGeneric(ref state,
|
ProcessReverbGeneric(
|
||||||
|
ref state,
|
||||||
outputBuffers,
|
outputBuffers,
|
||||||
inputBuffers,
|
inputBuffers,
|
||||||
sampleCount,
|
sampleCount,
|
||||||
@@ -105,7 +107,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ProcessReverbQuadraphonic(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private void ProcessReverbQuadraphonic(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
ProcessReverbGeneric(ref state,
|
ProcessReverbGeneric(
|
||||||
|
ref state,
|
||||||
outputBuffers,
|
outputBuffers,
|
||||||
inputBuffers,
|
inputBuffers,
|
||||||
sampleCount,
|
sampleCount,
|
||||||
@@ -118,7 +121,8 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ProcessReverbSurround(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
private void ProcessReverbSurround(ref ReverbState state, ReadOnlySpan<IntPtr> outputBuffers, ReadOnlySpan<IntPtr> inputBuffers, uint sampleCount)
|
||||||
{
|
{
|
||||||
ProcessReverbGeneric(ref state,
|
ProcessReverbGeneric(
|
||||||
|
ref state,
|
||||||
outputBuffers,
|
outputBuffers,
|
||||||
inputBuffers,
|
inputBuffers,
|
||||||
sampleCount,
|
sampleCount,
|
||||||
|
@@ -52,7 +52,7 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
{
|
{
|
||||||
// NOTE: Nintendo uses an approximation of log10, we don't.
|
// NOTE: Nintendo uses an approximation of log10, we don't.
|
||||||
// As such, we support the same ranges as Nintendo to avoid unexpected behaviours.
|
// As such, we support the same ranges as Nintendo to avoid unexpected behaviours.
|
||||||
return MathF.Pow(10, MathF.Max(x, 1.0e-10f));
|
return MathF.Log10(MathF.Max(x, 1.0e-10f));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
@@ -62,7 +62,8 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
|
|
||||||
foreach (float input in inputs)
|
foreach (float input in inputs)
|
||||||
{
|
{
|
||||||
res += (input * input);
|
float normInput = input * (1f / 32768f);
|
||||||
|
res += normInput * normInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
res /= inputs.Length;
|
res /= inputs.Length;
|
||||||
@@ -81,19 +82,6 @@ namespace Ryujinx.Audio.Renderer.Dsp
|
|||||||
return MathF.Pow(10.0f, db / 20.0f);
|
return MathF.Pow(10.0f, db / 20.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Map decibel to linear in [0, 2] range.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="db">The decibel value to convert</param>
|
|
||||||
/// <returns>Converted linear value in [0, 2] range</returns>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public static float DecibelToLinearExtended(float db)
|
|
||||||
{
|
|
||||||
float tmp = MathF.Log2(DecibelToLinear(db));
|
|
||||||
|
|
||||||
return MathF.Truncate(tmp) + MathF.Pow(2.0f, tmp - MathF.Truncate(tmp));
|
|
||||||
}
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static float DegreesToRadians(float degrees)
|
public static float DegreesToRadians(float degrees)
|
||||||
{
|
{
|
||||||
|
@@ -3,7 +3,7 @@ using Ryujinx.Audio.Renderer.Parameter.Effect;
|
|||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class CompressorState
|
public struct CompressorState
|
||||||
{
|
{
|
||||||
public ExponentialMovingAverage InputMovingAverage;
|
public ExponentialMovingAverage InputMovingAverage;
|
||||||
public float Unknown4;
|
public float Unknown4;
|
||||||
@@ -45,7 +45,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
CompressorGainReduction = (1.0f - ratio) / Constants.ChannelCountMax;
|
CompressorGainReduction = (1.0f - ratio) / Constants.ChannelCountMax;
|
||||||
Unknown10 = threshold - 1.5f;
|
Unknown10 = threshold - 1.5f;
|
||||||
Unknown14 = threshold + 1.5f;
|
Unknown14 = threshold + 1.5f;
|
||||||
OutputGain = FloatingPointHelper.DecibelToLinearExtended(parameter.OutputGain + makeupGain);
|
OutputGain = FloatingPointHelper.DecibelToLinear(parameter.OutputGain + makeupGain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ using System.Runtime.CompilerServices;
|
|||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class DelayState
|
public struct DelayState
|
||||||
{
|
{
|
||||||
public DelayLine[] DelayLines { get; }
|
public DelayLine[] DelayLines { get; }
|
||||||
public float[] LowPassZ { get; set; }
|
public float[] LowPassZ { get; set; }
|
||||||
@@ -53,7 +53,7 @@ namespace Ryujinx.Audio.Renderer.Dsp.State
|
|||||||
LowPassBaseGain = 1.0f - LowPassFeedbackGain;
|
LowPassBaseGain = 1.0f - LowPassFeedbackGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateLowPassFilter(ref float tempRawRef, uint channelCount)
|
public readonly void UpdateLowPassFilter(ref float tempRawRef, uint channelCount)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < channelCount; i++)
|
for (int i = 0; i < channelCount; i++)
|
||||||
{
|
{
|
||||||
|
@@ -4,7 +4,7 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class LimiterState
|
public struct LimiterState
|
||||||
{
|
{
|
||||||
public ExponentialMovingAverage[] DetectorAverage;
|
public ExponentialMovingAverage[] DetectorAverage;
|
||||||
public ExponentialMovingAverage[] CompressionGainAverage;
|
public ExponentialMovingAverage[] CompressionGainAverage;
|
||||||
|
@@ -4,7 +4,7 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class Reverb3dState
|
public struct Reverb3dState
|
||||||
{
|
{
|
||||||
private readonly float[] _fdnDelayMinTimes = new float[4] { 5.0f, 6.0f, 13.0f, 14.0f };
|
private readonly float[] _fdnDelayMinTimes = new float[4] { 5.0f, 6.0f, 13.0f, 14.0f };
|
||||||
private readonly float[] _fdnDelayMaxTimes = new float[4] { 45.704f, 82.782f, 149.94f, 271.58f };
|
private readonly float[] _fdnDelayMaxTimes = new float[4] { 45.704f, 82.782f, 149.94f, 271.58f };
|
||||||
|
@@ -5,7 +5,7 @@ using System;
|
|||||||
|
|
||||||
namespace Ryujinx.Audio.Renderer.Dsp.State
|
namespace Ryujinx.Audio.Renderer.Dsp.State
|
||||||
{
|
{
|
||||||
public class ReverbState
|
public struct ReverbState
|
||||||
{
|
{
|
||||||
private static readonly float[] _fdnDelayTimes = new float[20]
|
private static readonly float[] _fdnDelayTimes = new float[20]
|
||||||
{
|
{
|
||||||
|
@@ -147,6 +147,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
public bool EnableTextureRecompression { get; set; }
|
public bool EnableTextureRecompression { get; set; }
|
||||||
public bool EnableMacroHLE { get; set; }
|
public bool EnableMacroHLE { get; set; }
|
||||||
public bool EnableColorSpacePassthrough { get; set; }
|
public bool EnableColorSpacePassthrough { get; set; }
|
||||||
|
public bool ColorSpacePassthroughAvailable => IsMacOS;
|
||||||
public bool EnableFileLog { get; set; }
|
public bool EnableFileLog { get; set; }
|
||||||
public bool EnableStub { get; set; }
|
public bool EnableStub { get; set; }
|
||||||
public bool EnableInfo { get; set; }
|
public bool EnableInfo { get; set; }
|
||||||
|
@@ -73,6 +73,7 @@
|
|||||||
<TextBlock Text="{locale:Locale SettingsEnableMacroHLE}" />
|
<TextBlock Text="{locale:Locale SettingsEnableMacroHLE}" />
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
<CheckBox IsChecked="{Binding EnableColorSpacePassthrough}"
|
<CheckBox IsChecked="{Binding EnableColorSpacePassthrough}"
|
||||||
|
IsVisible="{Binding ColorSpacePassthroughAvailable}"
|
||||||
ToolTip.Tip="{locale:Locale SettingsEnableColorSpacePassthroughTooltip}">
|
ToolTip.Tip="{locale:Locale SettingsEnableColorSpacePassthroughTooltip}">
|
||||||
<TextBlock Text="{locale:Locale SettingsEnableColorSpacePassthrough}" />
|
<TextBlock Text="{locale:Locale SettingsEnableColorSpacePassthrough}" />
|
||||||
</CheckBox>
|
</CheckBox>
|
||||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
private const ushort FileFormatVersionMajor = 1;
|
private const ushort FileFormatVersionMajor = 1;
|
||||||
private const ushort FileFormatVersionMinor = 2;
|
private const ushort FileFormatVersionMinor = 2;
|
||||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||||
private const uint CodeGenVersion = 5682;
|
private const uint CodeGenVersion = 5750;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
|
@@ -184,8 +184,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
case Instruction.TextureSample:
|
case Instruction.TextureSample:
|
||||||
return TextureSample(context, operation);
|
return TextureSample(context, operation);
|
||||||
|
|
||||||
case Instruction.TextureSize:
|
case Instruction.TextureQuerySamples:
|
||||||
return TextureSize(context, operation);
|
return TextureQuerySamples(context, operation);
|
||||||
|
|
||||||
|
case Instruction.TextureQuerySize:
|
||||||
|
return TextureQuerySize(context, operation);
|
||||||
|
|
||||||
case Instruction.UnpackDouble2x32:
|
case Instruction.UnpackDouble2x32:
|
||||||
return UnpackDouble2x32(context, operation);
|
return UnpackDouble2x32(context, operation);
|
||||||
|
@@ -118,7 +118,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
Add(Instruction.Subtract, InstType.OpBinary, "-", 2);
|
Add(Instruction.Subtract, InstType.OpBinary, "-", 2);
|
||||||
Add(Instruction.SwizzleAdd, InstType.CallTernary, HelperFunctionNames.SwizzleAdd);
|
Add(Instruction.SwizzleAdd, InstType.CallTernary, HelperFunctionNames.SwizzleAdd);
|
||||||
Add(Instruction.TextureSample, InstType.Special);
|
Add(Instruction.TextureSample, InstType.Special);
|
||||||
Add(Instruction.TextureSize, InstType.Special);
|
Add(Instruction.TextureQuerySamples, InstType.Special);
|
||||||
|
Add(Instruction.TextureQuerySize, InstType.Special);
|
||||||
Add(Instruction.Truncate, InstType.CallUnary, "trunc");
|
Add(Instruction.Truncate, InstType.CallUnary, "trunc");
|
||||||
Add(Instruction.UnpackDouble2x32, InstType.Special);
|
Add(Instruction.UnpackDouble2x32, InstType.Special);
|
||||||
Add(Instruction.UnpackHalf2x16, InstType.Special);
|
Add(Instruction.UnpackHalf2x16, InstType.Special);
|
||||||
|
@@ -517,7 +517,33 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
|||||||
return texCall;
|
return texCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string TextureSize(CodeGenContext context, AstOperation operation)
|
public static string TextureQuerySamples(CodeGenContext context, AstOperation operation)
|
||||||
|
{
|
||||||
|
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||||
|
|
||||||
|
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||||
|
|
||||||
|
// TODO: Bindless texture support. For now we just return 0.
|
||||||
|
if (isBindless)
|
||||||
|
{
|
||||||
|
return NumberFormatter.FormatInt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||||
|
|
||||||
|
string indexExpr = null;
|
||||||
|
|
||||||
|
if (isIndexed)
|
||||||
|
{
|
||||||
|
indexExpr = GetSoureExpr(context, texOp.GetSource(0), AggregateType.S32);
|
||||||
|
}
|
||||||
|
|
||||||
|
string samplerName = GetSamplerName(context.Properties, texOp, indexExpr);
|
||||||
|
|
||||||
|
return $"textureSamples({samplerName})";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string TextureQuerySize(CodeGenContext context, AstOperation operation)
|
||||||
{
|
{
|
||||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||||
|
|
||||||
|
@@ -134,7 +134,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
Add(Instruction.Subtract, GenerateSubtract);
|
Add(Instruction.Subtract, GenerateSubtract);
|
||||||
Add(Instruction.SwizzleAdd, GenerateSwizzleAdd);
|
Add(Instruction.SwizzleAdd, GenerateSwizzleAdd);
|
||||||
Add(Instruction.TextureSample, GenerateTextureSample);
|
Add(Instruction.TextureSample, GenerateTextureSample);
|
||||||
Add(Instruction.TextureSize, GenerateTextureSize);
|
Add(Instruction.TextureQuerySamples, GenerateTextureQuerySamples);
|
||||||
|
Add(Instruction.TextureQuerySize, GenerateTextureQuerySize);
|
||||||
Add(Instruction.Truncate, GenerateTruncate);
|
Add(Instruction.Truncate, GenerateTruncate);
|
||||||
Add(Instruction.UnpackDouble2x32, GenerateUnpackDouble2x32);
|
Add(Instruction.UnpackDouble2x32, GenerateUnpackDouble2x32);
|
||||||
Add(Instruction.UnpackHalf2x16, GenerateUnpackHalf2x16);
|
Add(Instruction.UnpackHalf2x16, GenerateUnpackHalf2x16);
|
||||||
@@ -1492,7 +1493,36 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
|
|||||||
return new OperationResult(swizzledResultType, result);
|
return new OperationResult(swizzledResultType, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OperationResult GenerateTextureSize(CodeGenContext context, AstOperation operation)
|
private static OperationResult GenerateTextureQuerySamples(CodeGenContext context, AstOperation operation)
|
||||||
|
{
|
||||||
|
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||||
|
|
||||||
|
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||||
|
|
||||||
|
// TODO: Bindless texture support. For now we just return 0.
|
||||||
|
if (isBindless)
|
||||||
|
{
|
||||||
|
return new OperationResult(AggregateType.S32, context.Constant(context.TypeS32(), 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||||
|
|
||||||
|
if (isIndexed)
|
||||||
|
{
|
||||||
|
context.GetS32(texOp.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
(var imageType, var sampledImageType, var sampledImageVariable) = context.Samplers[texOp.Binding];
|
||||||
|
|
||||||
|
var image = context.Load(sampledImageType, sampledImageVariable);
|
||||||
|
image = context.Image(imageType, image);
|
||||||
|
|
||||||
|
SpvInstruction result = context.ImageQuerySamples(context.TypeS32(), image);
|
||||||
|
|
||||||
|
return new OperationResult(AggregateType.S32, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OperationResult GenerateTextureQuerySize(CodeGenContext context, AstOperation operation)
|
||||||
{
|
{
|
||||||
AstTextureOperation texOp = (AstTextureOperation)operation;
|
AstTextureOperation texOp = (AstTextureOperation)operation;
|
||||||
|
|
||||||
|
@@ -1093,18 +1093,29 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
SamplerType type;
|
SamplerType type;
|
||||||
|
|
||||||
if (isBindless)
|
if (isBindless)
|
||||||
|
{
|
||||||
|
if (query == TexQuery.TexHeaderTextureType)
|
||||||
|
{
|
||||||
|
type = SamplerType.Texture2D | SamplerType.Multisample;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
type = (componentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D;
|
type = (componentMask & 4) != 0 ? SamplerType.Texture3D : SamplerType.Texture2D;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type = context.TranslatorContext.GpuAccessor.QuerySamplerType(imm);
|
type = context.TranslatorContext.GpuAccessor.QuerySamplerType(imm);
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
TextureFlags flags = isBindless ? TextureFlags.Bindless : TextureFlags.None;
|
||||||
|
int binding;
|
||||||
|
|
||||||
int binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
switch (query)
|
||||||
Instruction.TextureSize,
|
{
|
||||||
|
case TexQuery.TexHeaderDimension:
|
||||||
|
binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
|
Instruction.TextureQuerySize,
|
||||||
type,
|
type,
|
||||||
TextureFormat.Unknown,
|
TextureFormat.Unknown,
|
||||||
flags,
|
flags,
|
||||||
@@ -1122,12 +1133,46 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Validate and use query parameter.
|
context.Copy(d, context.TextureQuerySize(type, flags, binding, compIndex, sources));
|
||||||
Operand res = context.TextureSize(type, flags, binding, compIndex, sources);
|
|
||||||
|
|
||||||
context.Copy(d, res);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TexQuery.TexHeaderTextureType:
|
||||||
|
binding = isBindless ? 0 : context.ResourceManager.GetTextureOrImageBinding(
|
||||||
|
Instruction.TextureQuerySamples,
|
||||||
|
type,
|
||||||
|
TextureFormat.Unknown,
|
||||||
|
flags,
|
||||||
|
TextureOperation.DefaultCbufSlot,
|
||||||
|
imm);
|
||||||
|
|
||||||
|
if ((componentMask & 4) != 0)
|
||||||
|
{
|
||||||
|
// Skip first 2 components if necessary.
|
||||||
|
if ((componentMask & 1) != 0)
|
||||||
|
{
|
||||||
|
GetDest();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((componentMask & 2) != 0)
|
||||||
|
{
|
||||||
|
GetDest();
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand d = GetDest();
|
||||||
|
|
||||||
|
if (d != null)
|
||||||
|
{
|
||||||
|
context.Copy(d, context.TextureQuerySamples(type, flags, binding, sources));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
context.TranslatorContext.GpuAccessor.Log($"Invalid or unsupported query type \"{query}\".");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitTextureSample(
|
private static void EmitTextureSample(
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
[Flags]
|
[Flags]
|
||||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
|
||||||
enum Instruction
|
enum Instruction
|
||||||
{
|
{
|
||||||
Absolute = 1,
|
Absolute = 1,
|
||||||
@@ -118,7 +116,8 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
|||||||
Subtract,
|
Subtract,
|
||||||
SwizzleAdd,
|
SwizzleAdd,
|
||||||
TextureSample,
|
TextureSample,
|
||||||
TextureSize,
|
TextureQuerySamples,
|
||||||
|
TextureQuerySize,
|
||||||
Truncate,
|
Truncate,
|
||||||
UnpackDouble2x32,
|
UnpackDouble2x32,
|
||||||
UnpackHalf2x16,
|
UnpackHalf2x16,
|
||||||
@@ -160,7 +159,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
|||||||
public static bool IsTextureQuery(this Instruction inst)
|
public static bool IsTextureQuery(this Instruction inst)
|
||||||
{
|
{
|
||||||
inst &= Instruction.Mask;
|
inst &= Instruction.Mask;
|
||||||
return inst == Instruction.Lod || inst == Instruction.TextureSize;
|
return inst == Instruction.Lod || inst == Instruction.TextureQuerySamples || inst == Instruction.TextureQuerySize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -124,7 +124,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
|||||||
Add(Instruction.Subtract, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
Add(Instruction.Subtract, AggregateType.Scalar, AggregateType.Scalar, AggregateType.Scalar);
|
||||||
Add(Instruction.SwizzleAdd, AggregateType.FP32, AggregateType.FP32, AggregateType.FP32, AggregateType.S32);
|
Add(Instruction.SwizzleAdd, AggregateType.FP32, AggregateType.FP32, AggregateType.FP32, AggregateType.S32);
|
||||||
Add(Instruction.TextureSample, AggregateType.FP32);
|
Add(Instruction.TextureSample, AggregateType.FP32);
|
||||||
Add(Instruction.TextureSize, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
Add(Instruction.TextureQuerySamples, AggregateType.S32, AggregateType.S32);
|
||||||
|
Add(Instruction.TextureQuerySize, AggregateType.S32, AggregateType.S32, AggregateType.S32);
|
||||||
Add(Instruction.Truncate, AggregateType.Scalar, AggregateType.Scalar);
|
Add(Instruction.Truncate, AggregateType.Scalar, AggregateType.Scalar);
|
||||||
Add(Instruction.UnpackDouble2x32, AggregateType.U32, AggregateType.FP64);
|
Add(Instruction.UnpackDouble2x32, AggregateType.U32, AggregateType.FP64);
|
||||||
Add(Instruction.UnpackHalf2x16, AggregateType.FP32, AggregateType.U32);
|
Add(Instruction.UnpackHalf2x16, AggregateType.FP32, AggregateType.U32);
|
||||||
|
@@ -897,7 +897,21 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
context.Add(new TextureOperation(Instruction.TextureSample, type, TextureFormat.Unknown, flags, binding, compMask, dests, sources));
|
context.Add(new TextureOperation(Instruction.TextureSample, type, TextureFormat.Unknown, flags, binding, compMask, dests, sources));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand TextureSize(
|
public static Operand TextureQuerySamples(
|
||||||
|
this EmitterContext context,
|
||||||
|
SamplerType type,
|
||||||
|
TextureFlags flags,
|
||||||
|
int binding,
|
||||||
|
Operand[] sources)
|
||||||
|
{
|
||||||
|
Operand dest = Local();
|
||||||
|
|
||||||
|
context.Add(new TextureOperation(Instruction.TextureQuerySamples, type, TextureFormat.Unknown, flags, binding, 0, new[] { dest }, sources));
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand TextureQuerySize(
|
||||||
this EmitterContext context,
|
this EmitterContext context,
|
||||||
SamplerType type,
|
SamplerType type,
|
||||||
TextureFlags flags,
|
TextureFlags flags,
|
||||||
@@ -907,7 +921,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
{
|
{
|
||||||
Operand dest = Local();
|
Operand dest = Local();
|
||||||
|
|
||||||
context.Add(new TextureOperation(Instruction.TextureSize, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources));
|
context.Add(new TextureOperation(Instruction.TextureQuerySize, type, TextureFormat.Unknown, flags, binding, compIndex, new[] { dest }, sources));
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
@@ -27,9 +27,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texOp.Inst == Instruction.Lod ||
|
if (texOp.Inst == Instruction.TextureSample || texOp.Inst.IsTextureQuery())
|
||||||
texOp.Inst == Instruction.TextureSample ||
|
|
||||||
texOp.Inst == Instruction.TextureSize)
|
|
||||||
{
|
{
|
||||||
Operand bindlessHandle = Utils.FindLastOperation(texOp.GetSource(0), block);
|
Operand bindlessHandle = Utils.FindLastOperation(texOp.GetSource(0), block);
|
||||||
|
|
||||||
@@ -40,7 +38,8 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||||||
// as long bindless elimination is successful and we know where the texture descriptor is located.
|
// as long bindless elimination is successful and we know where the texture descriptor is located.
|
||||||
bool rewriteSamplerType =
|
bool rewriteSamplerType =
|
||||||
texOp.Type == SamplerType.TextureBuffer ||
|
texOp.Type == SamplerType.TextureBuffer ||
|
||||||
texOp.Inst == Instruction.TextureSize;
|
texOp.Inst == Instruction.TextureQuerySamples ||
|
||||||
|
texOp.Inst == Instruction.TextureQuerySize;
|
||||||
|
|
||||||
if (bindlessHandle.Type == OperandType.ConstantBuffer)
|
if (bindlessHandle.Type == OperandType.ConstantBuffer)
|
||||||
{
|
{
|
||||||
|
@@ -232,8 +232,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
inst &= Instruction.Mask;
|
inst &= Instruction.Mask;
|
||||||
bool isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
bool isImage = inst == Instruction.ImageLoad || inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
||||||
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
bool isWrite = inst == Instruction.ImageStore || inst == Instruction.ImageAtomic;
|
||||||
bool accurateType = inst != Instruction.Lod && inst != Instruction.TextureSize;
|
bool accurateType = !inst.IsTextureQuery();
|
||||||
bool intCoords = isImage || flags.HasFlag(TextureFlags.IntCoords) || inst == Instruction.TextureSize;
|
bool intCoords = isImage || flags.HasFlag(TextureFlags.IntCoords) || inst == Instruction.TextureQuerySize;
|
||||||
bool coherent = flags.HasFlag(TextureFlags.Coherent);
|
bool coherent = flags.HasFlag(TextureFlags.Coherent);
|
||||||
|
|
||||||
if (!isImage)
|
if (!isImage)
|
||||||
|
@@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
{
|
{
|
||||||
node = InsertCoordNormalization(context.Hfm, node, context.ResourceManager, context.GpuAccessor, context.Stage);
|
node = InsertCoordNormalization(context.Hfm, node, context.ResourceManager, context.GpuAccessor, context.Stage);
|
||||||
node = InsertCoordGatherBias(node, context.ResourceManager, context.GpuAccessor);
|
node = InsertCoordGatherBias(node, context.ResourceManager, context.GpuAccessor);
|
||||||
node = InsertConstOffsets(node, context.ResourceManager, context.GpuAccessor);
|
node = InsertConstOffsets(node, context.GpuAccessor, context.Stage);
|
||||||
|
|
||||||
if (texOp.Type == SamplerType.TextureBuffer && !context.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat())
|
if (texOp.Type == SamplerType.TextureBuffer && !context.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat())
|
||||||
{
|
{
|
||||||
@@ -99,7 +99,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
bool isBindless = (texOp.Flags & TextureFlags.Bindless) != 0;
|
||||||
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
bool isIndexed = (texOp.Type & SamplerType.Indexed) != 0;
|
||||||
|
|
||||||
if (texOp.Inst == Instruction.TextureSize &&
|
if (texOp.Inst == Instruction.TextureQuerySize &&
|
||||||
texOp.Index < 2 &&
|
texOp.Index < 2 &&
|
||||||
!isBindless &&
|
!isBindless &&
|
||||||
!isIndexed &&
|
!isIndexed &&
|
||||||
@@ -190,7 +190,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
}
|
}
|
||||||
|
|
||||||
LinkedListNode<INode> textureSizeNode = node.List.AddBefore(node, new TextureOperation(
|
LinkedListNode<INode> textureSizeNode = node.List.AddBefore(node, new TextureOperation(
|
||||||
Instruction.TextureSize,
|
Instruction.TextureQuerySize,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
@@ -259,7 +259,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
}
|
}
|
||||||
|
|
||||||
node.List.AddBefore(node, new TextureOperation(
|
node.List.AddBefore(node, new TextureOperation(
|
||||||
Instruction.TextureSize,
|
Instruction.TextureQuerySize,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
@@ -287,7 +287,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LinkedListNode<INode> InsertConstOffsets(LinkedListNode<INode> node, ResourceManager resourceManager, IGpuAccessor gpuAccessor)
|
private static LinkedListNode<INode> InsertConstOffsets(LinkedListNode<INode> node, IGpuAccessor gpuAccessor, ShaderStage stage)
|
||||||
{
|
{
|
||||||
// Non-constant texture offsets are not allowed (according to the spec),
|
// Non-constant texture offsets are not allowed (according to the spec),
|
||||||
// however some GPUs does support that.
|
// however some GPUs does support that.
|
||||||
@@ -440,7 +440,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
|
|
||||||
sources.CopyTo(newSources, 0);
|
sources.CopyTo(newSources, 0);
|
||||||
|
|
||||||
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount);
|
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount, stage);
|
||||||
|
|
||||||
int destIndex = 0;
|
int destIndex = 0;
|
||||||
|
|
||||||
@@ -502,7 +502,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount);
|
Operand[] texSizes = InsertTextureLod(node, texOp, lodSources, bindlessHandle, coordsCount, stage);
|
||||||
|
|
||||||
for (int index = 0; index < coordsCount; index++)
|
for (int index = 0; index < coordsCount; index++)
|
||||||
{
|
{
|
||||||
@@ -554,11 +554,16 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
TextureOperation texOp,
|
TextureOperation texOp,
|
||||||
Operand[] lodSources,
|
Operand[] lodSources,
|
||||||
Operand bindlessHandle,
|
Operand bindlessHandle,
|
||||||
int coordsCount)
|
int coordsCount,
|
||||||
|
ShaderStage stage)
|
||||||
{
|
{
|
||||||
Operand[] texSizes = new Operand[coordsCount];
|
Operand[] texSizes = new Operand[coordsCount];
|
||||||
|
|
||||||
Operand lod = Local();
|
Operand lod;
|
||||||
|
|
||||||
|
if (stage == ShaderStage.Fragment)
|
||||||
|
{
|
||||||
|
lod = Local();
|
||||||
|
|
||||||
node.List.AddBefore(node, new TextureOperation(
|
node.List.AddBefore(node, new TextureOperation(
|
||||||
Instruction.Lod,
|
Instruction.Lod,
|
||||||
@@ -569,6 +574,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
0,
|
0,
|
||||||
new[] { lod },
|
new[] { lod },
|
||||||
lodSources));
|
lodSources));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lod = Const(0);
|
||||||
|
}
|
||||||
|
|
||||||
for (int index = 0; index < coordsCount; index++)
|
for (int index = 0; index < coordsCount; index++)
|
||||||
{
|
{
|
||||||
@@ -586,7 +596,7 @@ namespace Ryujinx.Graphics.Shader.Translation.Transforms
|
|||||||
}
|
}
|
||||||
|
|
||||||
node.List.AddBefore(node, new TextureOperation(
|
node.List.AddBefore(node, new TextureOperation(
|
||||||
Instruction.TextureSize,
|
Instruction.TextureQuerySize,
|
||||||
texOp.Type,
|
texOp.Type,
|
||||||
texOp.Format,
|
texOp.Format,
|
||||||
texOp.Flags,
|
texOp.Flags,
|
||||||
|
@@ -36,6 +36,8 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
|||||||
throw new InvalidOperationException("Out of handles!");
|
throw new InvalidOperationException("Out of handles!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_completionEvent.WritableEvent.Signal();
|
||||||
|
|
||||||
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(completionEventHandle);
|
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(completionEventHandle);
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
@@ -187,6 +189,20 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator
|
|||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CommandCmif(10420)]
|
||||||
|
// nn::friends::CheckBlockedUserListAvailability(nn::account::Uid userId) -> bool
|
||||||
|
public ResultCode CheckBlockedUserListAvailability(ServiceCtx context)
|
||||||
|
{
|
||||||
|
UserId userId = context.RequestData.ReadStruct<UserId>();
|
||||||
|
|
||||||
|
// Yes, it is available.
|
||||||
|
context.ResponseData.Write(true);
|
||||||
|
|
||||||
|
Logger.Stub?.PrintStub(LogClass.ServiceFriend, new { UserId = userId.ToString() });
|
||||||
|
|
||||||
|
return ResultCode.Success;
|
||||||
|
}
|
||||||
|
|
||||||
[CommandCmif(10600)]
|
[CommandCmif(10600)]
|
||||||
// nn::friends::DeclareOpenOnlinePlaySession(nn::account::Uid userId)
|
// nn::friends::DeclareOpenOnlinePlaySession(nn::account::Uid userId)
|
||||||
public ResultCode DeclareOpenOnlinePlaySession(ServiceCtx context)
|
public ResultCode DeclareOpenOnlinePlaySession(ServiceCtx context)
|
||||||
|
@@ -669,6 +669,12 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||||||
|
|
||||||
lock (Core.Lock)
|
lock (Core.Lock)
|
||||||
{
|
{
|
||||||
|
// If we are replacing a buffer that has already been queued, make sure we release the references.
|
||||||
|
if (Core.Slots[slot].BufferState == BufferState.Queued)
|
||||||
|
{
|
||||||
|
Core.Slots[slot].GraphicBuffer.Object.DecrementNvMapHandleRefCount(Core.Owner);
|
||||||
|
}
|
||||||
|
|
||||||
Core.Slots[slot].BufferState = BufferState.Free;
|
Core.Slots[slot].BufferState = BufferState.Free;
|
||||||
Core.Slots[slot].Fence = AndroidFence.NoFence;
|
Core.Slots[slot].Fence = AndroidFence.NoFence;
|
||||||
Core.Slots[slot].RequestBufferCalled = false;
|
Core.Slots[slot].RequestBufferCalled = false;
|
||||||
|
Reference in New Issue
Block a user