diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs | 96 |
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; |