Improve Buffer Textures and flush Image Stores (#2088)
* Improve Buffer Textures and flush Image Stores Fixes a number of issues with buffer textures: - Reworked Buffer Textures to create their buffers in the TextureManager, then bind them with the BufferManager later. - Fixes an issue where a buffer texture's buffer could be invalidated after it is bound, but before use. - Fixed width unpacking for large buffer textures. The width is now 32-bit rather than 16. - Force buffer textures to be rebound whenever any buffer is created, as using the handle id wasn't reliable, and the cost of binding isn't too high. Fixes vertex explosions and flickering animations in UE4 games. * Set ImageStore flag... for ImageStore. * Check the offset and size.
This commit is contained in:
parent
da283ff3c3
commit
1623ab524f
12 changed files with 154 additions and 30 deletions
|
@ -303,7 +303,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
// 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.Range.GetSubRange(0).Address, texture.Size, _isCompute);
|
||||
_context.Methods.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, bindingInfo.Format, false);
|
||||
}
|
||||
|
||||
Sampler sampler = _samplerPool.Get(samplerId);
|
||||
|
@ -349,12 +349,26 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
ITexture hostTexture = texture?.GetTargetTexture(bindingInfo.Target);
|
||||
|
||||
bool isStore = bindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
|
||||
|
||||
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.
|
||||
_context.Methods.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, _isCompute);
|
||||
|
||||
Format format = bindingInfo.Format;
|
||||
|
||||
if (format == 0 && texture != null)
|
||||
{
|
||||
format = texture.Format;
|
||||
}
|
||||
|
||||
_context.Methods.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, format, true);
|
||||
}
|
||||
else if (isStore)
|
||||
{
|
||||
texture?.SignalModified();
|
||||
}
|
||||
|
||||
if (_imageState[stageIndex][index].Texture != hostTexture || _rebind)
|
||||
|
|
|
@ -153,6 +153,15 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
return (int)(Word4 & 0xffff) + 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpack the width of a buffer texture.
|
||||
/// </summary>
|
||||
/// <returns>The texture width</returns>
|
||||
public int UnpackBufferTextureWidth()
|
||||
{
|
||||
return (int)((Word4 & 0xffff) | (Word3 << 16)) + 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unpacks the texture sRGB format flag.
|
||||
/// </summary>
|
||||
|
|
|
@ -172,8 +172,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
/// <returns>The texture information</returns>
|
||||
private TextureInfo GetInfo(TextureDescriptor descriptor, out int layerSize)
|
||||
{
|
||||
int width = descriptor.UnpackWidth();
|
||||
int height = descriptor.UnpackHeight();
|
||||
int depthOrLayers = descriptor.UnpackDepth();
|
||||
int levels = descriptor.UnpackLevels();
|
||||
|
||||
|
@ -190,6 +188,9 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
Target target = descriptor.UnpackTextureTarget().Convert((samplesInX | samplesInY) != 1);
|
||||
|
||||
int width = target == Target.TextureBuffer ? descriptor.UnpackBufferTextureWidth() : descriptor.UnpackWidth();
|
||||
int height = descriptor.UnpackHeight();
|
||||
|
||||
// We use 2D targets for 1D textures as that makes texture cache
|
||||
// management easier. We don't know the target for render target
|
||||
// and copies, so those would normally use 2D targets, which are
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue