diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs | 86 |
1 files changed, 69 insertions, 17 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs index 6c48fc0e..597c527d 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs @@ -11,6 +11,9 @@ namespace Ryujinx.Graphics.Gpu.Image /// </summary> class TextureBindingsManager : IDisposable { + private const int InitialTextureStateSize = 32; + private const int InitialImageStateSize = 8; + private const int HandleHigh = 16; private const int HandleMask = (1 << HandleHigh) - 1; @@ -43,6 +46,9 @@ namespace Ryujinx.Graphics.Gpu.Image private readonly TextureStatePerStage[][] _textureState; private readonly TextureStatePerStage[][] _imageState; + private int[] _textureBindingsCount; + private int[] _imageBindingsCount; + private int _textureBufferIndex; private bool _rebind; @@ -72,6 +78,18 @@ namespace Ryujinx.Graphics.Gpu.Image _textureState = new TextureStatePerStage[stages][]; _imageState = new TextureStatePerStage[stages][]; + _textureBindingsCount = new int[stages]; + _imageBindingsCount = new int[stages]; + + for (int stage = 0; stage < stages; stage++) + { + _textureBindings[stage] = new TextureBindingInfo[InitialTextureStateSize]; + _imageBindings[stage] = new TextureBindingInfo[InitialImageStateSize]; + + _textureState[stage] = new TextureStatePerStage[InitialTextureStateSize]; + _imageState[stage] = new TextureStatePerStage[InitialImageStateSize]; + } + _scales = new float[64]; for (int i = 0; i < 64; i++) @@ -81,25 +99,57 @@ namespace Ryujinx.Graphics.Gpu.Image } /// <summary> - /// Binds textures for a given shader stage. + /// Rents the texture bindings array for a given stage, so that they can be modified. /// </summary> /// <param name="stage">Shader stage number, or 0 for compute shaders</param> - /// <param name="bindings">Texture bindings</param> - public void SetTextures(int stage, TextureBindingInfo[] bindings) + /// <param name="count">The number of bindings needed</param> + /// <returns>The texture bindings array</returns> + public TextureBindingInfo[] RentTextureBindings(int stage, int count) { - _textureBindings[stage] = bindings; - _textureState[stage] = new TextureStatePerStage[bindings.Length]; + if (count > _textureBindings[stage].Length) + { + Array.Resize(ref _textureBindings[stage], count); + Array.Resize(ref _textureState[stage], count); + } + + int toClear = Math.Max(_textureBindingsCount[stage], count); + TextureStatePerStage[] state = _textureState[stage]; + + for (int i = 0; i < toClear; i++) + { + state[i] = new TextureStatePerStage(); + } + + _textureBindingsCount[stage] = count; + + return _textureBindings[stage]; } /// <summary> - /// Binds images for a given shader stage. + /// Rents the image bindings array for a given stage, so that they can be modified. /// </summary> /// <param name="stage">Shader stage number, or 0 for compute shaders</param> - /// <param name="bindings">Image bindings</param> - public void SetImages(int stage, TextureBindingInfo[] bindings) + /// <param name="count">The number of bindings needed</param> + /// <returns>The image bindings array</returns> + public TextureBindingInfo[] RentImageBindings(int stage, int count) { - _imageBindings[stage] = bindings; - _imageState[stage] = new TextureStatePerStage[bindings.Length]; + if (count > _imageBindings[stage].Length) + { + Array.Resize(ref _imageBindings[stage], count); + Array.Resize(ref _imageState[stage], count); + } + + int toClear = Math.Max(_imageBindingsCount[stage], count); + TextureStatePerStage[] state = _imageState[stage]; + + for (int i = 0; i < toClear; i++) + { + state[i] = new TextureStatePerStage(); + } + + _imageBindingsCount[stage] = count; + + return _imageBindings[stage]; } /// <summary> @@ -235,7 +285,7 @@ namespace Ryujinx.Graphics.Gpu.Image { if (_scaleChanged) { - _context.Renderer.Pipeline.UpdateRenderScale(stage, _scales, _textureBindings[stageIndex]?.Length ?? 0, _imageBindings[stageIndex]?.Length ?? 0); + _context.Renderer.Pipeline.UpdateRenderScale(stage, _scales, _textureBindingsCount[stageIndex], _imageBindingsCount[stageIndex]); _scaleChanged = false; } @@ -285,7 +335,8 @@ namespace Ryujinx.Graphics.Gpu.Image /// <param name="stageIndex">The stage number of the specified shader stage</param> private void CommitTextureBindings(TexturePool pool, ShaderStage stage, int stageIndex) { - if (_textureBindings[stageIndex] == null || _textureBindings[stageIndex].Length == 0) + int textureCount = _textureBindingsCount[stageIndex]; + if (textureCount == 0) { return; } @@ -304,7 +355,7 @@ namespace Ryujinx.Graphics.Gpu.Image return; } - for (int index = 0; index < _textureBindings[stageIndex].Length; index++) + for (int index = 0; index < textureCount; index++) { TextureBindingInfo bindingInfo = _textureBindings[stageIndex][index]; @@ -381,21 +432,22 @@ namespace Ryujinx.Graphics.Gpu.Image /// <param name="stageIndex">The stage number of the specified shader stage</param> private void CommitImageBindings(TexturePool pool, ShaderStage stage, int stageIndex) { - if (_imageBindings[stageIndex] == null) + int imageCount = _imageBindingsCount[stageIndex]; + if (imageCount == 0) { return; } - if (pool == null && _imageBindings[stageIndex].Length != 0) + if (pool == null) { Logger.Error?.Print(LogClass.Gpu, $"Shader stage \"{stage}\" uses images, but texture pool was not set."); return; } // Scales for images appear after the texture ones. - int baseScaleIndex = _textureBindings[stageIndex]?.Length ?? 0; + int baseScaleIndex = _textureBindingsCount[stageIndex]; - for (int index = 0; index < _imageBindings[stageIndex].Length; index++) + for (int index = 0; index < imageCount; index++) { TextureBindingInfo bindingInfo = _imageBindings[stageIndex][index]; |