Account for res scale changes when updating bindings (#3403)

Fixes a regression introduced by the texture bindings PR.

Also renames TextureStatePerStage, as it's no longer per stage.
This commit is contained in:
riperiperi 2022-06-17 21:41:38 +01:00 committed by GitHub
parent 99ffc061d3
commit 68f9091870
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -35,7 +35,7 @@ namespace Ryujinx.Graphics.Gpu.Image
private readonly TextureBindingInfo[][] _textureBindings; private readonly TextureBindingInfo[][] _textureBindings;
private readonly TextureBindingInfo[][] _imageBindings; private readonly TextureBindingInfo[][] _imageBindings;
private struct TextureStatePerStage private struct TextureState
{ {
public ITexture Texture; public ITexture Texture;
public ISampler Sampler; public ISampler Sampler;
@ -45,10 +45,12 @@ namespace Ryujinx.Graphics.Gpu.Image
public int InvalidatedSequence; public int InvalidatedSequence;
public Texture CachedTexture; public Texture CachedTexture;
public Sampler CachedSampler; public Sampler CachedSampler;
public int ScaleIndex;
public TextureUsageFlags UsageFlags;
} }
private TextureStatePerStage[] _textureState; private TextureState[] _textureState;
private TextureStatePerStage[] _imageState; private TextureState[] _imageState;
private int[] _textureBindingsCount; private int[] _textureBindingsCount;
private int[] _imageBindingsCount; private int[] _imageBindingsCount;
@ -83,8 +85,8 @@ namespace Ryujinx.Graphics.Gpu.Image
_textureBindings = new TextureBindingInfo[stages][]; _textureBindings = new TextureBindingInfo[stages][];
_imageBindings = new TextureBindingInfo[stages][]; _imageBindings = new TextureBindingInfo[stages][];
_textureState = new TextureStatePerStage[InitialTextureStateSize]; _textureState = new TextureState[InitialTextureStateSize];
_imageState = new TextureStatePerStage[InitialImageStateSize]; _imageState = new TextureState[InitialImageStateSize];
_textureBindingsCount = new int[stages]; _textureBindingsCount = new int[stages];
_imageBindingsCount = new int[stages]; _imageBindingsCount = new int[stages];
@ -230,18 +232,18 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Updates the texture scale for a given texture or image. /// Updates the texture scale for a given texture or image.
/// </summary> /// </summary>
/// <param name="texture">Start GPU virtual address of the pool</param> /// <param name="texture">Start GPU virtual address of the pool</param>
/// <param name="binding">The related texture binding</param> /// <param name="usageFlags">The related texture usage flags</param>
/// <param name="index">The texture/image binding index</param> /// <param name="index">The texture/image binding index</param>
/// <param name="stage">The active shader stage</param> /// <param name="stage">The active shader stage</param>
/// <returns>True if the given texture has become blacklisted, indicating that its host texture may have changed.</returns> /// <returns>True if the given texture has become blacklisted, indicating that its host texture may have changed.</returns>
private bool UpdateScale(Texture texture, TextureBindingInfo binding, int index, ShaderStage stage) private bool UpdateScale(Texture texture, TextureUsageFlags usageFlags, int index, ShaderStage stage)
{ {
float result = 1f; float result = 1f;
bool changed = false; bool changed = false;
if ((binding.Flags & TextureUsageFlags.NeedsScaleValue) != 0 && texture != null) if ((usageFlags & TextureUsageFlags.NeedsScaleValue) != 0 && texture != null)
{ {
if ((binding.Flags & TextureUsageFlags.ResScaleUnsupported) != 0) if ((usageFlags & TextureUsageFlags.ResScaleUnsupported) != 0)
{ {
changed = texture.ScaleMode != TextureScaleMode.Blacklisted; changed = texture.ScaleMode != TextureScaleMode.Blacklisted;
texture.BlacklistScale(); texture.BlacklistScale();
@ -469,6 +471,7 @@ namespace Ryujinx.Graphics.Gpu.Image
for (int index = 0; index < textureCount; index++) for (int index = 0; index < textureCount; index++)
{ {
TextureBindingInfo bindingInfo = _textureBindings[stageIndex][index]; TextureBindingInfo bindingInfo = _textureBindings[stageIndex][index];
TextureUsageFlags usageFlags = bindingInfo.Flags;
(int textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, _textureBufferIndex); (int textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, _textureBufferIndex);
@ -487,7 +490,7 @@ namespace Ryujinx.Graphics.Gpu.Image
samplerId = TextureHandle.UnpackSamplerId(packedId); samplerId = TextureHandle.UnpackSamplerId(packedId);
} }
ref TextureStatePerStage state = ref _textureState[bindingInfo.Binding]; ref TextureState state = ref _textureState[bindingInfo.Binding];
if (!poolModified && if (!poolModified &&
state.TextureHandle == textureId && state.TextureHandle == textureId &&
@ -499,6 +502,18 @@ namespace Ryujinx.Graphics.Gpu.Image
// The texture is already bound. // The texture is already bound.
state.CachedTexture.SynchronizeMemory(); state.CachedTexture.SynchronizeMemory();
if ((state.ScaleIndex != index || state.UsageFlags != usageFlags) &&
UpdateScale(state.CachedTexture, usageFlags, index, stage))
{
ITexture hostTextureRebind = state.CachedTexture.GetTargetTexture(bindingInfo.Target);
state.Texture = hostTextureRebind;
state.ScaleIndex = index;
state.UsageFlags = usageFlags;
_context.Renderer.Pipeline.SetTexture(bindingInfo.Binding, hostTextureRebind);
}
continue; continue;
} }
@ -522,12 +537,14 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
if (state.Texture != hostTexture) if (state.Texture != hostTexture)
{ {
if (UpdateScale(texture, bindingInfo, index, stage)) if (UpdateScale(texture, usageFlags, index, stage))
{ {
hostTexture = texture?.GetTargetTexture(bindingInfo.Target); hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
} }
state.Texture = hostTexture; state.Texture = hostTexture;
state.ScaleIndex = index;
state.UsageFlags = usageFlags;
_context.Renderer.Pipeline.SetTexture(bindingInfo.Binding, hostTexture); _context.Renderer.Pipeline.SetTexture(bindingInfo.Binding, hostTexture);
} }
@ -589,6 +606,8 @@ namespace Ryujinx.Graphics.Gpu.Image
for (int index = 0; index < imageCount; index++) for (int index = 0; index < imageCount; index++)
{ {
TextureBindingInfo bindingInfo = _imageBindings[stageIndex][index]; TextureBindingInfo bindingInfo = _imageBindings[stageIndex][index];
TextureUsageFlags usageFlags = bindingInfo.Flags;
int scaleIndex = baseScaleIndex + index;
(int textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, _textureBufferIndex); (int textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, _textureBufferIndex);
@ -597,7 +616,7 @@ namespace Ryujinx.Graphics.Gpu.Image
int packedId = TextureHandle.ReadPackedId(bindingInfo.Handle, cachedTextureBuffer, cachedSamplerBuffer); int packedId = TextureHandle.ReadPackedId(bindingInfo.Handle, cachedTextureBuffer, cachedSamplerBuffer);
int textureId = TextureHandle.UnpackTextureId(packedId); int textureId = TextureHandle.UnpackTextureId(packedId);
ref TextureStatePerStage state = ref _imageState[bindingInfo.Binding]; ref TextureState state = ref _imageState[bindingInfo.Binding];
bool isStore = bindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore); bool isStore = bindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
@ -606,12 +625,28 @@ namespace Ryujinx.Graphics.Gpu.Image
state.CachedTexture != null && state.CachedTexture != null &&
state.CachedTexture.InvalidatedSequence == state.InvalidatedSequence) state.CachedTexture.InvalidatedSequence == state.InvalidatedSequence)
{ {
Texture cachedTexture = state.CachedTexture;
// The texture is already bound. // The texture is already bound.
state.CachedTexture.SynchronizeMemory(); cachedTexture.SynchronizeMemory();
if (isStore) if (isStore)
{ {
state.CachedTexture?.SignalModified(); cachedTexture?.SignalModified();
}
if ((state.ScaleIndex != index || state.UsageFlags != usageFlags) &&
UpdateScale(state.CachedTexture, usageFlags, scaleIndex, stage))
{
ITexture hostTextureRebind = state.CachedTexture.GetTargetTexture(bindingInfo.Target);
Format format = bindingInfo.Format == 0 ? cachedTexture.Format : bindingInfo.Format;
state.Texture = hostTextureRebind;
state.ScaleIndex = scaleIndex;
state.UsageFlags = usageFlags;
_context.Renderer.Pipeline.SetImage(bindingInfo.Binding, hostTextureRebind, format);
} }
continue; continue;
@ -649,12 +684,14 @@ namespace Ryujinx.Graphics.Gpu.Image
if (state.Texture != hostTexture) if (state.Texture != hostTexture)
{ {
if (UpdateScale(texture, bindingInfo, baseScaleIndex + index, stage)) if (UpdateScale(texture, usageFlags, scaleIndex, stage))
{ {
hostTexture = texture?.GetTargetTexture(bindingInfo.Target); hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
} }
state.Texture = hostTexture; state.Texture = hostTexture;
state.ScaleIndex = scaleIndex;
state.UsageFlags = usageFlags;
Format format = bindingInfo.Format; Format format = bindingInfo.Format;