aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs')
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs96
1 files changed, 69 insertions, 27 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index 067a1f9f..6c122124 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -281,6 +281,30 @@ namespace Ryujinx.Graphics.Gpu.Image
}
/// <summary>
+ /// Determines if the vertex stage requires a scale value.
+ /// </summary>
+ private bool VertexRequiresScale()
+ {
+ for (int i = 0; i < _textureBindingsCount[0]; i++)
+ {
+ if ((_textureBindings[0][i].Flags & TextureUsageFlags.NeedsScaleValue) != 0)
+ {
+ return true;
+ }
+ }
+
+ for (int i = 0; i < _imageBindingsCount[0]; i++)
+ {
+ if ((_imageBindings[0][i].Flags & TextureUsageFlags.NeedsScaleValue) != 0)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
/// Uploads texture and image scales to the backend when they are used.
/// </summary>
private void CommitRenderScale()
@@ -291,10 +315,10 @@ namespace Ryujinx.Graphics.Gpu.Image
int fragmentIndex = (int)ShaderStage.Fragment - 1;
int fragmentTotal = _isCompute ? 0 : (_textureBindingsCount[fragmentIndex] + _imageBindingsCount[fragmentIndex]);
- if (total != 0 && fragmentTotal != _lastFragmentTotal)
+ if (total != 0 && fragmentTotal != _lastFragmentTotal && VertexRequiresScale())
{
// Must update scales in the support buffer if:
- // - Vertex stage has bindings.
+ // - Vertex stage has bindings that require scale.
// - Fragment stage binding count has been updated since last render scale update.
_scaleChanged = true;
@@ -421,6 +445,25 @@ namespace Ryujinx.Graphics.Gpu.Image
}
/// <summary>
+ /// Counts the total number of texture bindings used by all shader stages.
+ /// </summary>
+ /// <returns>The total amount of textures used</returns>
+ private int GetTextureBindingsCount()
+ {
+ int count = 0;
+
+ for (int i = 0; i < _textureBindings.Length; i++)
+ {
+ if (_textureBindings[i] != null)
+ {
+ count += _textureBindings[i].Length;
+ }
+ }
+
+ return count;
+ }
+
+ /// <summary>
/// Ensures that the texture bindings are visible to the host GPU.
/// Note: this actually performs the binding using the host graphics API.
/// </summary>
@@ -501,7 +544,7 @@ namespace Ryujinx.Graphics.Gpu.Image
state.ScaleIndex = index;
state.UsageFlags = usageFlags;
- _context.Renderer.Pipeline.SetTexture(bindingInfo.Binding, hostTextureRebind);
+ _context.Renderer.Pipeline.SetTextureAndSampler(stage, bindingInfo.Binding, hostTextureRebind, state.Sampler);
}
continue;
@@ -514,44 +557,42 @@ namespace Ryujinx.Graphics.Gpu.Image
specStateMatches &= specState.MatchesTexture(stage, index, descriptor);
+ Sampler sampler = _samplerPool?.Get(samplerId);
+
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
+ ISampler hostSampler = sampler?.GetHostSampler(texture);
if (hostTexture != null && texture.Target == Target.TextureBuffer)
{
// Ensure that the buffer texture is using the correct buffer as storage.
// Buffers are frequently re-created to accomodate larger data, so we need to re-bind
// to ensure we're not using a old buffer that was already deleted.
- _channel.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, bindingInfo.Format, false);
+ _channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, bindingInfo.Format, false);
}
else
{
- if (state.Texture != hostTexture)
+ bool textureOrSamplerChanged = state.Texture != hostTexture || state.Sampler != hostSampler;
+
+ if ((state.ScaleIndex != index || state.UsageFlags != usageFlags || textureOrSamplerChanged) &&
+ UpdateScale(texture, usageFlags, index, stage))
{
- if (UpdateScale(texture, usageFlags, index, stage))
- {
- hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
- }
+ hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
+ textureOrSamplerChanged = true;
+ }
+ if (textureOrSamplerChanged)
+ {
state.Texture = hostTexture;
state.ScaleIndex = index;
state.UsageFlags = usageFlags;
- _context.Renderer.Pipeline.SetTexture(bindingInfo.Binding, hostTexture);
- }
-
- Sampler sampler = samplerPool?.Get(samplerId);
- state.CachedSampler = sampler;
-
- ISampler hostSampler = sampler?.GetHostSampler(texture);
-
- if (state.Sampler != hostSampler)
- {
state.Sampler = hostSampler;
- _context.Renderer.Pipeline.SetSampler(bindingInfo.Binding, hostSampler);
+ _context.Renderer.Pipeline.SetTextureAndSampler(stage, bindingInfo.Binding, hostTexture, hostSampler);
}
state.CachedTexture = texture;
+ state.CachedSampler = sampler;
state.InvalidatedSequence = texture?.InvalidatedSequence ?? 0;
}
}
@@ -625,7 +666,7 @@ namespace Ryujinx.Graphics.Gpu.Image
cachedTexture?.SignalModified();
}
- if ((state.ScaleIndex != index || state.UsageFlags != usageFlags) &&
+ if ((state.ScaleIndex != scaleIndex || state.UsageFlags != usageFlags) &&
UpdateScale(state.CachedTexture, usageFlags, scaleIndex, stage))
{
ITexture hostTextureRebind = state.CachedTexture.GetTargetTexture(bindingInfo.Target);
@@ -663,7 +704,7 @@ namespace Ryujinx.Graphics.Gpu.Image
format = texture.Format;
}
- _channel.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, format, true);
+ _channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, format, true);
}
else
{
@@ -672,13 +713,14 @@ namespace Ryujinx.Graphics.Gpu.Image
texture?.SignalModified();
}
- if (state.Texture != hostTexture)
+ if ((state.ScaleIndex != scaleIndex || state.UsageFlags != usageFlags || state.Texture != hostTexture) &&
+ UpdateScale(texture, usageFlags, scaleIndex, stage))
{
- if (UpdateScale(texture, usageFlags, scaleIndex, stage))
- {
- hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
- }
+ hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
+ }
+ if (state.Texture != hostTexture)
+ {
state.Texture = hostTexture;
state.ScaleIndex = scaleIndex;
state.UsageFlags = usageFlags;