From 3cb1fa0e853efc04cc183d3ee75ec1bbe2c845a4 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 25 Apr 2020 10:02:18 -0300 Subject: Implement texture buffers (#1152) * Implement texture buffers * Throw NotSupportedException where appropriate --- Ryujinx.Graphics.Gpu/Image/Texture.cs | 4 +++- .../Image/TextureBindingsManager.cs | 25 +++++++++++++--------- Ryujinx.Graphics.Gpu/Image/TextureManager.cs | 6 +++++- 3 files changed, 23 insertions(+), 12 deletions(-) (limited to 'Ryujinx.Graphics.Gpu/Image') diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs index ba7dce7b..957c3465 100644 --- a/Ryujinx.Graphics.Gpu/Image/Texture.cs +++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs @@ -295,7 +295,9 @@ namespace Ryujinx.Graphics.Gpu.Image /// public void SynchronizeMemory() { - if (_sequenceNumber == _context.SequenceNumber && _hasData) + // Texture buffers are not handled here, instead they are invalidated (if modified) + // when the texture is bound. This is handled by the buffer manager. + if ((_sequenceNumber == _context.SequenceNumber && _hasData) || Info.Target == Target.TextureBuffer) { return; } diff --git a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs index 7cc7f046..612ec5ca 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureBindingsManager.cs @@ -69,7 +69,6 @@ namespace Ryujinx.Graphics.Gpu.Image public void SetTextures(int stage, TextureBindingInfo[] bindings) { _textureBindings[stage] = bindings; - _textureState[stage] = new TextureStatePerStage[bindings.Length]; } @@ -81,7 +80,6 @@ namespace Ryujinx.Graphics.Gpu.Image public void SetImages(int stage, TextureBindingInfo[] bindings) { _imageBindings[stage] = bindings; - _imageState[stage] = new TextureStatePerStage[bindings.Length]; } @@ -201,7 +199,7 @@ namespace Ryujinx.Graphics.Gpu.Image } else { - packedId = ReadPackedId(stageIndex, binding.Handle); + packedId = ReadPackedId(stageIndex, binding.Handle, _textureBufferIndex); } int textureId = UnpackTextureId(packedId); @@ -227,6 +225,14 @@ namespace Ryujinx.Graphics.Gpu.Image _context.Renderer.Pipeline.SetTexture(index, stage, hostTexture); } + if (hostTexture != null && texture.Info.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. + _context.Methods.BufferManager.SetBufferTextureStorage(hostTexture, texture.Address, texture.Size, _isCompute); + } + Sampler sampler = _samplerPool.Get(samplerId); ISampler hostSampler = sampler?.HostSampler; @@ -258,8 +264,7 @@ namespace Ryujinx.Graphics.Gpu.Image { TextureBindingInfo binding = _imageBindings[stageIndex][index]; - int packedId = ReadPackedId(stageIndex, binding.Handle); - + int packedId = ReadPackedId(stageIndex, binding.Handle, _textureBufferIndex); int textureId = UnpackTextureId(packedId); Texture texture = pool.Get(textureId); @@ -284,8 +289,7 @@ namespace Ryujinx.Graphics.Gpu.Image /// The texture descriptor for the specified texture public TextureDescriptor GetTextureDescriptor(GpuState state, int stageIndex, int handle) { - int packedId = ReadPackedId(stageIndex, handle); - + int packedId = ReadPackedId(stageIndex, handle, state.Get(MethodOffset.TextureBufferIndex)); int textureId = UnpackTextureId(packedId); var poolState = state.Get(MethodOffset.TexturePoolState); @@ -303,8 +307,9 @@ namespace Ryujinx.Graphics.Gpu.Image /// /// The number of the shader stage where the texture is bound /// A word offset of the handle on the buffer (the "fake" shader handle) + /// Index of the constant buffer holding the texture handles /// The packed texture and sampler ID (the real texture handle) - private int ReadPackedId(int stageIndex, int wordOffset) + private int ReadPackedId(int stageIndex, int wordOffset, int textureBufferIndex) { ulong address; @@ -312,11 +317,11 @@ namespace Ryujinx.Graphics.Gpu.Image if (_isCompute) { - address = bufferManager.GetComputeUniformBufferAddress(_textureBufferIndex); + address = bufferManager.GetComputeUniformBufferAddress(textureBufferIndex); } else { - address = bufferManager.GetGraphicsUniformBufferAddress(stageIndex, _textureBufferIndex); + address = bufferManager.GetGraphicsUniformBufferAddress(stageIndex, textureBufferIndex); } address += (uint)wordOffset * 4; diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs index b127690b..600e2f5b 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs @@ -489,7 +489,11 @@ namespace Ryujinx.Graphics.Gpu.Image // Calculate texture sizes, used to find all overlapping textures. SizeInfo sizeInfo; - if (info.IsLinear) + if (info.Target == Target.TextureBuffer) + { + sizeInfo = new SizeInfo(info.Width * info.FormatInfo.BytesPerPixel); + } + else if (info.IsLinear) { sizeInfo = SizeCalculator.GetLinearTextureSize( info.Stride, -- cgit v1.2.3