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.cs164
1 files changed, 93 insertions, 71 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
index fcd23441..067a1f9f 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs
@@ -13,7 +13,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <summary>
/// Texture bindings manager.
/// </summary>
- class TextureBindingsManager : IDisposable
+ class TextureBindingsManager
{
private const int InitialTextureStateSize = 32;
private const int InitialImageStateSize = 8;
@@ -22,15 +22,17 @@ namespace Ryujinx.Graphics.Gpu.Image
private readonly bool _isCompute;
- private SamplerPool _samplerPool;
-
+ private ulong _texturePoolGpuVa;
+ private int _texturePoolMaximumId;
+ private TexturePool _texturePool;
+ private ulong _samplerPoolGpuVa;
+ private int _samplerPoolMaximumId;
private SamplerIndex _samplerIndex;
-
- private ulong _texturePoolAddress;
- private int _texturePoolMaximumId;
+ private SamplerPool _samplerPool;
private readonly GpuChannel _channel;
private readonly TexturePoolCache _texturePoolCache;
+ private readonly SamplerPoolCache _samplerPoolCache;
private TexturePool _cachedTexturePool;
private SamplerPool _cachedSamplerPool;
@@ -72,16 +74,25 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary>
/// <param name="context">The GPU context that the texture bindings manager belongs to</param>
/// <param name="channel">The GPU channel that the texture bindings manager belongs to</param>
- /// <param name="poolCache">Texture pools cache used to get texture pools from</param>
+ /// <param name="texturePoolCache">Texture pools cache used to get texture pools from</param>
+ /// <param name="samplerPoolCache">Sampler pools cache used to get sampler pools from</param>
/// <param name="scales">Array where the scales for the currently bound textures are stored</param>
/// <param name="isCompute">True if the bindings manager is used for the compute engine</param>
- public TextureBindingsManager(GpuContext context, GpuChannel channel, TexturePoolCache poolCache, float[] scales, bool isCompute)
+ public TextureBindingsManager(
+ GpuContext context,
+ GpuChannel channel,
+ TexturePoolCache texturePoolCache,
+ SamplerPoolCache samplerPoolCache,
+ float[] scales,
+ bool isCompute)
{
- _context = context;
- _channel = channel;
- _texturePoolCache = poolCache;
- _scales = scales;
- _isCompute = isCompute;
+ _context = context;
+ _channel = channel;
+ _texturePoolCache = texturePoolCache;
+ _samplerPoolCache = samplerPoolCache;
+
+ _scales = scales;
+ _isCompute = isCompute;
int stages = isCompute ? 1 : Constants.ShaderStages;
@@ -173,25 +184,10 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="samplerIndex">Type of the sampler pool indexing used for bound samplers</param>
public void SetSamplerPool(ulong gpuVa, int maximumId, SamplerIndex samplerIndex)
{
- if (gpuVa != 0)
- {
- ulong address = _channel.MemoryManager.Translate(gpuVa);
-
- if (_samplerPool != null && _samplerPool.Address == address && _samplerPool.MaximumId >= maximumId)
- {
- return;
- }
-
- _samplerPool?.Dispose();
- _samplerPool = new SamplerPool(_context, _channel.MemoryManager.Physical, address, maximumId);
- }
- else
- {
- _samplerPool?.Dispose();
- _samplerPool = null;
- }
-
+ _samplerPoolGpuVa = gpuVa;
+ _samplerPoolMaximumId = maximumId;
_samplerIndex = samplerIndex;
+ _samplerPool = null;
}
/// <summary>
@@ -201,18 +197,9 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="maximumId">Maximum ID of the pool (total count minus one)</param>
public void SetTexturePool(ulong gpuVa, int maximumId)
{
- if (gpuVa != 0)
- {
- ulong address = _channel.MemoryManager.Translate(gpuVa);
-
- _texturePoolAddress = address;
- _texturePoolMaximumId = maximumId;
- }
- else
- {
- _texturePoolAddress = 0;
- _texturePoolMaximumId = 0;
- }
+ _texturePoolGpuVa = gpuVa;
+ _texturePoolMaximumId = maximumId;
+ _texturePool = null;
}
/// <summary>
@@ -222,13 +209,9 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="samplerId">ID of the sampler</param>
public (Texture, Sampler) GetTextureAndSampler(int textureId, int samplerId)
{
- ulong texturePoolAddress = _texturePoolAddress;
-
- TexturePool texturePool = texturePoolAddress != 0
- ? _texturePoolCache.FindOrCreate(_channel, texturePoolAddress, _texturePoolMaximumId)
- : null;
+ (TexturePool texturePool, SamplerPool samplerPool) = GetPools();
- return (texturePool.Get(textureId), _samplerPool.Get(samplerId));
+ return (texturePool.Get(textureId), samplerPool.Get(samplerId));
}
/// <summary>
@@ -340,13 +323,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <returns>True if all bound textures match the current shader specialiation state, false otherwise</returns>
public bool CommitBindings(ShaderSpecializationState specState)
{
- ulong texturePoolAddress = _texturePoolAddress;
-
- TexturePool texturePool = texturePoolAddress != 0
- ? _texturePoolCache.FindOrCreate(_channel, texturePoolAddress, _texturePoolMaximumId)
- : null;
-
- SamplerPool samplerPool = _samplerPool;
+ (TexturePool texturePool, SamplerPool samplerPool) = GetPools();
// Check if the texture pool has been modified since bindings were last committed.
// If it wasn't, then it's possible to avoid looking up textures again when the handle remains the same.
@@ -381,7 +358,7 @@ namespace Ryujinx.Graphics.Gpu.Image
if (_isCompute)
{
- specStateMatches &= CommitTextureBindings(texturePool, ShaderStage.Compute, 0, poolModified, specState);
+ specStateMatches &= CommitTextureBindings(texturePool, samplerPool, ShaderStage.Compute, 0, poolModified, specState);
specStateMatches &= CommitImageBindings(texturePool, ShaderStage.Compute, 0, poolModified, specState);
}
else
@@ -390,7 +367,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
int stageIndex = (int)stage - 1;
- specStateMatches &= CommitTextureBindings(texturePool, stage, stageIndex, poolModified, specState);
+ specStateMatches &= CommitTextureBindings(texturePool, samplerPool, stage, stageIndex, poolModified, specState);
specStateMatches &= CommitImageBindings(texturePool, stage, stageIndex, poolModified, specState);
}
}
@@ -447,13 +424,20 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Ensures that the texture bindings are visible to the host GPU.
/// Note: this actually performs the binding using the host graphics API.
/// </summary>
- /// <param name="pool">The current texture pool</param>
+ /// <param name="texturePool">The current texture pool</param>
+ /// <param name="samplerPool">The current sampler pool</param>
/// <param name="stage">The shader stage using the textures to be bound</param>
/// <param name="stageIndex">The stage number of the specified shader stage</param
/// <param name="poolModified">True if either the texture or sampler pool was modified, false otherwise</param>
/// <param name="specState">Specialization state for the bound shader</param>
/// <returns>True if all bound textures match the current shader specialiation state, false otherwise</returns>
- private bool CommitTextureBindings(TexturePool pool, ShaderStage stage, int stageIndex, bool poolModified, ShaderSpecializationState specState)
+ private bool CommitTextureBindings(
+ TexturePool texturePool,
+ SamplerPool samplerPool,
+ ShaderStage stage,
+ int stageIndex,
+ bool poolModified,
+ ShaderSpecializationState specState)
{
int textureCount = _textureBindingsCount[stageIndex];
if (textureCount == 0)
@@ -461,9 +445,7 @@ namespace Ryujinx.Graphics.Gpu.Image
return true;
}
- var samplerPool = _samplerPool;
-
- if (pool == null)
+ if (texturePool == null)
{
Logger.Error?.Print(LogClass.Gpu, $"Shader stage \"{stage}\" uses textures, but texture pool was not set.");
return true;
@@ -528,7 +510,7 @@ namespace Ryujinx.Graphics.Gpu.Image
state.TextureHandle = textureId;
state.SamplerHandle = samplerId;
- ref readonly TextureDescriptor descriptor = ref pool.GetForBinding(textureId, out Texture texture);
+ ref readonly TextureDescriptor descriptor = ref texturePool.GetForBinding(textureId, out Texture texture);
specStateMatches &= specState.MatchesTexture(stage, index, descriptor);
@@ -820,20 +802,60 @@ namespace Ryujinx.Graphics.Gpu.Image
}
/// <summary>
- /// Force all bound textures and images to be rebound the next time CommitBindings is called.
+ /// Gets the texture and sampler pool for the GPU virtual address that are currently set.
/// </summary>
- public void Rebind()
+ /// <returns>The texture and sampler pools</returns>
+ private (TexturePool, SamplerPool) GetPools()
{
- Array.Clear(_textureState);
- Array.Clear(_imageState);
+ MemoryManager memoryManager = _channel.MemoryManager;
+
+ TexturePool texturePool = _texturePool;
+ SamplerPool samplerPool = _samplerPool;
+
+ if (texturePool == null)
+ {
+ ulong poolAddress = memoryManager.Translate(_texturePoolGpuVa);
+
+ if (poolAddress != MemoryManager.PteUnmapped)
+ {
+ texturePool = _texturePoolCache.FindOrCreate(_channel, poolAddress, _texturePoolMaximumId);
+ _texturePool = texturePool;
+ }
+ }
+
+ if (samplerPool == null)
+ {
+ ulong poolAddress = memoryManager.Translate(_samplerPoolGpuVa);
+
+ if (poolAddress != MemoryManager.PteUnmapped)
+ {
+ samplerPool = _samplerPoolCache.FindOrCreate(_channel, poolAddress, _samplerPoolMaximumId);
+ _samplerPool = samplerPool;
+ }
+ }
+
+ return (texturePool, samplerPool);
+ }
+
+ /// <summary>
+ /// Forces the texture and sampler pools to be re-loaded from the cache on next use.
+ /// </summary>
+ /// <remarks>
+ /// This should be called if the memory mappings change, to ensure the correct pools are being used.
+ /// </remarks>
+ public void ReloadPools()
+ {
+ _samplerPool = null;
+ _texturePool = null;
}
/// <summary>
- /// Disposes all textures and samplers in the cache.
+ /// Force all bound textures and images to be rebound the next time CommitBindings is called.
/// </summary>
- public void Dispose()
+ public void Rebind()
{
- _samplerPool?.Dispose();
+ Array.Clear(_textureState);
+ Array.Clear(_imageState);
}
}
} \ No newline at end of file